OSDN Git Service

Merge branch 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Sat, 5 May 2007 21:55:20 +0000 (14:55 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Sat, 5 May 2007 21:55:20 +0000 (14:55 -0700)
* 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6: (231 commits)
  [PATCH] i386: Don't delete cpu_devs data to identify different x86 types in late_initcall
  [PATCH] i386: type may be unused
  [PATCH] i386: Some additional chipset register values validation.
  [PATCH] i386: Add missing !X86_PAE dependincy to the 2G/2G split.
  [PATCH] x86-64: Don't exclude asm-offsets.c in Documentation/dontdiff
  [PATCH] i386: avoid redundant preempt_disable in __unlazy_fpu
  [PATCH] i386: white space fixes in i387.h
  [PATCH] i386: Drop noisy e820 debugging printks
  [PATCH] x86-64: Fix allnoconfig error in genapic_flat.c
  [PATCH] x86-64: Shut up warnings for vfat compat ioctls on other file systems
  [PATCH] x86-64: Share identical video.S between i386 and x86-64
  [PATCH] x86-64: Remove CONFIG_REORDER
  [PATCH] x86-64: Print type and size correctly for unknown compat ioctls
  [PATCH] i386: Remove copy_*_user BUG_ONs for (size < 0)
  [PATCH] i386: Little cleanups in smpboot.c
  [PATCH] x86-64: Don't enable NUMA for a single node in K8 NUMA scanning
  [PATCH] x86: Use RDTSCP for synchronous get_cycles if possible
  [PATCH] i386: Add X86_FEATURE_RDTSCP
  [PATCH] i386: Implement X86_FEATURE_SYNC_RDTSC on i386
  [PATCH] i386: Implement alternative_io for i386
  ...

Fix up trivial conflict in include/linux/highmem.h manually.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
862 files changed:
Documentation/driver-model/devres.txt
Documentation/feature-removal-schedule.txt
Documentation/i2c/busses/i2c-nforce2
Documentation/i2c/porting-clients
Documentation/i2c/summary
Documentation/i2c/writing-clients
Documentation/input/input-programming.txt
Documentation/pci.txt
Documentation/power/pci.txt
Documentation/scsi/aacraid.txt
Documentation/scsi/ncr53c8xx.txt
Documentation/usb/usb-serial.txt
MAINTAINERS
arch/alpha/kernel/err_common.c
arch/alpha/kernel/err_ev6.c
arch/alpha/kernel/err_ev7.c
arch/arm/Kconfig
arch/arm/mach-omap1/pm.c
arch/i386/Kconfig
arch/i386/kernel/cpu/cpufreq/longhaul.c
arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
arch/i386/kernel/cpu/cpufreq/powernow-k8.c
arch/i386/kernel/cpu/cpufreq/powernow-k8.h
arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
arch/i386/kernel/i8253.c
arch/i386/kernel/io_apic.c
arch/i386/mach-voyager/setup.c
arch/i386/mach-voyager/voyager_cat.c
arch/i386/mach-voyager/voyager_smp.c
arch/i386/mach-voyager/voyager_thread.c
arch/i386/pci/fixup.c
arch/i386/pci/i386.c
arch/ia64/Kconfig
arch/ia64/sn/kernel/huberror.c
arch/ia64/sn/kernel/msi_sn.c
arch/ia64/sn/kernel/xpnet.c
arch/m68k/Kconfig
arch/m68k/Makefile
arch/m68k/amiga/config.c
arch/m68k/atari/Makefile
arch/m68k/atari/atakeyb.c [new file with mode: 0644]
arch/m68k/atari/config.c
arch/m68k/atari/debug.c
arch/m68k/kernel/entry.S
arch/m68k/kernel/head.S
arch/m68k/kernel/setup.c
arch/m68k/lib/checksum.c
arch/m68k/mac/baboon.c
arch/m68k/mac/config.c
arch/m68k/mac/debug.c
arch/m68k/mac/oss.c
arch/m68k/mac/psc.c
arch/m68k/mac/via.c
arch/m68k/q40/config.c
arch/m68k/sun3/sun3ints.c
arch/m68k/sun3x/prom.c
arch/m68knommu/kernel/dma.c
arch/mips/cobalt/Makefile
arch/mips/cobalt/buttons.c [new file with mode: 0644]
arch/mips/lib/iomap.c
arch/powerpc/kernel/pci_64.c
arch/powerpc/kernel/vio.c
arch/powerpc/platforms/powermac/cpufreq_32.c
arch/powerpc/platforms/pseries/power.c
arch/powerpc/platforms/pseries/ras.c
arch/ppc/8260_io/enet.c
arch/ppc/8260_io/fcc_enet.c
arch/ppc/8xx_io/enet.c
arch/ppc/syslib/ppc4xx_sgdma.c
arch/s390/appldata/appldata_net_sum.c
arch/s390/crypto/aes_s390.c
arch/s390/kernel/ipl.c
arch/s390/kernel/kprobes.c
arch/s390/kernel/setup.c
arch/s390/mm/fault.c
arch/sh64/mach-cayman/iomap.c
arch/sparc64/Kconfig
arch/sparc64/kernel/pci.c
arch/sparc64/kernel/pci_sun4v.c
arch/sparc64/solaris/ioctl.c
arch/x86_64/Kconfig
arch/x86_64/kernel/cpufreq/Kconfig
arch/x86_64/kernel/io_apic.c
arch/xtensa/kernel/xtensa_ksyms.c
arch/xtensa/platform-iss/setup.c
block/genhd.c
block/ll_rw_blk.c
block/scsi_ioctl.c
crypto/Kconfig
crypto/Makefile
crypto/ablkcipher.c [new file with mode: 0644]
crypto/algapi.c
crypto/blkcipher.c
crypto/cbc.c
crypto/cryptd.c [new file with mode: 0644]
crypto/cryptomgr.c
crypto/ecb.c
crypto/hash.c
crypto/hmac.c
crypto/lrw.c
crypto/pcbc.c
crypto/tcrypt.c
crypto/xcbc.c
drivers/Makefile
drivers/acpi/processor_perflib.c
drivers/atm/adummy.c
drivers/base/base.h
drivers/base/bus.c
drivers/base/class.c
drivers/base/core.c
drivers/base/dd.c
drivers/base/firmware.c
drivers/base/platform.c
drivers/base/power/shutdown.c
drivers/base/sys.c
drivers/block/aoe/aoecmd.c
drivers/char/agp/ali-agp.c
drivers/char/agp/alpha-agp.c
drivers/char/agp/generic.c
drivers/char/agp/intel-agp.c
drivers/char/agp/nvidia-agp.c
drivers/char/agp/parisc-agp.c
drivers/char/agp/sgi-agp.c
drivers/char/agp/sis-agp.c
drivers/char/agp/sworks-agp.c
drivers/char/hw_random/via-rng.c
drivers/char/keyboard.c
drivers/char/pcmcia/synclink_cs.c
drivers/char/tpm/tpm.h
drivers/char/watchdog/sc1200wdt.c
drivers/char/watchdog/scx200_wdt.c
drivers/cpufreq/Kconfig
drivers/cpufreq/cpufreq.c
drivers/crypto/Kconfig
drivers/crypto/Makefile
drivers/crypto/padlock.c [deleted file]
drivers/firmware/efivars.c
drivers/i2c/Kconfig
drivers/i2c/Makefile
drivers/i2c/algos/Kconfig
drivers/i2c/algos/i2c-algo-bit.c
drivers/i2c/algos/i2c-algo-sgi.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-ali1535.c
drivers/i2c/busses/i2c-ali15x3.c
drivers/i2c/busses/i2c-amd8111.c
drivers/i2c/busses/i2c-at91.c
drivers/i2c/busses/i2c-bfin-twi.c [new file with mode: 0644]
drivers/i2c/busses/i2c-elektor.c
drivers/i2c/busses/i2c-gpio.c [new file with mode: 0644]
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-isa.c
drivers/i2c/busses/i2c-ixp2000.c
drivers/i2c/busses/i2c-ixp4xx.c
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-nforce2.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-parport-light.c
drivers/i2c/busses/i2c-parport.c
drivers/i2c/busses/i2c-pasemi.c
drivers/i2c/busses/i2c-pca-isa.c
drivers/i2c/busses/i2c-piix4.c
drivers/i2c/busses/i2c-pxa.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-simtec.c [new file with mode: 0644]
drivers/i2c/busses/i2c-sis96x.c
drivers/i2c/busses/i2c-tiny-usb.c [new file with mode: 0644]
drivers/i2c/busses/i2c-viapro.c
drivers/i2c/busses/scx200_acb.c
drivers/i2c/chips/Kconfig
drivers/i2c/i2c-boardinfo.c [new file with mode: 0644]
drivers/i2c/i2c-core.c
drivers/i2c/i2c-core.h [new file with mode: 0644]
drivers/ide/cris/ide-cris.c
drivers/ide/legacy/ide-cs.c
drivers/ide/pci/aec62xx.c
drivers/ide/pci/alim15x3.c
drivers/ide/pci/cmd64x.c
drivers/ide/pci/hpt366.c
drivers/ide/pci/it821x.c
drivers/ide/pci/pdc202xx_new.c
drivers/ide/pci/siimage.c
drivers/ide/pci/sl82c105.c
drivers/ieee1394/hosts.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/iwcm.c
drivers/infiniband/core/mad_priv.h
drivers/infiniband/core/multicast.c
drivers/infiniband/core/sa_query.c
drivers/infiniband/core/user_mad.c
drivers/infiniband/hw/ipath/ipath_fs.c
drivers/infiniband/hw/ipath/ipath_layer.c
drivers/infiniband/hw/ipath/ipath_stats.c
drivers/infiniband/hw/ipath/ipath_sysfs.c
drivers/infiniband/hw/mthca/mthca_memfree.h
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/iser/iser_initiator.c
drivers/input/Makefile
drivers/input/evbug.c
drivers/input/evdev.c
drivers/input/input.c
drivers/input/joydev.c
drivers/input/joystick/a3d.c
drivers/input/joystick/adi.c
drivers/input/joystick/analog.c
drivers/input/joystick/cobra.c
drivers/input/joystick/db9.c
drivers/input/joystick/gamecon.c
drivers/input/joystick/gf2k.c
drivers/input/joystick/grip.c
drivers/input/joystick/grip_mp.c
drivers/input/joystick/guillemot.c
drivers/input/joystick/iforce/iforce-ff.c
drivers/input/joystick/iforce/iforce-main.c
drivers/input/joystick/iforce/iforce-packets.c
drivers/input/joystick/iforce/iforce-serio.c
drivers/input/joystick/iforce/iforce-usb.c
drivers/input/joystick/iforce/iforce.h
drivers/input/joystick/interact.c
drivers/input/joystick/magellan.c
drivers/input/joystick/sidewinder.c
drivers/input/joystick/spaceball.c
drivers/input/joystick/spaceorb.c
drivers/input/joystick/stinger.c
drivers/input/joystick/tmdc.c
drivers/input/joystick/turbografx.c
drivers/input/joystick/twidjoy.c
drivers/input/joystick/warrior.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/keyboard/aaed2000_kbd.c
drivers/input/keyboard/atakbd.c [new file with mode: 0644]
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/corgikbd.c
drivers/input/keyboard/gpio_keys.c
drivers/input/keyboard/hil_kbd.c
drivers/input/keyboard/hilkbd.c
drivers/input/keyboard/lkkbd.c
drivers/input/keyboard/locomokbd.c
drivers/input/keyboard/newtonkbd.c
drivers/input/keyboard/omap-keypad.c
drivers/input/keyboard/pxa27x_keyboard.c [new file with mode: 0644]
drivers/input/keyboard/spitzkbd.c
drivers/input/keyboard/stowaway.c
drivers/input/keyboard/sunkbd.c
drivers/input/keyboard/xtkbd.c
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/cobalt_btns.c [new file with mode: 0644]
drivers/input/misc/input-polldev.c [new file with mode: 0644]
drivers/input/misc/ixp4xx-beeper.c
drivers/input/misc/m68kspkr.c
drivers/input/misc/pcspkr.c
drivers/input/misc/sparcspkr.c
drivers/input/misc/uinput.c
drivers/input/misc/wistron_btns.c
drivers/input/mouse/Kconfig
drivers/input/mouse/Makefile
drivers/input/mouse/alps.c
drivers/input/mouse/alps.h
drivers/input/mouse/atarimouse.c [new file with mode: 0644]
drivers/input/mouse/hil_ptr.c
drivers/input/mouse/lifebook.c
drivers/input/mouse/lifebook.h
drivers/input/mouse/logips2pp.c
drivers/input/mouse/logips2pp.h
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/psmouse.h
drivers/input/mouse/sermouse.c
drivers/input/mouse/synaptics.c
drivers/input/mouse/synaptics.h
drivers/input/mouse/touchkit_ps2.c [new file with mode: 0644]
drivers/input/mouse/touchkit_ps2.h [new file with mode: 0644]
drivers/input/mouse/trackpoint.h
drivers/input/mouse/vsxxxaa.c
drivers/input/mousedev.c
drivers/input/power.c [deleted file]
drivers/input/serio/hil_mlc.c
drivers/input/serio/hp_sdc.c
drivers/input/serio/hp_sdc_mlc.c
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/i8042.c
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/corgi_ts.c
drivers/input/touchscreen/elo.c
drivers/input/touchscreen/gunze.c
drivers/input/touchscreen/h3600_ts_input.c
drivers/input/touchscreen/mtouch.c
drivers/input/touchscreen/penmount.c
drivers/input/touchscreen/touchright.c
drivers/input/touchscreen/touchwin.c
drivers/input/touchscreen/ucb1400_ts.c
drivers/input/tsdev.c
drivers/isdn/hisax/netjet.c
drivers/isdn/hysdn/hysdn_proclog.c
drivers/macintosh/therm_windtunnel.c
drivers/macintosh/via-cuda.c
drivers/macintosh/via-macii.c
drivers/macintosh/via-pmu68k.c
drivers/media/dvb/b2c2/flexcop-i2c.c
drivers/media/dvb/cinergyT2/cinergyT2.c
drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
drivers/media/dvb/frontends/dibx000_common.c
drivers/media/video/adv7170.c
drivers/media/video/adv7175.c
drivers/media/video/bt819.c
drivers/media/video/bt856.c
drivers/media/video/bt866.c
drivers/media/video/cx2341x.c
drivers/media/video/cx88/cx88-tvaudio.c
drivers/media/video/em28xx/em28xx-cards.c
drivers/media/video/ovcamchip/ovcamchip_priv.h
drivers/media/video/saa7111.c
drivers/media/video/saa7114.c
drivers/media/video/saa711x.c
drivers/media/video/saa7185.c
drivers/media/video/usbvision/usbvision-cards.c
drivers/message/fusion/mptbase.c
drivers/message/fusion/mptbase.h
drivers/message/fusion/mptscsih.c
drivers/message/fusion/mptspi.c
drivers/misc/hdpuftrs/hdpu_cpustate.c
drivers/misc/hdpuftrs/hdpu_nexus.c
drivers/misc/tifm_7xx1.c
drivers/misc/tifm_core.c
drivers/mmc/Kconfig
drivers/mmc/Makefile
drivers/mmc/card/Kconfig [new file with mode: 0644]
drivers/mmc/card/Makefile [new file with mode: 0644]
drivers/mmc/card/block.c [moved from drivers/mmc/mmc_block.c with 93% similarity]
drivers/mmc/card/queue.c [moved from drivers/mmc/mmc_queue.c with 96% similarity]
drivers/mmc/card/queue.h [moved from drivers/mmc/mmc_queue.h with 100% similarity]
drivers/mmc/core/Kconfig [new file with mode: 0644]
drivers/mmc/core/Makefile [new file with mode: 0644]
drivers/mmc/core/core.c [new file with mode: 0644]
drivers/mmc/core/core.h [new file with mode: 0644]
drivers/mmc/core/mmc.c [new file with mode: 0644]
drivers/mmc/core/mmc_ops.c [new file with mode: 0644]
drivers/mmc/core/mmc_ops.h [new file with mode: 0644]
drivers/mmc/core/sd.c [new file with mode: 0644]
drivers/mmc/core/sd_ops.c [new file with mode: 0644]
drivers/mmc/core/sd_ops.h [new file with mode: 0644]
drivers/mmc/core/sysfs.c [moved from drivers/mmc/mmc_sysfs.c with 97% similarity]
drivers/mmc/core/sysfs.h [moved from drivers/mmc/mmc.h with 86% similarity]
drivers/mmc/host/Kconfig [new file with mode: 0644]
drivers/mmc/host/Makefile [new file with mode: 0644]
drivers/mmc/host/at91_mci.c [moved from drivers/mmc/at91_mci.c with 99% similarity]
drivers/mmc/host/au1xmmc.c [moved from drivers/mmc/au1xmmc.c with 99% similarity]
drivers/mmc/host/au1xmmc.h [moved from drivers/mmc/au1xmmc.h with 100% similarity]
drivers/mmc/host/imxmmc.c [moved from drivers/mmc/imxmmc.c with 99% similarity]
drivers/mmc/host/imxmmc.h [moved from drivers/mmc/imxmmc.h with 100% similarity]
drivers/mmc/host/mmci.c [moved from drivers/mmc/mmci.c with 99% similarity]
drivers/mmc/host/mmci.h [moved from drivers/mmc/mmci.h with 100% similarity]
drivers/mmc/host/omap.c [moved from drivers/mmc/omap.c with 98% similarity]
drivers/mmc/host/pxamci.c [moved from drivers/mmc/pxamci.c with 99% similarity]
drivers/mmc/host/pxamci.h [moved from drivers/mmc/pxamci.h with 100% similarity]
drivers/mmc/host/sdhci.c [moved from drivers/mmc/sdhci.c with 97% similarity]
drivers/mmc/host/sdhci.h [moved from drivers/mmc/sdhci.h with 98% similarity]
drivers/mmc/host/tifm_sd.c [new file with mode: 0644]
drivers/mmc/host/wbsd.c [moved from drivers/mmc/wbsd.c with 93% similarity]
drivers/mmc/host/wbsd.h [moved from drivers/mmc/wbsd.h with 95% similarity]
drivers/mmc/mmc.c [deleted file]
drivers/mmc/tifm_sd.c [deleted file]
drivers/mtd/devices/doc2000.c
drivers/mtd/devices/doc2001.c
drivers/mtd/devices/doc2001plus.c
drivers/mtd/devices/docecc.c
drivers/mtd/inftlmount.c
drivers/mtd/nand/cs553x_nand.c
drivers/mtd/nftlcore.c
drivers/net/7990.c
drivers/net/Kconfig
drivers/net/Space.c
drivers/net/a2065.c
drivers/net/ariadne.c
drivers/net/atl1/atl1_param.c
drivers/net/au1000_eth.c
drivers/net/bnx2.c
drivers/net/bnx2.h
drivers/net/bnx2_fw.h
drivers/net/bnx2_fw2.h
drivers/net/fec_8xx/fec_main.c
drivers/net/fec_8xx/fec_mii.c
drivers/net/fs_enet/fs_enet-main.c
drivers/net/fs_enet/mac-fcc.c
drivers/net/fs_enet/mac-fec.c
drivers/net/fs_enet/mac-scc.c
drivers/net/fs_enet/mii-bitbang.c
drivers/net/fs_enet/mii-fec.c
drivers/net/ibm_emac/ibm_emac_core.c
drivers/net/ixgb/ixgb_osdep.h
drivers/net/jazzsonic.c
drivers/net/lasi_82596.c
drivers/net/mac8390.c
drivers/net/mac89x0.c
drivers/net/macmace.c
drivers/net/macsonic.c
drivers/net/sonic.c
drivers/net/sun3_82586.c
drivers/net/tg3.c
drivers/net/tg3.h
drivers/net/tokenring/madgemc.c
drivers/net/tokenring/smctr.c
drivers/net/tulip/21142.c
drivers/net/tulip/pnic.c
drivers/net/tulip/pnic2.c
drivers/net/tulip/timer.c
drivers/net/tulip/tulip.h
drivers/net/wan/lmc/lmc_media.c
drivers/net/wan/lmc/lmc_proto.c
drivers/net/wan/pc300_tty.c
drivers/net/wireless/strip.c
drivers/parisc/hppb.c
drivers/parisc/led.c
drivers/parisc/pdc_stable.c
drivers/pci/Kconfig
drivers/pci/bus.c
drivers/pci/hotplug/Kconfig
drivers/pci/hotplug/acpiphp_ibm.c
drivers/pci/hotplug/cpcihp_zt5550.c
drivers/pci/hotplug/fakephp.c
drivers/pci/hotplug/pci_hotplug_core.c
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp_core.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/hotplug/rpadlpar_core.c
drivers/pci/hotplug/rpaphp.h
drivers/pci/hotplug/rpaphp_core.c
drivers/pci/hotplug/rpaphp_pci.c
drivers/pci/hotplug/rpaphp_slot.c
drivers/pci/hotplug/shpchp.h
drivers/pci/hotplug/shpchp_core.c
drivers/pci/hotplug/shpchp_ctrl.c
drivers/pci/msi.c
drivers/pci/pci-driver.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/search.c
drivers/pci/setup-bus.c
drivers/pci/setup-res.c
drivers/pcmcia/cs.c
drivers/pcmcia/socket_sysfs.c
drivers/ps3/ps3av.c
drivers/ps3/ps3av_cmd.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_fba.c
drivers/s390/block/dasd_int.h
drivers/s390/char/tape.h
drivers/s390/char/tape_3590.c
drivers/s390/char/tape_3590.h
drivers/s390/char/tape_core.c
drivers/s390/cio/qdio.c
drivers/s390/cio/qdio.h
drivers/s390/net/qeth.h
drivers/s390/net/qeth_main.c
drivers/s390/net/qeth_mpc.h
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_fsf.c
drivers/sbus/sbus.c
drivers/scsi/BusLogic.c
drivers/scsi/Kconfig
drivers/scsi/Makefile
drivers/scsi/aacraid/aachba.c
drivers/scsi/aacraid/aacraid.h
drivers/scsi/aacraid/commctrl.c
drivers/scsi/aacraid/comminit.c
drivers/scsi/aacraid/commsup.c
drivers/scsi/aacraid/dpcsup.c
drivers/scsi/aacraid/linit.c
drivers/scsi/aacraid/nark.c
drivers/scsi/aacraid/rkt.c
drivers/scsi/aacraid/rx.c
drivers/scsi/aacraid/sa.c
drivers/scsi/aha1542.c
drivers/scsi/aic7xxx/Kconfig.aic79xx
drivers/scsi/aic7xxx/Kconfig.aic7xxx
drivers/scsi/aic7xxx/aic79xx_osm.c
drivers/scsi/aic7xxx/aic79xx_osm.h
drivers/scsi/aic7xxx/aic7xxx.h
drivers/scsi/aic7xxx/aic7xxx_core.c
drivers/scsi/aic94xx/aic94xx_scb.c
drivers/scsi/arcmsr/arcmsr_attr.c
drivers/scsi/atari_NCR5380.c
drivers/scsi/atari_scsi.c
drivers/scsi/atari_scsi.h
drivers/scsi/constants.c
drivers/scsi/dpt/dpti_i2o.h
drivers/scsi/dpt/dpti_ioctl.h
drivers/scsi/dpt/dptsig.h
drivers/scsi/dpt_i2o.c
drivers/scsi/eata_generic.h
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/ibmvscsi/ibmvscsi.h
drivers/scsi/ibmvscsi/ibmvstgt.c
drivers/scsi/ipr.c
drivers/scsi/ipr.h
drivers/scsi/iscsi_tcp.c
drivers/scsi/libiscsi.c
drivers/scsi/libsas/sas_expander.c
drivers/scsi/libsrp.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/megaraid.c
drivers/scsi/osst.c
drivers/scsi/pci2000.h [deleted file]
drivers/scsi/pcmcia/Kconfig
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_sup.c
drivers/scsi/qla2xxx/qla_version.h
drivers/scsi/scsi.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/scsi_tgt_if.c
drivers/scsi/scsi_tgt_lib.c
drivers/scsi/scsi_tgt_priv.h
drivers/scsi/scsi_transport_fc.c
drivers/scsi/scsi_transport_iscsi.c
drivers/scsi/sd.c
drivers/scsi/sg.c
drivers/scsi/sr.c
drivers/scsi/st.c
drivers/scsi/tmscsim.c
drivers/usb/input/Makefile
drivers/usb/input/acecad.c
drivers/usb/input/aiptek.c
drivers/usb/input/appletouch.c
drivers/usb/input/ati_remote.c
drivers/usb/input/ati_remote2.c
drivers/usb/input/gtco.c
drivers/usb/input/itmtouch.c [deleted file]
drivers/usb/input/kbtab.c
drivers/usb/input/keyspan_remote.c
drivers/usb/input/mtouchusb.c [deleted file]
drivers/usb/input/powermate.c
drivers/usb/input/touchkitusb.c [deleted file]
drivers/usb/input/usbtouchscreen.c
drivers/usb/input/wacom_sys.c
drivers/usb/input/xpad.c
drivers/usb/input/yealink.c
drivers/usb/net/kaweth.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/atafb.c
drivers/video/atafb.h [new file with mode: 0644]
drivers/video/atafb_iplan2p2.c [new file with mode: 0644]
drivers/video/atafb_iplan2p4.c [new file with mode: 0644]
drivers/video/atafb_iplan2p8.c [new file with mode: 0644]
drivers/video/atafb_mfb.c [new file with mode: 0644]
drivers/video/atafb_utils.h [new file with mode: 0644]
drivers/video/aty/radeon_i2c.c
drivers/video/g364fb.c
drivers/video/intelfb/intelfb_i2c.c
drivers/video/matrox/i2c-matroxfb.c
drivers/video/platinumfb.c
drivers/video/ps3fb.c
drivers/video/stifb.c
drivers/video/valkyriefb.c
drivers/zorro/proc.c
drivers/zorro/zorro-sysfs.c
drivers/zorro/zorro.c
fs/Kconfig
fs/afs/Makefile
fs/afs/callback.c
fs/afs/cmservice.c
fs/afs/fsclient.c
fs/afs/internal.h
fs/afs/main.c
fs/afs/netdevices.c [new file with mode: 0644]
fs/afs/super.c
fs/afs/use-rtnetlink.c [deleted file]
fs/afs/vlocation.c
fs/configfs/mount.c
fs/debugfs/inode.c
fs/dlm/lockspace.c
fs/ecryptfs/main.c
fs/fuse/inode.c
fs/gfs2/locking/dlm/sysfs.c
fs/gfs2/sys.c
fs/lockd/mon.c
fs/lockd/xdr.c
fs/lockd/xdr4.c
fs/nfs/client.c
fs/nfs/dir.c
fs/nfs/direct.c
fs/nfs/internal.h
fs/nfs/mount_clnt.c
fs/nfs/nfs2xdr.c
fs/nfs/nfs3xdr.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
fs/nfs/nfsroot.c
fs/nfs/pagelist.c
fs/nfs/read.c
fs/nfs/super.c
fs/nfs/write.c
fs/nfsd/nfs4callback.c
fs/ocfs2/alloc.c
fs/ocfs2/aops.c
fs/ocfs2/cluster/heartbeat.c
fs/ocfs2/cluster/masklog.c
fs/ocfs2/cluster/masklog.h
fs/ocfs2/cluster/sys.c
fs/ocfs2/cluster/tcp.c
fs/ocfs2/dir.c
fs/ocfs2/dlm/dlmast.c
fs/ocfs2/dlm/dlmrecovery.c
fs/ocfs2/dlm/dlmthread.c
fs/ocfs2/dlmglue.c
fs/ocfs2/dlmglue.h
fs/ocfs2/export.c
fs/ocfs2/file.c
fs/ocfs2/file.h
fs/ocfs2/inode.c
fs/ocfs2/inode.h
fs/ocfs2/ioctl.c
fs/ocfs2/ioctl.h
fs/ocfs2/journal.c
fs/ocfs2/namei.c
fs/ocfs2/ocfs2.h
fs/ocfs2/ocfs2_fs.h
fs/ocfs2/suballoc.c
fs/ocfs2/super.c
fs/partitions/check.c
fs/sysfs/bin.c
fs/sysfs/file.c
include/acpi/acpi_bus.h
include/asm-alpha/scatterlist.h
include/asm-arm/arch-imx/mmc.h
include/asm-arm/arch-ixp4xx/dma.h
include/asm-arm/arch-pxa/mmc.h
include/asm-arm/arch-pxa/pxa27x_keyboard.h [new file with mode: 0644]
include/asm-arm/mach/mmc.h
include/asm-avr32/scatterlist.h
include/asm-frv/scatterlist.h
include/asm-h8300/scatterlist.h
include/asm-i386/agp.h
include/asm-i386/scatterlist.h
include/asm-i386/voyager.h
include/asm-ia64/scatterlist.h
include/asm-m32r/scatterlist.h
include/asm-m68k/adb.h [deleted file]
include/asm-m68k/atarikb.h
include/asm-m68knommu/scatterlist.h
include/asm-mips/scatterlist.h
include/asm-parisc/scatterlist.h
include/asm-powerpc/ps3av.h
include/asm-s390/ccwdev.h
include/asm-s390/elf.h
include/asm-s390/kdebug.h
include/asm-s390/kprobes.h
include/asm-s390/lowcore.h
include/asm-sh/scatterlist.h
include/asm-sh64/scatterlist.h
include/asm-sparc64/scatterlist.h
include/asm-v850/scatterlist.h
include/asm-x86_64/agp.h
include/asm-x86_64/scatterlist.h
include/asm-xtensa/scatterlist.h
include/crypto/algapi.h
include/linux/cpufreq.h
include/linux/crypto.h
include/linux/device.h
include/linux/ethtool.h
include/linux/fs.h
include/linux/gpio_keys.h
include/linux/highmem.h
include/linux/hp_sdc.h
include/linux/i2c-algo-bit.h
include/linux/i2c-gpio.h [new file with mode: 0644]
include/linux/i2c-id.h
include/linux/i2c.h
include/linux/ide.h
include/linux/ieee80211.h [new file with mode: 0644]
include/linux/input-polldev.h [new file with mode: 0644]
include/linux/input.h
include/linux/interrupt.h
include/linux/kobject.h
include/linux/lockd/lockd.h
include/linux/mmc/card.h
include/linux/mmc/core.h [new file with mode: 0644]
include/linux/mmc/host.h
include/linux/mmc/mmc.h
include/linux/mmc/protocol.h [deleted file]
include/linux/mmc/sd.h [new file with mode: 0644]
include/linux/module.h
include/linux/msi.h
include/linux/netdevice.h
include/linux/netfilter/nf_conntrack_proto_gre.h
include/linux/netfilter_bridge.h
include/linux/netlink.h
include/linux/nfs_fs.h
include/linux/nfs_mount.h
include/linux/nfs_page.h
include/linux/nubus.h
include/linux/parser.h
include/linux/pci.h
include/linux/pci_hotplug.h
include/linux/pci_ids.h
include/linux/skbuff.h
include/linux/sunrpc/clnt.h
include/linux/sunrpc/debug.h
include/linux/sunrpc/msg_prot.h
include/linux/sunrpc/sched.h
include/linux/sunrpc/xprt.h
include/linux/tifm.h
include/linux/writeback.h
include/linux/xfrm.h
include/media/ovcamchip.h
include/media/tuner.h
include/net/ipv6.h
include/net/iucv/af_iucv.h
include/net/mac80211.h [new file with mode: 0644]
include/net/sctp/command.h
include/net/sctp/sctp.h
include/net/sctp/structs.h
include/net/tcp.h
include/net/xfrm.h
include/rdma/ib_mad.h
include/scsi/iscsi_proto.h
include/scsi/scsi.h
include/scsi/scsi_cmnd.h
include/scsi/scsi_dbg.h
include/scsi/scsi_device.h
include/scsi/scsi_host.h
include/scsi/scsi_tgt_if.h
include/scsi/scsi_transport_fc.h
include/scsi/sd.h [new file with mode: 0644]
kernel/irq/chip.c
kernel/ksysfs.c
kernel/module.c
kernel/params.c
kernel/power/disk.c
kernel/power/main.c
kernel/power/power.h
lib/iomap.c
lib/kobject.c
lib/parser.c
net/8021q/vlan.c
net/8021q/vlanproc.c
net/Kconfig
net/Makefile
net/bridge/br_if.c
net/bridge/br_ioctl.c
net/bridge/br_netfilter.c
net/bridge/br_netlink.c
net/core/dev.c
net/core/dev_mcast.c
net/core/rtnetlink.c
net/decnet/af_decnet.c
net/decnet/dn_dev.c
net/decnet/dn_fib.c
net/decnet/dn_route.c
net/ipv4/devinet.c
net/ipv4/igmp.c
net/ipv4/ipconfig.c
net/ipv4/netfilter/nf_nat_proto_gre.c
net/ipv4/netfilter/nf_nat_rule.c
net/ipv4/netfilter/nf_nat_sip.c
net/ipv4/tcp.c
net/ipv4/tcp_highspeed.c
net/ipv4/tcp_yeah.h [deleted file]
net/ipv6/addrconf.c
net/ipv6/anycast.c
net/ipv6/mcast.c
net/iucv/af_iucv.c
net/iucv/iucv.c
net/llc/llc_core.c
net/mac80211/Kconfig [new file with mode: 0644]
net/mac80211/Makefile [new file with mode: 0644]
net/mac80211/aes_ccm.c [new file with mode: 0644]
net/mac80211/aes_ccm.h [new file with mode: 0644]
net/mac80211/debugfs.c [new file with mode: 0644]
net/mac80211/debugfs.h [new file with mode: 0644]
net/mac80211/debugfs_key.c [new file with mode: 0644]
net/mac80211/debugfs_key.h [new file with mode: 0644]
net/mac80211/debugfs_netdev.c [new file with mode: 0644]
net/mac80211/debugfs_netdev.h [new file with mode: 0644]
net/mac80211/debugfs_sta.c [new file with mode: 0644]
net/mac80211/debugfs_sta.h [new file with mode: 0644]
net/mac80211/hostapd_ioctl.h [new file with mode: 0644]
net/mac80211/ieee80211.c [new file with mode: 0644]
net/mac80211/ieee80211_cfg.c [new file with mode: 0644]
net/mac80211/ieee80211_cfg.h [new file with mode: 0644]
net/mac80211/ieee80211_common.h [new file with mode: 0644]
net/mac80211/ieee80211_i.h [new file with mode: 0644]
net/mac80211/ieee80211_iface.c [new file with mode: 0644]
net/mac80211/ieee80211_ioctl.c [new file with mode: 0644]
net/mac80211/ieee80211_key.h [new file with mode: 0644]
net/mac80211/ieee80211_led.c [new file with mode: 0644]
net/mac80211/ieee80211_led.h [new file with mode: 0644]
net/mac80211/ieee80211_rate.c [new file with mode: 0644]
net/mac80211/ieee80211_rate.h [new file with mode: 0644]
net/mac80211/ieee80211_sta.c [new file with mode: 0644]
net/mac80211/michael.c [new file with mode: 0644]
net/mac80211/michael.h [new file with mode: 0644]
net/mac80211/rc80211_simple.c [new file with mode: 0644]
net/mac80211/sta_info.c [new file with mode: 0644]
net/mac80211/sta_info.h [new file with mode: 0644]
net/mac80211/tkip.c [new file with mode: 0644]
net/mac80211/tkip.h [new file with mode: 0644]
net/mac80211/wep.c [new file with mode: 0644]
net/mac80211/wep.h [new file with mode: 0644]
net/mac80211/wme.c [new file with mode: 0644]
net/mac80211/wme.h [new file with mode: 0644]
net/mac80211/wpa.c [new file with mode: 0644]
net/mac80211/wpa.h [new file with mode: 0644]
net/netlink/af_netlink.c
net/netrom/nr_route.c
net/rose/rose_route.c
net/rxrpc/Kconfig
net/rxrpc/ar-ack.c
net/rxrpc/ar-error.c
net/rxrpc/ar-output.c
net/rxrpc/ar-peer.c
net/sched/sch_api.c
net/sctp/associola.c
net/sctp/ipv6.c
net/sctp/protocol.c
net/sctp/sm_make_chunk.c
net/sctp/sm_sideeffect.c
net/sctp/sm_statefuns.c
net/sctp/socket.c
net/sunrpc/Makefile
net/sunrpc/auth_gss/gss_spkm3_seal.c
net/sunrpc/clnt.c
net/sunrpc/pmap_clnt.c [deleted file]
net/sunrpc/rpcb_clnt.c [new file with mode: 0644]
net/sunrpc/sched.c
net/sunrpc/svc.c
net/sunrpc/xprt.c
net/sunrpc/xprtsock.c
net/tipc/eth_media.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
net/xfrm/xfrm_user.c
security/inode.c
sound/core/init.c
sound/oss/au1550_ac97.c
sound/oss/dmasound/tas_ioctl.h
sound/oss/soundcard.c
sound/pci/ca0106/ca0106_mixer.c
sound/pci/ca0106/ca0106_proc.c
sound/pci/cs46xx/dsp_spos.c
sound/pci/cs46xx/dsp_spos_scb_lib.c
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_proc.c
sound/pci/hda/patch_atihdmi.c
sound/pci/hda/patch_si3054.c
sound/pci/hda/patch_via.c

index 5163b85..6c8d8f2 100644 (file)
@@ -182,7 +182,7 @@ For example, you can do something like the following.
 
        ...
 
-       devres_close_group(dev, my_midlayer_something);
+       devres_close_group(dev, my_midlayer_create_something);
        return 0;
   }
 
index 5c88ba1..5f96cb3 100644 (file)
@@ -117,13 +117,6 @@ Who:   Adrian Bunk <bunk@stusta.de>
 
 ---------------------------
 
-What:  pci_module_init(driver)
-When:  January 2007
-Why:   Is replaced by pci_register_driver(pci_driver).
-Who:   Richard Knutsson <ricknu-0@student.ltu.se> and Greg Kroah-Hartman <gregkh@suse.de>
-
----------------------------
-
 What:  Usage of invalid timevals in setitimer
 When:  March 2007
 Why:   POSIX requires to validate timevals in the setitimer call. This
@@ -190,18 +183,10 @@ Who:      Jean Delvare <khali@linux-fr.org>
 
 ---------------------------
 
-What:  i2c_adapter.dev
-       i2c_adapter.list
+What:  i2c_adapter.list
 When:  July 2007
-Why:   Superfluous, given i2c_adapter.class_dev:
-         * The "dev" was a stand-in for the physical device node that legacy
-           drivers would not have; but now it's almost always present.  Any
-           remaining legacy drivers must upgrade (they now trigger warnings).
-         * The "list" duplicates class device children.
-       The delay in removing this is so upgraded lm_sensors and libsensors
-       can get deployed.  (Removal causes minor changes in the sysfs layout,
-       notably the location of the adapter type name and parenting the i2c
-       client hardware directly from their controller.)
+Why:   Superfluous, this list duplicates the one maintained by the driver
+       core.
 Who:   Jean Delvare <khali@linux-fr.org>,
        David Brownell <dbrownell@users.sourceforge.net>
 
@@ -314,3 +299,27 @@ Why:       Code was merged, then submitter immediately disappeared leaving
 Who:   David S. Miller <davem@davemloft.net>
 
 ---------------------------
+
+What:  read_dev_chars(), read_conf_data{,_lpm}() (s390 common I/O layer)
+When:  December 2007
+Why:   These functions are a leftover from 2.4 times. They have several
+       problems:
+       - Duplication of checks that are done in the device driver's
+         interrupt handler
+       - common I/O layer can't do device specific error recovery
+       - device driver can't be notified for conditions happening during
+         execution of the function
+       Device drivers should issue the read device characteristics and read
+       configuration data ccws and do the appropriate error handling
+       themselves.
+Who:   Cornelia Huck <cornelia.huck@de.ibm.com>
+
+---------------------------
+
+What:  i2c-ixp2000, i2c-ixp4xx and scx200_i2c drivers
+When:  September 2007
+Why:   Obsolete. The new i2c-gpio driver replaces all hardware-specific
+       I2C-over-GPIO drivers.
+Who:   Jean Delvare <khali@linux-fr.org>
+
+---------------------------
index 7f61fbc..fae3495 100644 (file)
@@ -9,6 +9,8 @@ Supported adapters:
   * nForce4 MCP-04             10de:0034
   * nForce4 MCP51              10de:0264
   * nForce4 MCP55              10de:0368
+  * nForce4 MCP61              10de:03EB
+  * nForce4 MCP65              10de:0446
 
 Datasheet: not publicly available, but seems to be similar to the
            AMD-8111 SMBus 2.0 adapter.
index ca272b2..7bf82c0 100644 (file)
@@ -1,4 +1,4 @@
-Revision 6, 2005-11-20
+Revision 7, 2007-04-19
 Jean Delvare <khali@linux-fr.org>
 Greg KH <greg@kroah.com>
 
@@ -20,6 +20,10 @@ yours for best results.
 
 Technical changes:
 
+* [Driver type] Any driver that was relying on i2c-isa has to be
+  converted to a proper isa, platform or pci driver. This is not
+  covered by this guide.
+
 * [Includes] Get rid of "version.h" and <linux/i2c-proc.h>.
   Includes typically look like that:
   #include <linux/module.h>
@@ -27,12 +31,10 @@ Technical changes:
   #include <linux/slab.h>
   #include <linux/jiffies.h>
   #include <linux/i2c.h>
-  #include <linux/i2c-isa.h>   /* for ISA drivers */
   #include <linux/hwmon.h>     /* for hardware monitoring drivers */
   #include <linux/hwmon-sysfs.h>
   #include <linux/hwmon-vid.h> /* if you need VRM support */
   #include <linux/err.h>       /* for class registration */
-  #include <asm/io.h>          /* if you have I/O operations */
   Please respect this inclusion order. Some extra headers may be
   required for a given driver (e.g. "lm75.h").
 
@@ -69,20 +71,16 @@ Technical changes:
   sensors mailing list <lm-sensors@lm-sensors.org> by providing a
   patch to the Documentation/hwmon/sysfs-interface file.
 
-* [Attach] For I2C drivers, the attach function should make sure
-  that the adapter's class has I2C_CLASS_HWMON (or whatever class is
-  suitable for your driver), using the following construct:
+* [Attach] The attach function should make sure that the adapter's
+  class has I2C_CLASS_HWMON (or whatever class is suitable for your
+  driver), using the following construct:
   if (!(adapter->class & I2C_CLASS_HWMON))
           return 0;
-  ISA-only drivers of course don't need this.
   Call i2c_probe() instead of i2c_detect().
 
 * [Detect] As mentioned earlier, the flags parameter is gone.
   The type_name and client_name strings are replaced by a single
   name string, which will be filled with a lowercase, short string.
-  In i2c-only drivers, drop the i2c_is_isa_adapter check, it's
-  useless. Same for isa-only drivers, as the test would always be
-  true. Only hybrid drivers (which are quite rare) still need it.
   The labels used for error paths are reduced to the number needed.
   It is advised that the labels are given descriptive names such as
   exit and exit_free. Don't forget to properly set err before
index 41dde87..aea60bf 100644 (file)
@@ -4,17 +4,23 @@ I2C and SMBus
 =============
 
 I2C (pronounce: I squared C) is a protocol developed by Philips. It is a 
-slow two-wire protocol (10-400 kHz), but it suffices for many types of 
-devices.
+slow two-wire protocol (variable speed, up to 400 kHz), with a high speed
+extension (3.4 MHz).  It provides an inexpensive bus for connecting many
+types of devices with infrequent or low bandwidth communications needs.
+I2C is widely used with embedded systems.  Some systems use variants that
+don't meet branding requirements, and so are not advertised as being I2C.
 
-SMBus (System Management Bus) is a subset of the I2C protocol. Many
-modern mainboards have a System Management Bus. There are a lot of 
-devices which can be connected to a SMBus; the most notable are modern 
-memory chips with EEPROM memories and chips for hardware monitoring.
+SMBus (System Management Bus) is based on the I2C protocol, and is mostly
+a subset of I2C protocols and signaling.  Many I2C devices will work on an
+SMBus, but some SMBus protocols add semantics beyond what is required to
+achieve I2C branding.  Modern PC mainboards rely on SMBus.  The most common
+devices connected through SMBus are RAM modules configured using I2C EEPROMs,
+and hardware monitoring chips.
 
-Because the SMBus is just a special case of the generalized I2C bus, we
-can simulate the SMBus protocol on plain I2C busses. The reverse is
-regretfully impossible.
+Because the SMBus is mostly a subset of the generalized I2C bus, we can
+use its protocols on many I2C systems.  However, there are systems that don't
+meet both SMBus and I2C electrical constraints; and others which can't
+implement all the common SMBus protocol semantics or messages.
 
 
 Terminology
@@ -29,6 +35,7 @@ When we talk about I2C, we use the following terms:
 An Algorithm driver contains general code that can be used for a whole class
 of I2C adapters. Each specific adapter driver depends on one algorithm
 driver.
+
 A Driver driver (yes, this sounds ridiculous, sorry) contains the general
 code to access some type of device. Each detected device gets its own
 data in the Client structure. Usually, Driver and Client are more closely
@@ -40,6 +47,10 @@ a separate Adapter and Algorithm driver), and drivers for your I2C devices
 in this package. See the lm_sensors project http://www.lm-sensors.nu
 for device drivers.
 
+At this time, Linux only operates I2C (or SMBus) in master mode; you can't
+use these APIs to make a Linux system behave as a slave/device, either to
+speak a custom protocol or to emulate some other device.
+
 
 Included Bus Drivers
 ====================
index fbcff96..3d8d36b 100644 (file)
@@ -1,5 +1,5 @@
 This is a small guide for those who want to write kernel drivers for I2C
-or SMBus devices.
+or SMBus devices, using Linux as the protocol host/master (not slave).
 
 To set up a driver, you need to do several things. Some are optional, and
 some things can be done slightly or completely different. Use this as a
@@ -29,8 +29,16 @@ static struct i2c_driver foo_driver = {
        .driver = {
                .name   = "foo",
        },
+
+       /* iff driver uses driver model ("new style") binding model: */
+       .probe          = foo_probe,
+       .remove         = foo_remove,
+
+       /* else, driver uses "legacy" binding model: */
        .attach_adapter = foo_attach_adapter,
        .detach_client  = foo_detach_client,
+
+       /* these may be used regardless of the driver binding model */
        .shutdown       = foo_shutdown, /* optional */
        .suspend        = foo_suspend,  /* optional */
        .resume         = foo_resume,   /* optional */
@@ -40,7 +48,8 @@ static struct i2c_driver foo_driver = {
 The name field is the driver name, and must not contain spaces.  It
 should match the module name (if the driver can be compiled as a module),
 although you can use MODULE_ALIAS (passing "foo" in this example) to add
-another name for the module.
+another name for the module.  If the driver name doesn't match the module
+name, the module won't be automatically loaded (hotplug/coldplug).
 
 All other fields are for call-back functions which will be explained 
 below.
@@ -65,16 +74,13 @@ An example structure is below.
 
   struct foo_data {
     struct i2c_client client;
-    struct semaphore lock; /* For ISA access in `sensors' drivers. */
-    int sysctl_id;         /* To keep the /proc directory entry for 
-                              `sensors' drivers. */
     enum chips type;       /* To keep the chips type for `sensors' drivers. */
    
     /* Because the i2c bus is slow, it is often useful to cache the read
        information of a chip for some time (for example, 1 or 2 seconds).
        It depends of course on the device whether this is really worthwhile
        or even sensible. */
-    struct semaphore update_lock; /* When we are reading lots of information,
+    struct mutex update_lock;     /* When we are reading lots of information,
                                      another process should not update the
                                      below information */
     char valid;                   /* != 0 if the following fields are valid. */
@@ -95,8 +101,7 @@ some obscure clients). But we need generic reading and writing routines.
 I have found it useful to define foo_read and foo_write function for this.
 For some cases, it will be easier to call the i2c functions directly,
 but many chips have some kind of register-value idea that can easily
-be encapsulated. Also, some chips have both ISA and I2C interfaces, and
-it useful to abstract from this (only for `sensors' drivers).
+be encapsulated.
 
 The below functions are simple examples, and should not be copied
 literally.
@@ -119,28 +124,101 @@ literally.
       return i2c_smbus_write_word_data(client,reg,value);
   }
 
-For sensors code, you may have to cope with ISA registers too. Something
-like the below often works. Note the locking! 
-
-  int foo_read_value(struct i2c_client *client, u8 reg)
-  {
-    int res;
-    if (i2c_is_isa_client(client)) {
-      down(&(((struct foo_data *) (client->data)) -> lock));
-      outb_p(reg,client->addr + FOO_ADDR_REG_OFFSET);
-      res = inb_p(client->addr + FOO_DATA_REG_OFFSET);
-      up(&(((struct foo_data *) (client->data)) -> lock));
-      return res;
-    } else
-      return i2c_smbus_read_byte_data(client,reg);
-  }
-
-Writing is done the same way.
-
 
 Probing and attaching
 =====================
 
+The Linux I2C stack was originally written to support access to hardware
+monitoring chips on PC motherboards, and thus it embeds some assumptions
+that are more appropriate to SMBus (and PCs) than to I2C.  One of these
+assumptions is that most adapters and devices drivers support the SMBUS_QUICK
+protocol to probe device presence.  Another is that devices and their drivers
+can be sufficiently configured using only such probe primitives.
+
+As Linux and its I2C stack became more widely used in embedded systems
+and complex components such as DVB adapters, those assumptions became more
+problematic.  Drivers for I2C devices that issue interrupts need more (and
+different) configuration information, as do drivers handling chip variants
+that can't be distinguished by protocol probing, or which need some board
+specific information to operate correctly.
+
+Accordingly, the I2C stack now has two models for associating I2C devices
+with their drivers:  the original "legacy" model, and a newer one that's
+fully compatible with the Linux 2.6 driver model.  These models do not mix,
+since the "legacy" model requires drivers to create "i2c_client" device
+objects after SMBus style probing, while the Linux driver model expects
+drivers to be given such device objects in their probe() routines.
+
+
+Standard Driver Model Binding ("New Style")
+-------------------------------------------
+
+System infrastructure, typically board-specific initialization code or
+boot firmware, reports what I2C devices exist.  For example, there may be
+a table, in the kernel or from the boot loader, identifying I2C devices
+and linking them to board-specific configuration information about IRQs
+and other wiring artifacts, chip type, and so on.  That could be used to
+create i2c_client objects for each I2C device.
+
+I2C device drivers using this binding model work just like any other
+kind of driver in Linux:  they provide a probe() method to bind to
+those devices, and a remove() method to unbind.
+
+       static int foo_probe(struct i2c_client *client);
+       static int foo_remove(struct i2c_client *client);
+
+Remember that the i2c_driver does not create those client handles.  The
+handle may be used during foo_probe().  If foo_probe() reports success
+(zero not a negative status code) it may save the handle and use it until
+foo_remove() returns.  That binding model is used by most Linux drivers.
+
+Drivers match devices when i2c_client.driver_name and the driver name are
+the same; this approach is used in several other busses that don't have
+device typing support in the hardware.  The driver and module name should
+match, so hotplug/coldplug mechanisms will modprobe the driver.
+
+
+Device Creation (Standard driver model)
+---------------------------------------
+
+If you know for a fact that an I2C device is connected to a given I2C bus,
+you can instantiate that device by simply filling an i2c_board_info
+structure with the device address and driver name, and calling
+i2c_new_device().  This will create the device, then the driver core will
+take care of finding the right driver and will call its probe() method.
+If a driver supports different device types, you can specify the type you
+want using the type field.  You can also specify an IRQ and platform data
+if needed.
+
+Sometimes you know that a device is connected to a given I2C bus, but you
+don't know the exact address it uses.  This happens on TV adapters for
+example, where the same driver supports dozens of slightly different
+models, and I2C device addresses change from one model to the next.  In
+that case, you can use the i2c_new_probed_device() variant, which is
+similar to i2c_new_device(), except that it takes an additional list of
+possible I2C addresses to probe.  A device is created for the first
+responsive address in the list.  If you expect more than one device to be
+present in the address range, simply call i2c_new_probed_device() that
+many times.
+
+The call to i2c_new_device() or i2c_new_probed_device() typically happens
+in the I2C bus driver. You may want to save the returned i2c_client
+reference for later use.
+
+
+Device Deletion (Standard driver model)
+---------------------------------------
+
+Each I2C device which has been created using i2c_new_device() or
+i2c_new_probed_device() can be unregistered by calling
+i2c_unregister_device().  If you don't call it explicitly, it will be
+called automatically before the underlying I2C bus itself is removed, as a
+device can't survive its parent in the device driver model.
+
+
+Legacy Driver Binding Model
+---------------------------
+
 Most i2c devices can be present on several i2c addresses; for some this
 is determined in hardware (by soldering some chip pins to Vcc or Ground),
 for others this can be changed in software (by writing to specific client
@@ -157,13 +235,9 @@ detection algorithm.
 You do not have to use this parameter interface; but don't try to use
 function i2c_probe() if you don't.
 
-NOTE: If you want to write a `sensors' driver, the interface is slightly
-      different! See below.
-
 
-
-Probing classes
----------------
+Probing classes (Legacy model)
+------------------------------
 
 All parameters are given as lists of unsigned 16-bit integers. Lists are
 terminated by I2C_CLIENT_END.
@@ -210,8 +284,8 @@ Note that you *have* to call the defined variable `normal_i2c',
 without any prefix!
 
 
-Attaching to an adapter
------------------------
+Attaching to an adapter (Legacy model)
+--------------------------------------
 
 Whenever a new adapter is inserted, or for all adapters if the driver is
 being registered, the callback attach_adapter() is called. Now is the
@@ -237,17 +311,13 @@ them (unless a `force' parameter was used). In addition, addresses that
 are already in use (by some other registered client) are skipped.
 
 
-The detect client function
---------------------------
+The detect client function (Legacy model)
+-----------------------------------------
 
 The detect client function is called by i2c_probe. The `kind' parameter
 contains -1 for a probed detection, 0 for a forced detection, or a positive
 number for a forced detection with a chip type forced.
 
-Below, some things are only needed if this is a `sensors' driver. Those
-parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */
-markers. 
-
 Returning an error different from -ENODEV in a detect function will cause
 the detection to stop: other addresses and adapters won't be scanned.
 This should only be done on fatal or internal errors, such as a memory
@@ -256,64 +326,20 @@ shortage or i2c_attach_client failing.
 For now, you can ignore the `flags' parameter. It is there for future use.
 
   int foo_detect_client(struct i2c_adapter *adapter, int address, 
-                        unsigned short flags, int kind)
+                        int kind)
   {
     int err = 0;
     int i;
-    struct i2c_client *new_client;
+    struct i2c_client *client;
     struct foo_data *data;
-    const char *client_name = ""; /* For non-`sensors' drivers, put the real
-                                     name here! */
+    const char *name = "";
    
     /* Let's see whether this adapter can support what we need.
-       Please substitute the things you need here! 
-       For `sensors' drivers, add `! is_isa &&' to the if statement */
+       Please substitute the things you need here! */
     if (!i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA |
                                         I2C_FUNC_SMBUS_WRITE_BYTE))
        goto ERROR0;
 
-    /* SENSORS ONLY START */
-    const char *type_name = "";
-    int is_isa = i2c_is_isa_adapter(adapter);
-
-    /* Do this only if the chip can additionally be found on the ISA bus
-       (hybrid chip). */
-
-    if (is_isa) {
-
-      /* Discard immediately if this ISA range is already used */
-      /* FIXME: never use check_region(), only request_region() */
-      if (check_region(address,FOO_EXTENT))
-        goto ERROR0;
-
-      /* Probe whether there is anything on this address.
-         Some example code is below, but you will have to adapt this
-         for your own driver */
-
-      if (kind < 0) /* Only if no force parameter was used */ {
-        /* We may need long timeouts at least for some chips. */
-        #define REALLY_SLOW_IO
-        i = inb_p(address + 1);
-        if (inb_p(address + 2) != i)
-          goto ERROR0;
-        if (inb_p(address + 3) != i)
-          goto ERROR0;
-        if (inb_p(address + 7) != i)
-          goto ERROR0;
-        #undef REALLY_SLOW_IO
-
-        /* Let's just hope nothing breaks here */
-        i = inb_p(address + 5) & 0x7f;
-        outb_p(~i & 0x7f,address+5);
-        if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
-          outb_p(i,address+5);
-          return 0;
-        }
-      }
-    }
-
-    /* SENSORS ONLY END */
-
     /* OK. For now, we presume we have a valid client. We now create the
        client structure, even though we cannot fill it completely yet.
        But it allows us to access several i2c functions safely */
@@ -323,13 +349,12 @@ For now, you can ignore the `flags' parameter. It is there for future use.
       goto ERROR0;
     }
 
-    new_client = &data->client;
-    i2c_set_clientdata(new_client, data);
+    client = &data->client;
+    i2c_set_clientdata(client, data);
 
-    new_client->addr = address;
-    new_client->adapter = adapter;
-    new_client->driver = &foo_driver;
-    new_client->flags = 0;
+    client->addr = address;
+    client->adapter = adapter;
+    client->driver = &foo_driver;
 
     /* Now, we do the remaining detection. If no `force' parameter is used. */
 
@@ -337,19 +362,17 @@ For now, you can ignore the `flags' parameter. It is there for future use.
        parameter was used. */
     if (kind < 0) {
       /* The below is of course bogus */
-      if (foo_read(new_client,FOO_REG_GENERIC) != FOO_GENERIC_VALUE)
+      if (foo_read(client, FOO_REG_GENERIC) != FOO_GENERIC_VALUE)
          goto ERROR1;
     }
 
-    /* SENSORS ONLY START */
-
     /* Next, specific detection. This is especially important for `sensors'
        devices. */
 
     /* Determine the chip type. Not needed if a `force_CHIPTYPE' parameter
        was used. */
     if (kind <= 0) {
-      i = foo_read(new_client,FOO_REG_CHIPTYPE);
+      i = foo_read(client, FOO_REG_CHIPTYPE);
       if (i == FOO_TYPE_1) 
         kind = chip1; /* As defined in the enum */
       else if (i == FOO_TYPE_2)
@@ -363,63 +386,31 @@ For now, you can ignore the `flags' parameter. It is there for future use.
 
     /* Now set the type and chip names */
     if (kind == chip1) {
-      type_name = "chip1"; /* For /proc entry */
-      client_name = "CHIP 1";
+      name = "chip1";
     } else if (kind == chip2) {
-      type_name = "chip2"; /* For /proc entry */
-      client_name = "CHIP 2";
+      name = "chip2";
     }
    
-    /* Reserve the ISA region */
-    if (is_isa)
-      request_region(address,FOO_EXTENT,type_name);
-
-    /* SENSORS ONLY END */
-
     /* Fill in the remaining client fields. */
-    strcpy(new_client->name,client_name);
-
-    /* SENSORS ONLY BEGIN */
+    strlcpy(client->name, name, I2C_NAME_SIZE);
     data->type = kind;
-    /* SENSORS ONLY END */
-
-    data->valid = 0; /* Only if you use this field */
-    init_MUTEX(&data->update_lock); /* Only if you use this field */
+    mutex_init(&data->update_lock); /* Only if you use this field */
 
     /* Any other initializations in data must be done here too. */
 
-    /* Tell the i2c layer a new client has arrived */
-    if ((err = i2c_attach_client(new_client)))
-      goto ERROR3;
-
-    /* SENSORS ONLY BEGIN */
-    /* Register a new directory entry with module sensors. See below for
-       the `template' structure. */
-    if ((i = i2c_register_entry(new_client, type_name,
-                                    foo_dir_table_template,THIS_MODULE)) < 0) {
-      err = i;
-      goto ERROR4;
-    }
-    data->sysctl_id = i;
-
-    /* SENSORS ONLY END */
-
     /* This function can write default values to the client registers, if
        needed. */
-    foo_init_client(new_client);
+    foo_init_client(client);
+
+    /* Tell the i2c layer a new client has arrived */
+    if ((err = i2c_attach_client(client)))
+      goto ERROR1;
+
     return 0;
 
     /* OK, this is not exactly good programming practice, usually. But it is
        very code-efficient in this case. */
 
-    ERROR4:
-      i2c_detach_client(new_client);
-    ERROR3:
-    ERROR2:
-    /* SENSORS ONLY START */
-      if (is_isa)
-        release_region(address,FOO_EXTENT);
-    /* SENSORS ONLY END */
     ERROR1:
       kfree(data);
     ERROR0:
@@ -427,8 +418,8 @@ For now, you can ignore the `flags' parameter. It is there for future use.
   }
 
 
-Removing the client
-===================
+Removing the client (Legacy model)
+==================================
 
 The detach_client call back function is called when a client should be
 removed. It may actually fail, but only when panicking. This code is
@@ -436,22 +427,12 @@ much simpler than the attachment code, fortunately!
 
   int foo_detach_client(struct i2c_client *client)
   {
-    int err,i;
-
-    /* SENSORS ONLY START */
-    /* Deregister with the `i2c-proc' module. */
-    i2c_deregister_entry(((struct lm78_data *)(client->data))->sysctl_id);
-    /* SENSORS ONLY END */
+    int err;
 
     /* Try to detach the client from i2c space */
     if ((err = i2c_detach_client(client)))
       return err;
 
-    /* HYBRID SENSORS CHIP ONLY START */
-    if i2c_is_isa_client(client)
-      release_region(client->addr,LM78_EXTENT);
-    /* HYBRID SENSORS CHIP ONLY END */
-
     kfree(i2c_get_clientdata(client));
     return 0;
   }
@@ -464,45 +445,34 @@ When the kernel is booted, or when your foo driver module is inserted,
 you have to do some initializing. Fortunately, just attaching (registering)
 the driver module is usually enough.
 
-  /* Keep track of how far we got in the initialization process. If several
-     things have to initialized, and we fail halfway, only those things
-     have to be cleaned up! */
-  static int __initdata foo_initialized = 0;
-
   static int __init foo_init(void)
   {
     int res;
-    printk("foo version %s (%s)\n",FOO_VERSION,FOO_DATE);
     
     if ((res = i2c_add_driver(&foo_driver))) {
       printk("foo: Driver registration failed, module not inserted.\n");
-      foo_cleanup();
       return res;
     }
-    foo_initialized ++;
     return 0;
   }
 
-  void foo_cleanup(void)
+  static void __exit foo_cleanup(void)
   {
-    if (foo_initialized == 1) {
-      if ((res = i2c_del_driver(&foo_driver))) {
-        printk("foo: Driver registration failed, module not removed.\n");
-        return;
-      }
-      foo_initialized --;
-    }
+    i2c_del_driver(&foo_driver);
   }
 
   /* Substitute your own name and email address */
   MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"
   MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices");
 
+  /* a few non-GPL license types are also allowed */
+  MODULE_LICENSE("GPL");
+
   module_init(foo_init);
   module_exit(foo_cleanup);
 
 Note that some functions are marked by `__init', and some data structures
-by `__init_data'.  Hose functions and structures can be removed after
+by `__initdata'.  These functions and structures can be removed after
 kernel booting (or module loading) is completed.
 
 
@@ -632,110 +602,7 @@ General purpose routines
 Below all general purpose routines are listed, that were not mentioned
 before.
 
-  /* This call returns a unique low identifier for each registered adapter,
-   * or -1 if the adapter was not registered.
+  /* This call returns a unique low identifier for each registered adapter.
    */
   extern int i2c_adapter_id(struct i2c_adapter *adap);
 
-
-The sensors sysctl/proc interface
-=================================
-
-This section only applies if you write `sensors' drivers.
-
-Each sensors driver creates a directory in /proc/sys/dev/sensors for each
-registered client. The directory is called something like foo-i2c-4-65.
-The sensors module helps you to do this as easily as possible.
-
-The template
-------------
-
-You will need to define a ctl_table template. This template will automatically
-be copied to a newly allocated structure and filled in where necessary when
-you call sensors_register_entry.
-
-First, I will give an example definition.
-  static ctl_table foo_dir_table_template[] = {
-    { FOO_SYSCTL_FUNC1, "func1", NULL, 0, 0644, NULL, &i2c_proc_real,
-      &i2c_sysctl_real,NULL,&foo_func },
-    { FOO_SYSCTL_FUNC2, "func2", NULL, 0, 0644, NULL, &i2c_proc_real,
-      &i2c_sysctl_real,NULL,&foo_func },
-    { FOO_SYSCTL_DATA, "data", NULL, 0, 0644, NULL, &i2c_proc_real,
-      &i2c_sysctl_real,NULL,&foo_data },
-    { 0 }
-  };
-
-In the above example, three entries are defined. They can either be
-accessed through the /proc interface, in the /proc/sys/dev/sensors/*
-directories, as files named func1, func2 and data, or alternatively 
-through the sysctl interface, in the appropriate table, with identifiers
-FOO_SYSCTL_FUNC1, FOO_SYSCTL_FUNC2 and FOO_SYSCTL_DATA.
-
-The third, sixth and ninth parameters should always be NULL, and the
-fourth should always be 0. The fifth is the mode of the /proc file;
-0644 is safe, as the file will be owned by root:root. 
-
-The seventh and eighth parameters should be &i2c_proc_real and
-&i2c_sysctl_real if you want to export lists of reals (scaled
-integers). You can also use your own function for them, as usual.
-Finally, the last parameter is the call-back to gather the data
-(see below) if you use the *_proc_real functions. 
-
-
-Gathering the data
-------------------
-
-The call back functions (foo_func and foo_data in the above example)
-can be called in several ways; the operation parameter determines
-what should be done:
-
-  * If operation == SENSORS_PROC_REAL_INFO, you must return the
-    magnitude (scaling) in nrels_mag;
-  * If operation == SENSORS_PROC_REAL_READ, you must read information
-    from the chip and return it in results. The number of integers
-    to display should be put in nrels_mag;
-  * If operation == SENSORS_PROC_REAL_WRITE, you must write the
-    supplied information to the chip. nrels_mag will contain the number
-    of integers, results the integers themselves.
-
-The *_proc_real functions will display the elements as reals for the
-/proc interface. If you set the magnitude to 2, and supply 345 for
-SENSORS_PROC_REAL_READ, it would display 3.45; and if the user would
-write 45.6 to the /proc file, it would be returned as 4560 for
-SENSORS_PROC_REAL_WRITE. A magnitude may even be negative!
-
-An example function:
-
-  /* FOO_FROM_REG and FOO_TO_REG translate between scaled values and
-     register values. Note the use of the read cache. */
-  void foo_in(struct i2c_client *client, int operation, int ctl_name, 
-              int *nrels_mag, long *results)
-  {
-    struct foo_data *data = client->data;
-    int nr = ctl_name - FOO_SYSCTL_FUNC1; /* reduce to 0 upwards */
-    
-    if (operation == SENSORS_PROC_REAL_INFO)
-      *nrels_mag = 2;
-    else if (operation == SENSORS_PROC_REAL_READ) {
-      /* Update the readings cache (if necessary) */
-      foo_update_client(client);
-      /* Get the readings from the cache */
-      results[0] = FOO_FROM_REG(data->foo_func_base[nr]);
-      results[1] = FOO_FROM_REG(data->foo_func_more[nr]);
-      results[2] = FOO_FROM_REG(data->foo_func_readonly[nr]);
-      *nrels_mag = 2;
-    } else if (operation == SENSORS_PROC_REAL_WRITE) {
-      if (*nrels_mag >= 1) {
-        /* Update the cache */
-        data->foo_base[nr] = FOO_TO_REG(results[0]);
-        /* Update the chip */
-        foo_write_value(client,FOO_REG_FUNC_BASE(nr),data->foo_base[nr]);
-      }
-      if (*nrels_mag >= 2) {
-        /* Update the cache */
-        data->foo_more[nr] = FOO_TO_REG(results[1]);
-        /* Update the chip */
-        foo_write_value(client,FOO_REG_FUNC_MORE(nr),data->foo_more[nr]);
-      }
-    }
-  }
index 180e068..d9d5230 100644 (file)
@@ -1,5 +1,3 @@
-$Id: input-programming.txt,v 1.4 2001/05/04 09:47:14 vojtech Exp $
-
 Programming input drivers
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -20,28 +18,51 @@ pressed or released a BUTTON_IRQ happens. The driver could look like:
 #include <asm/irq.h>
 #include <asm/io.h>
 
+static struct input_dev *button_dev;
+
 static void button_interrupt(int irq, void *dummy, struct pt_regs *fp)
 {
-       input_report_key(&button_dev, BTN_1, inb(BUTTON_PORT) & 1);
-       input_sync(&button_dev);
+       input_report_key(button_dev, BTN_1, inb(BUTTON_PORT) & 1);
+       input_sync(button_dev);
 }
 
 static int __init button_init(void)
 {
+       int error;
+
        if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {
                 printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
                 return -EBUSY;
         }
-       
-       button_dev.evbit[0] = BIT(EV_KEY);
-       button_dev.keybit[LONG(BTN_0)] = BIT(BTN_0);
-       
-       input_register_device(&button_dev);
+
+       button_dev = input_allocate_device();
+       if (!button_dev) {
+               printk(KERN_ERR "button.c: Not enough memory\n");
+               error = -ENOMEM;
+               goto err_free_irq;
+       }
+
+       button_dev->evbit[0] = BIT(EV_KEY);
+       button_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
+
+       error = input_register_device(button_dev);
+       if (error) {
+               printk(KERN_ERR "button.c: Failed to register device\n");
+               goto err_free_dev;
+       }
+
+       return 0;
+
+ err_free_dev:
+       input_free_device(button_dev);
+ err_free_irq:
+       free_irq(BUTTON_IRQ, button_interrupt);
+       return error;
 }
 
 static void __exit button_exit(void)
 {
-        input_unregister_device(&button_dev);
+        input_unregister_device(button_dev);
        free_irq(BUTTON_IRQ, button_interrupt);
 }
 
@@ -58,17 +79,18 @@ In the _init function, which is called either upon module load or when
 booting the kernel, it grabs the required resources (it should also check
 for the presence of the device).
 
-Then it sets the input bitfields. This way the device driver tells the other
+Then it allocates a new input device structure with input_aloocate_device()
+and sets up input bitfields. This way the device driver tells the other
 parts of the input systems what it is - what events can be generated or
-accepted by this input device. Our example device can only generate EV_KEY type
-events, and from those only BTN_0 event code. Thus we only set these two
-bits. We could have used
+accepted by this input device. Our example device can only generate EV_KEY
+type events, and from those only BTN_0 event code. Thus we only set these
+two bits. We could have used
 
        set_bit(EV_KEY, button_dev.evbit);
        set_bit(BTN_0, button_dev.keybit);
 
 as well, but with more than single bits the first approach tends to be
-shorter. 
+shorter.
 
 Then the example driver registers the input device structure by calling
 
@@ -76,16 +98,15 @@ Then the example driver registers the input device structure by calling
 
 This adds the button_dev structure to linked lists of the input driver and
 calls device handler modules _connect functions to tell them a new input
-device has appeared. Because the _connect functions may call kmalloc(,
-GFP_KERNEL), which can sleep, input_register_device() must not be called
-from an interrupt or with a spinlock held.
+device has appeared. input_register_device() may sleep and therefore must
+not be called from an interrupt or with a spinlock held.
 
 While in use, the only used function of the driver is
 
        button_interrupt()
 
 which upon every interrupt from the button checks its state and reports it
-via the 
+via the
 
        input_report_key()
 
@@ -113,16 +134,10 @@ can use the open and close callback to know when it can stop polling or
 release the interrupt and when it must resume polling or grab the interrupt
 again. To do that, we would add this to our example driver:
 
-int button_used = 0;
-
 static int button_open(struct input_dev *dev)
 {
-        if (button_used++)
-                return 0;
-
        if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {
                 printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
-                button_used--;
                 return -EBUSY;
         }
 
@@ -131,20 +146,21 @@ static int button_open(struct input_dev *dev)
 
 static void button_close(struct input_dev *dev)
 {
-        if (!--button_used)
-                free_irq(IRQ_AMIGA_VERTB, button_interrupt);
+        free_irq(IRQ_AMIGA_VERTB, button_interrupt);
 }
 
 static int __init button_init(void)
 {
        ...
-       button_dev.open = button_open;
-       button_dev.close = button_close;
+       button_dev->open = button_open;
+       button_dev->close = button_close;
        ...
 }
 
-Note the button_used variable - we have to track how many times the open
-function was called to know when exactly our device stops being used.
+Note that input core keeps track of number of users for the device and
+makes sure that dev->open() is called only when the first user connects
+to the device and that dev->close() is called when the very last user
+disconnects. Calls to both callbacks are serialized.
 
 The open() callback should return a 0 in case of success or any nonzero value
 in case of failure. The close() callback (which is void) must always succeed.
@@ -175,7 +191,7 @@ set the corresponding bits and call the
 
        input_report_rel(struct input_dev *dev, int code, int value)
 
-function. Events are generated only for nonzero value. 
+function. Events are generated only for nonzero value.
 
 However EV_ABS requires a little special care. Before calling
 input_register_device, you have to fill additional fields in the input_dev
@@ -187,6 +203,10 @@ the ABS_X axis:
        button_dev.absfuzz[ABS_X] = 4;
        button_dev.absflat[ABS_X] = 8;
 
+Or, you can just say:
+
+       input_set_abs_params(button_dev, ABS_X, 0, 255, 4, 8);
+
 This setting would be appropriate for a joystick X axis, with the minimum of
 0, maximum of 255 (which the joystick *must* be able to reach, no problem if
 it sometimes reports more, but it must be able to always reach the min and
@@ -197,14 +217,7 @@ If you don't need absfuzz and absflat, you can set them to zero, which mean
 that the thing is precise and always returns to exactly the center position
 (if it has any).
 
-1.4 The void *private field
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This field in the input structure can be used to point to any private data
-structures in the input device driver, in case the driver handles more than
-one device. You'll need it in the open and close callbacks.
-
-1.5 NBITS(), LONG(), BIT()
+1.4 NBITS(), LONG(), BIT()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 These three macros from input.h help some bitfield computations:
@@ -213,13 +226,9 @@ These three macros from input.h help some bitfield computations:
        LONG(x)  - returns the index in the array in longs for bit x
        BIT(x)   - returns the index in a long for bit x
 
-1.6 The number, id* and name fields
+1.5 The id* and name fields
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-The dev->number is assigned by the input system to the input device when it
-is registered. It has no use except for identifying the device to the user
-in system messages.
-
 The dev->name should be set before registering the input device by the input
 device driver. It's a string like 'Generic button device' containing a
 user friendly name of the device.
@@ -234,15 +243,25 @@ driver.
 
 The id and name fields can be passed to userland via the evdev interface.
 
-1.7 The keycode, keycodemax, keycodesize fields
+1.6 The keycode, keycodemax, keycodesize fields
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-These two fields will be used for any input devices that report their data
-as scancodes. If not all scancodes can be known by autodetection, they may
-need to be set by userland utilities. The keycode array then is an array
-used to map from scancodes to input system keycodes. The keycode max will
-contain the size of the array and keycodesize the size of each entry in it
-(in bytes).
+These three fields should be used by input devices that have dense keymaps.
+The keycode is an array used to map from scancodes to input system keycodes.
+The keycode max should contain the size of the array and keycodesize the
+size of each entry in it (in bytes).
+
+Userspace can query and alter current scancode to keycode mappings using
+EVIOCGKEYCODE and EVIOCSKEYCODE ioctls on corresponding evdev interface.
+When a device has all 3 aforementioned fields filled in, the driver may
+rely on kernel's default implementation of setting and querying keycode
+mappings.
+
+1.7 dev->getkeycode() and dev->setkeycode()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+getkeycode() and setkeycode() callbacks allow drivers to override default
+keycode/keycodesize/keycodemax mapping mechanism provided by input core
+and implement sparse keycode maps.
 
 1.8 Key autorepeat
 ~~~~~~~~~~~~~~~~~~
@@ -266,7 +285,7 @@ direction - from the system to the input device driver. If your input device
 driver can handle these events, it has to set the respective bits in evbit,
 *and* also the callback routine:
 
-       button_dev.event = button_event;
+       button_dev->event = button_event;
 
 int button_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
 {
index cdf2f3c..e2c9d0a 100644 (file)
@@ -124,10 +124,6 @@ initialization with a pointer to a structure describing the driver
 
        err_handler     See Documentation/pci-error-recovery.txt
 
-       multithread_probe       Enable multi-threaded probe/scan. Driver must
-                       provide its own locking/syncronization for init
-                       operations if this is enabled.
-
 
 The ID table is an array of struct pci_device_id entries ending with an
 all-zero entry.  Each entry consists of:
@@ -163,9 +159,9 @@ echo "vendor device subvendor subdevice class class_mask driver_data" > \
 /sys/bus/pci/drivers/{driver}/new_id
 
 All fields are passed in as hexadecimal values (no leading 0x).
-Users need pass only as many fields as necessary:
-       o vendor, device, subvendor, and subdevice fields default
-         to PCI_ANY_ID (FFFFFFFF),
+The vendor and device fields are mandatory, the others are optional. Users
+need pass only as many optional fields as necessary:
+       o subvendor and subdevice fields default to PCI_ANY_ID (FFFFFFFF)
        o class and classmask fields default to 0
        o driver_data defaults to 0UL.
 
@@ -549,8 +545,6 @@ pci_find_slot()                     Find pci_dev corresponding to given bus and
 pci_set_power_state()          Set PCI Power Management state (0=D0 ... 3=D3)
 pci_find_capability()          Find specified capability in device's capability
                                list.
-pci_module_init()              Inline helper function for ensuring correct
-                               pci_driver initialization and error handling.
 pci_resource_start()           Returns bus start address for a given PCI region
 pci_resource_end()             Returns bus end address for a given PCI region
 pci_resource_len()             Returns the byte length of a PCI region
index b6a3cbf..e00b099 100644 (file)
@@ -203,7 +203,7 @@ resume
 
 Usage:
 
-if (dev->driver && dev->driver->suspend)
+if (dev->driver && dev->driver->resume)
        dev->driver->resume(dev)
 
 The resume callback may be called from any power state, and is always meant to
index dc8e44f..2368e7e 100644 (file)
@@ -37,7 +37,11 @@ Supported Cards/Chipsets
        9005:0286:9005:029d     Adaptec 2420SA (Intruder HP release)
        9005:0286:9005:02ac     Adaptec 1800 (Typhoon44)
        9005:0285:9005:02b5     Adaptec 5445 (Voodoo44)
+       9005:0285:15d9:02b5     SMC     AOC-USAS-S4i
+       9005:0285:15d9:02c9     SMC     AOC-USAS-S4iR
        9005:0285:9005:02b6     Adaptec 5805 (Voodoo80)
+       9005:0285:15d9:02b6     SMC     AOC-USAS-S8i
+       9005:0285:15d9:02ca     SMC     AOC-USAS-S8iR
        9005:0285:9005:02b7     Adaptec 5085 (Voodoo08)
        9005:0285:9005:02bb     Adaptec 3405 (Marauder40LP)
        9005:0285:9005:02bc     Adaptec 3805 (Marauder80LP)
@@ -93,6 +97,9 @@ Supported Cards/Chipsets
        9005:0286:9005:02ae             (Aurora Lite ARK)
        9005:0285:9005:02b0             (Sunrise Lake ARK)
        9005:0285:9005:02b1     Adaptec (Voodoo 8 internal 8 external)
+       9005:0285:108e:7aac     SUN     STK RAID REM (Voodoo44 Coyote)
+       9005:0285:108e:0286     SUN     SG-XPCIESAS-R-IN (Cougar)
+       9005:0285:108e:0287     SUN     SG-XPCIESAS-R-EX (Prometheus)
 
 People
 -------------------------
index caf10b1..88ef88b 100644 (file)
@@ -562,11 +562,6 @@ if only one has a flaw for some SCSI feature, you can disable the
 support by the driver of this feature at linux start-up and enable
 this feature after boot-up only for devices that support it safely.
 
-CONFIG_SCSI_NCR53C8XX_PROFILE_SUPPORT  (default answer: n)
-    This option must be set for profiling information to be gathered 
-    and printed out through the proc file system. This features may 
-    impact performances.
-
 CONFIG_SCSI_NCR53C8XX_IOMAPPED       (default answer: n)
     Answer "y" if you suspect your mother board to not allow memory mapped I/O.
     May slow down performance a little.  This option is required by
index d61f6e7..b18e86a 100644 (file)
@@ -42,7 +42,7 @@ ConnectTech WhiteHEAT 4 port converter
   http://www.connecttech.com
 
   For any questions or problems with this driver, please contact
-  Stuart MacDonald at stuartm@connecttech.com
+  Connect Tech's Support Department at support@connecttech.com
 
 
 HandSpring Visor, Palm USB, and Clié USB driver
index 4b307e6..0492dd8 100644 (file)
@@ -733,6 +733,13 @@ M: tigran@aivazian.fsnet.co.uk
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 
+BLACKFIN I2C TWI DRIVER
+P:     Sonic Zhang
+M:     sonic.zhang@analog.com
+L:     uclinux-dist-devel@blackfin.uclinux.org (subscribers-only)
+W:     http://blackfin.uclinux.org/
+S:     Supported
+
 BLOCK LAYER
 P:     Jens Axboe
 M:     axboe@kernel.dk
@@ -1459,6 +1466,11 @@ L:       linux-scsi@vger.kernel.org
 W:     http://www.icp-vortex.com/
 S:     Supported
 
+GENERIC GPIO I2C DRIVER
+P:     Haavard Skinnemoen
+M:     hskinnemoen@atmel.com
+S:     Supported
+
 GENERIC HDLC DRIVER, N2, C101, PCI200SYN and WANXL DRIVERS
 P:     Krzysztof Halasa
 M:     khc@pm.waw.pl
@@ -1631,6 +1643,13 @@ L:       i2c@lm-sensors.org
 T:     quilt http://khali.linux-fr.org/devel/linux-2.6/jdelvare-i2c/
 S:     Maintained
 
+I2C-TINY-USB DRIVER
+P:     Till Harbaum
+M:     till@harbaum.org
+L:     i2c@lm-sensors.org
+T:     http://www.harbaum.org/till/i2c_tiny_usb
+S:     Maintained
+
 i386 BOOT CODE
 P:     Riley H. Williams
 M:     Riley@Williams.Name
@@ -2209,6 +2228,16 @@ M:       philb@gnu.org
 W:     http://www.tazenda.demon.co.uk/phil/linux-hp
 S:     Maintained
 
+MAC80211
+P:     Jiri Benc
+M:     jbenc@suse.cz
+P:     Michael Wu
+M:     flamingice@sourmilk.net
+L:     linux-wireless@vger.kernel.org
+W:     http://linuxwireless.org/
+T:     git kernel.org:/pub/scm/linux/kernel/git/jbenc/mac80211.git
+S:     Maintained
+
 MARVELL YUKON / SYSKONNECT DRIVER
 P:     Mirko Lindner
 M:     mlindner@syskonnect.de
@@ -3640,8 +3669,8 @@ W:        http://www.kroah.com/linux/
 S:     Maintained
 
 USB SERIAL WHITEHEAT DRIVER
-P:     Stuart MacDonald
-M:     stuartm@connecttech.com
+P:     Support Department
+M:     support@connecttech.com
 L:     linux-usb-users@lists.sourceforge.net
 L:     linux-usb-devel@lists.sourceforge.net
 W:     http://www.connecttech.com
index 687580b..13d53b1 100644 (file)
@@ -7,7 +7,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <linux/sched.h>
 
 #include <asm/io.h>
index 69b5f4e..11aee01 100644 (file)
@@ -7,7 +7,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <linux/sched.h>
 
 #include <asm/io.h>
index 95463ab..bc799f7 100644 (file)
@@ -7,7 +7,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <linux/sched.h>
 
 #include <asm/io.h>
index e7baca2..db00376 100644 (file)
@@ -255,6 +255,7 @@ config ARCH_IOP13XX
        depends on MMU
        select PLAT_IOP
        select PCI
+       select ARCH_SUPPORTS_MSI
        help
          Support for Intel's IOP13XX (XScale) family of processors.
 
index 0383ab3..6f4ea4b 100644 (file)
@@ -72,12 +72,12 @@ static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
 
 static unsigned short enable_dyn_sleep = 1;
 
-static ssize_t omap_pm_sleep_while_idle_show(struct subsystem * subsys, char *buf)
+static ssize_t omap_pm_sleep_while_idle_show(struct kset *kset, char *buf)
 {
        return sprintf(buf, "%hu\n", enable_dyn_sleep);
 }
 
-static ssize_t omap_pm_sleep_while_idle_store(struct subsystem * subsys,
+static ssize_t omap_pm_sleep_while_idle_store(struct kset *kset,
                                              const char * buf,
                                              size_t n)
 {
@@ -100,7 +100,7 @@ static struct subsys_attribute sleep_while_idle_attr = {
        .store  = omap_pm_sleep_while_idle_store,
 };
 
-extern struct subsystem power_subsys;
+extern struct kset power_subsys;
 static void (*omap_sram_idle)(void) = NULL;
 static void (*omap_sram_suspend)(unsigned long r0, unsigned long r1) = NULL;
 
index c6f8d68..a9af760 100644 (file)
@@ -1057,6 +1057,7 @@ config PCI
        bool "PCI support" if !X86_VISWS
        depends on !X86_VOYAGER
        default y if X86_VISWS
+       select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC)
        help
          Find out whether you have a PCI motherboard. PCI is the name of a
          bus system, i.e. the way the CPU talks to the other stuff inside
index 2b030d6..a3df9c0 100644 (file)
@@ -590,20 +590,23 @@ static acpi_status longhaul_walk_callback(acpi_handle obj_handle,
 static int enable_arbiter_disable(void)
 {
        struct pci_dev *dev;
+       int status;
        int reg;
        u8 pci_cmd;
 
+       status = 1;
        /* Find PLE133 host bridge */
        reg = 0x78;
-       dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0, NULL);
+       dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0,
+                            NULL);
        /* Find CLE266 host bridge */
        if (dev == NULL) {
                reg = 0x76;
-               dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_862X_0, NULL);
+               dev = pci_get_device(PCI_VENDOR_ID_VIA,
+                                    PCI_DEVICE_ID_VIA_862X_0, NULL);
                /* Find CN400 V-Link host bridge */
                if (dev == NULL)
-                       dev = pci_find_device(PCI_VENDOR_ID_VIA, 0x7259, NULL);
-
+                       dev = pci_get_device(PCI_VENDOR_ID_VIA, 0x7259, NULL);
        }
        if (dev != NULL) {
                /* Enable access to port 0x22 */
@@ -615,10 +618,11 @@ static int enable_arbiter_disable(void)
                        if (!(pci_cmd & 1<<7)) {
                                printk(KERN_ERR PFX
                                        "Can't enable access to port 0x22.\n");
-                               return 0;
+                               status = 0;
                        }
                }
-               return 1;
+               pci_dev_put(dev);
+               return status;
        }
        return 0;
 }
@@ -629,7 +633,7 @@ static int longhaul_setup_vt8235(void)
        u8 pci_cmd;
 
        /* Find VT8235 southbridge */
-       dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, NULL);
+       dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, NULL);
        if (dev != NULL) {
                /* Set transition time to max */
                pci_read_config_byte(dev, 0xec, &pci_cmd);
@@ -641,6 +645,7 @@ static int longhaul_setup_vt8235(void)
                pci_read_config_byte(dev, 0xe5, &pci_cmd);
                pci_cmd |= 1 << 7;
                pci_write_config_byte(dev, 0xe5, pci_cmd);
+               pci_dev_put(dev);
                return 1;
        }
        return 0;
@@ -678,7 +683,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
                                sizeof(samuel2_eblcr));
                        break;
                case 1 ... 15:
-                       longhaul_version = TYPE_LONGHAUL_V2;
+                       longhaul_version = TYPE_LONGHAUL_V1;
                        if (c->x86_mask < 8) {
                                cpu_model = CPU_SAMUEL2;
                                cpuname = "C3 'Samuel 2' [C5B]";
index 4786fed..4c76b51 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/cpufreq.h>
 #include <linux/slab.h>
 #include <linux/cpumask.h>
-#include <linux/sched.h>       /* current / set_cpus_allowed() */
 
 #include <asm/processor.h>
 #include <asm/msr.h>
@@ -62,7 +61,7 @@ static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate)
        if (!cpu_online(cpu) || (newstate > DC_DISABLE) || (newstate == DC_RESV))
                return -EINVAL;
 
-       rdmsr(MSR_IA32_THERM_STATUS, l, h);
+       rdmsr_on_cpu(cpu, MSR_IA32_THERM_STATUS, &l, &h);
 
        if (l & 0x01)
                dprintk("CPU#%d currently thermal throttled\n", cpu);
@@ -70,10 +69,10 @@ static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate)
        if (has_N44_O17_errata[cpu] && (newstate == DC_25PT || newstate == DC_DFLT))
                newstate = DC_38PT;
 
-       rdmsr(MSR_IA32_THERM_CONTROL, l, h);
+       rdmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, &l, &h);
        if (newstate == DC_DISABLE) {
                dprintk("CPU#%d disabling modulation\n", cpu);
-               wrmsr(MSR_IA32_THERM_CONTROL, l & ~(1<<4), h);
+               wrmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, l & ~(1<<4), h);
        } else {
                dprintk("CPU#%d setting duty cycle to %d%%\n",
                        cpu, ((125 * newstate) / 10));
@@ -84,7 +83,7 @@ static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate)
                 */
                l = (l & ~14);
                l = l | (1<<4) | ((newstate & 0x7)<<1);
-               wrmsr(MSR_IA32_THERM_CONTROL, l, h);
+               wrmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, l, h);
        }
 
        return 0;
@@ -111,7 +110,6 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy,
 {
        unsigned int    newstate = DC_RESV;
        struct cpufreq_freqs freqs;
-       cpumask_t cpus_allowed;
        int i;
 
        if (cpufreq_frequency_table_target(policy, &p4clockmod_table[0], target_freq, relation, &newstate))
@@ -132,17 +130,8 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy,
        /* run on each logical CPU, see section 13.15.3 of IA32 Intel Architecture Software
         * Developer's Manual, Volume 3
         */
-       cpus_allowed = current->cpus_allowed;
-
-       for_each_cpu_mask(i, policy->cpus) {
-               cpumask_t this_cpu = cpumask_of_cpu(i);
-
-               set_cpus_allowed(current, this_cpu);
-               BUG_ON(smp_processor_id() != i);
-
+       for_each_cpu_mask(i, policy->cpus)
                cpufreq_p4_setdc(i, p4clockmod_table[newstate].index);
-       }
-       set_cpus_allowed(current, cpus_allowed);
 
        /* notifiers */
        for_each_cpu_mask(i, policy->cpus) {
@@ -256,17 +245,9 @@ static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy)
 
 static unsigned int cpufreq_p4_get(unsigned int cpu)
 {
-       cpumask_t cpus_allowed;
        u32 l, h;
 
-       cpus_allowed = current->cpus_allowed;
-
-       set_cpus_allowed(current, cpumask_of_cpu(cpu));
-       BUG_ON(smp_processor_id() != cpu);
-
-       rdmsr(MSR_IA32_THERM_CONTROL, l, h);
-
-       set_cpus_allowed(current, cpus_allowed);
+       rdmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, &l, &h);
 
        if (l & 0x10) {
                l = l >> 1;
index fe3b670..7cf3d20 100644 (file)
@@ -661,7 +661,8 @@ static int fill_powernow_table(struct powernow_k8_data *data, struct pst_s *pst,
 
        dprintk("cfid 0x%x, cvid 0x%x\n", data->currfid, data->currvid);
        data->powernow_table = powernow_table;
-       print_basics(data);
+       if (first_cpu(cpu_core_map[data->cpu]) == data->cpu)
+               print_basics(data);
 
        for (j = 0; j < data->numps; j++)
                if ((pst[j].fid==data->currfid) && (pst[j].vid==data->currvid))
@@ -814,7 +815,8 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
 
        /* fill in data */
        data->numps = data->acpi_data.state_count;
-       print_basics(data);
+       if (first_cpu(cpu_core_map[data->cpu]) == data->cpu)
+               print_basics(data);
        powernow_k8_acpi_pst_values(data, 0);
 
        /* notify BIOS that we exist */
index 0fb2a30..95be501 100644 (file)
@@ -215,8 +215,10 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid);
 
 static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index);
 
+#ifdef CONFIG_X86_POWERNOW_K8_ACPI
 static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table);
 static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table);
+#endif
 
 #ifdef CONFIG_SMP
 static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[])
index f43b987..35489fd 100644 (file)
@@ -720,6 +720,7 @@ static int centrino_target (struct cpufreq_policy *policy,
                        cpu_set(j, set_mask);
 
                set_cpus_allowed(current, set_mask);
+               preempt_disable();
                if (unlikely(!cpu_isset(smp_processor_id(), set_mask))) {
                        dprintk("couldn't limit to CPUs in this domain\n");
                        retval = -EAGAIN;
@@ -727,6 +728,7 @@ static int centrino_target (struct cpufreq_policy *policy,
                                /* We haven't started the transition yet. */
                                goto migrate_end;
                        }
+                       preempt_enable();
                        break;
                }
 
@@ -761,10 +763,13 @@ static int centrino_target (struct cpufreq_policy *policy,
                }
 
                wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
-               if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
+               if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
+                       preempt_enable();
                        break;
+               }
 
                cpu_set(j, covered_cpus);
+               preempt_enable();
        }
 
        for_each_cpu_mask(k, online_policy_cpus) {
@@ -796,8 +801,11 @@ static int centrino_target (struct cpufreq_policy *policy,
                        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
                }
        }
+       set_cpus_allowed(current, saved_mask);
+       return 0;
 
 migrate_end:
+       preempt_enable();
        set_cpus_allowed(current, saved_mask);
        return 0;
 }
index d59277c..b1acc8c 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/cpufreq.h>
-#include <linux/pci.h>
 #include <linux/slab.h>
 
 #include <asm/msr.h>
index ff0d898..e1c509a 100644 (file)
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/cpufreq.h>
-#include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <asm/ist.h>
+#include <asm/io.h>
 
 #include "speedstep-lib.h"
 
index 10cef5c..f8a3c40 100644 (file)
@@ -110,7 +110,7 @@ void __init setup_pit_timer(void)
         * Start pit with the boot cpu mask and make it global after the
         * IO_APIC has been initialized.
         */
-       pit_clockevent.cpumask = cpumask_of_cpu(0);
+       pit_clockevent.cpumask = cpumask_of_cpu(smp_processor_id());
        pit_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, 32);
        pit_clockevent.max_delta_ns =
                clockevent_delta2ns(0x7FFF, &pit_clockevent);
index f23a17b..1b623cd 100644 (file)
@@ -2579,19 +2579,19 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
        if (irq < 0)
                return irq;
 
-       set_irq_msi(irq, desc);
        ret = msi_compose_msg(dev, irq, &msg);
        if (ret < 0) {
                destroy_irq(irq);
                return ret;
        }
 
+       set_irq_msi(irq, desc);
        write_msi_msg(irq, &msg);
 
        set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq,
                                      "edge");
 
-       return irq;
+       return 0;
 }
 
 void arch_teardown_msi_irq(unsigned int irq)
index cfa16c1..447bb10 100644 (file)
@@ -40,10 +40,16 @@ void __init trap_init_hook(void)
 {
 }
 
-static struct irqaction irq0  = { timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL};
+static struct irqaction irq0  = {
+       .handler = timer_interrupt,
+       .flags = IRQF_DISABLED | IRQF_NOBALANCING,
+       .mask = CPU_MASK_NONE,
+       .name = "timer"
+};
 
 void __init time_init_hook(void)
 {
+       irq0.mask = cpumask_of_cpu(safe_smp_processor_id());
        setup_irq(0, &irq0);
 }
 
index 943a947..26a2d4c 100644 (file)
@@ -1111,7 +1111,7 @@ voyager_cat_do_common_interrupt(void)
                                printk(KERN_ERR "Voyager front panel switch turned off\n");
                                voyager_status.switch_off = 1;
                                voyager_status.request_from_kernel = 1;
-                               up(&kvoyagerd_sem);
+                               wake_up_process(voyager_thread);
                        }
                        /* Tell the hardware we're taking care of the
                         * shutdown, otherwise it will power the box off
@@ -1157,7 +1157,7 @@ voyager_cat_do_common_interrupt(void)
                        outb(VOYAGER_CAT_END, CAT_CMD);
                        voyager_status.power_fail = 1;
                        voyager_status.request_from_kernel = 1;
-                       up(&kvoyagerd_sem);
+                       wake_up_process(voyager_thread);
                }
                
                
index b9ce33c..1a5e448 100644 (file)
@@ -536,15 +536,6 @@ do_boot_cpu(__u8 cpu)
                & ~( voyager_extended_vic_processors
                     & voyager_allowed_boot_processors);
 
-       /* For the 486, we can't use the 4Mb page table trick, so
-        * must map a region of memory */
-#ifdef CONFIG_M486
-       int i;
-       unsigned long *page_table_copies = (unsigned long *)
-               __get_free_page(GFP_KERNEL);
-#endif
-       pgd_t orig_swapper_pg_dir0;
-
        /* This is an area in head.S which was used to set up the
         * initial kernel stack.  We need to alter this to give the
         * booting CPU a new stack (taken from its idle process) */
@@ -573,6 +564,8 @@ do_boot_cpu(__u8 cpu)
        hijack_source.idt.Segment = (start_phys_address >> 4) & 0xFFFF;
 
        cpucount++;
+       alternatives_smp_switch(1);
+
        idle = fork_idle(cpu);
        if(IS_ERR(idle))
                panic("failed fork for CPU%d", cpu);
@@ -587,24 +580,11 @@ do_boot_cpu(__u8 cpu)
        VDEBUG(("VOYAGER SMP: Booting CPU%d at 0x%lx[%x:%x], stack %p\n", cpu, 
                (unsigned long)hijack_source.val, hijack_source.idt.Segment,
                hijack_source.idt.Offset, stack_start.esp));
-       /* set the original swapper_pg_dir[0] to map 0 to 4Mb transparently
-        * (so that the booting CPU can find start_32 */
-       orig_swapper_pg_dir0 = swapper_pg_dir[0];
-#ifdef CONFIG_M486
-       if(page_table_copies == NULL)
-               panic("No free memory for 486 page tables\n");
-       for(i = 0; i < PAGE_SIZE/sizeof(unsigned long); i++)
-               page_table_copies[i] = (i * PAGE_SIZE) 
-                       | _PAGE_RW | _PAGE_USER | _PAGE_PRESENT;
-
-       ((unsigned long *)swapper_pg_dir)[0] = 
-               ((virt_to_phys(page_table_copies)) & PAGE_MASK)
-               | _PAGE_RW | _PAGE_USER | _PAGE_PRESENT;
-#else
-       ((unsigned long *)swapper_pg_dir)[0] = 
-               (virt_to_phys(pg0) & PAGE_MASK)
-               | _PAGE_RW | _PAGE_USER | _PAGE_PRESENT;
-#endif
+
+       /* init lowmem identity mapping */
+       clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
+                       min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS));
+       flush_tlb_all();
 
        if(quad_boot) {
                printk("CPU %d: non extended Quad boot\n", cpu);
@@ -647,11 +627,7 @@ do_boot_cpu(__u8 cpu)
                udelay(100);
        }
        /* reset the page table */
-       swapper_pg_dir[0] = orig_swapper_pg_dir0;
-       local_flush_tlb();
-#ifdef CONFIG_M486
-       free_page((unsigned long)page_table_copies);
-#endif
+       zap_low_mappings();
          
        if (cpu_booted_map) {
                VDEBUG(("CPU%d: Booted successfully, back in CPU %d\n",
@@ -1068,20 +1044,11 @@ smp_call_function_interrupt(void)
        }
 }
 
-/* Call this function on all CPUs using the function_interrupt above 
-    <func> The function to run. This must be fast and non-blocking.
-    <info> An arbitrary pointer to pass to the function.
-    <retry> If true, keep retrying until ready.
-    <wait> If true, wait until function has completed on other CPUs.
-    [RETURNS] 0 on success, else a negative status code. Does not return until
-    remote CPUs are nearly ready to execute <<func>> or are or have executed.
-*/
-int
-smp_call_function (void (*func) (void *info), void *info, int retry,
-                  int wait)
+static int
+__smp_call_function_mask (void (*func) (void *info), void *info, int retry,
+                         int wait, __u32 mask)
 {
        struct call_data_struct data;
-       __u32 mask = cpus_addr(cpu_online_map)[0];
 
        mask &= ~(1<<smp_processor_id());
 
@@ -1102,7 +1069,7 @@ smp_call_function (void (*func) (void *info), void *info, int retry,
        call_data = &data;
        wmb();
        /* Send a message to all other CPUs and wait for them to respond */
-       send_CPI_allbutself(VIC_CALL_FUNCTION_CPI);
+       send_CPI(mask, VIC_CALL_FUNCTION_CPI);
 
        /* Wait for response */
        while (data.started)
@@ -1116,8 +1083,48 @@ smp_call_function (void (*func) (void *info), void *info, int retry,
 
        return 0;
 }
+
+/* Call this function on all CPUs using the function_interrupt above
+    <func> The function to run. This must be fast and non-blocking.
+    <info> An arbitrary pointer to pass to the function.
+    <retry> If true, keep retrying until ready.
+    <wait> If true, wait until function has completed on other CPUs.
+    [RETURNS] 0 on success, else a negative status code. Does not return until
+    remote CPUs are nearly ready to execute <<func>> or are or have executed.
+*/
+int
+smp_call_function(void (*func) (void *info), void *info, int retry,
+                  int wait)
+{
+       __u32 mask = cpus_addr(cpu_online_map)[0];
+
+       return __smp_call_function_mask(func, info, retry, wait, mask);
+}
 EXPORT_SYMBOL(smp_call_function);
 
+/*
+ * smp_call_function_single - Run a function on another CPU
+ * @func: The function to run. This must be fast and non-blocking.
+ * @info: An arbitrary pointer to pass to the function.
+ * @nonatomic: Currently unused.
+ * @wait: If true, wait until function has completed on other CPUs.
+ *
+ * Retrurns 0 on success, else a negative status code.
+ *
+ * Does not return until the remote CPU is nearly ready to execute <func>
+ * or is or has executed.
+ */
+
+int
+smp_call_function_single(int cpu, void (*func) (void *info), void *info,
+                        int nonatomic, int wait)
+{
+       __u32 mask = 1 << cpu;
+
+       return __smp_call_function_mask(func, info, nonatomic, wait, mask);
+}
+EXPORT_SYMBOL(smp_call_function_single);
+
 /* Sorry about the name.  In an APIC based system, the APICs
  * themselves are programmed to send a timer interrupt.  This is used
  * by linux to reschedule the processor.  Voyager doesn't have this,
index f398873..fdc1d92 100644 (file)
 #include <linux/kmod.h>
 #include <linux/completion.h>
 #include <linux/sched.h>
+#include <linux/kthread.h>
 #include <asm/desc.h>
 #include <asm/voyager.h>
 #include <asm/vic.h>
 #include <asm/mtrr.h>
 #include <asm/msr.h>
 
-#define THREAD_NAME "kvoyagerd"
 
-/* external variables */
-int kvoyagerd_running = 0;
-DECLARE_MUTEX_LOCKED(kvoyagerd_sem);
-
-static int thread(void *);
-
-static __u8 set_timeout = 0;
-
-/* Start the machine monitor thread.  Return 1 if OK, 0 if fail */
-static int __init
-voyager_thread_start(void)
-{
-       if(kernel_thread(thread, NULL, CLONE_KERNEL) < 0) {
-               /* This is serious, but not fatal */
-               printk(KERN_ERR "Voyager: Failed to create system monitor thread!!!\n");
-               return 1;
-       }
-       return 0;
-}
+struct task_struct *voyager_thread;
+static __u8 set_timeout;
 
 static int
 execute(const char *string)
@@ -110,31 +93,15 @@ check_continuing_condition(void)
        }
 }
 
-static void
-wakeup(unsigned long unused)
-{
-       up(&kvoyagerd_sem);
-}
-
 static int
 thread(void *unused)
 {
-       struct timer_list wakeup_timer;
-
-       kvoyagerd_running = 1;
-
-       daemonize(THREAD_NAME);
-
-       set_timeout = 0;
-
-       init_timer(&wakeup_timer);
-
-       sigfillset(&current->blocked);
-
        printk(KERN_NOTICE "Voyager starting monitor thread\n");
 
-       for(;;) {
-               down_interruptible(&kvoyagerd_sem);
+       for (;;) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule_timeout(set_timeout ? HZ : MAX_SCHEDULE_TIMEOUT);
+
                VDEBUG(("Voyager Daemon awoken\n"));
                if(voyager_status.request_from_kernel == 0) {
                        /* probably awoken from timeout */
@@ -143,20 +110,26 @@ thread(void *unused)
                        check_from_kernel();
                        voyager_status.request_from_kernel = 0;
                }
-               if(set_timeout) {
-                       del_timer(&wakeup_timer);
-                       wakeup_timer.expires = HZ + jiffies;
-                       wakeup_timer.function = wakeup;
-                       add_timer(&wakeup_timer);
-               }
        }
 }
 
+static int __init
+voyager_thread_start(void)
+{
+       voyager_thread = kthread_run(thread, NULL, "kvoyagerd");
+       if (IS_ERR(voyager_thread)) {
+               printk(KERN_ERR "Voyager: Failed to create system monitor thread.\n");
+               return PTR_ERR(voyager_thread);
+       }
+       return 0;
+}
+
+
 static void __exit
 voyager_thread_stop(void)
 {
-       /* FIXME: do nothing at the moment */
+       kthread_stop(voyager_thread);
 }
 
 module_init(voyager_thread_start);
-//module_exit(voyager_thread_stop);
+module_exit(voyager_thread_stop);
index 8053b17..b62eafb 100644 (file)
@@ -354,7 +354,7 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev)
                printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev));
        }
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
 
 /*
  * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A.
index 43005f0..bcd2f94 100644 (file)
@@ -246,8 +246,8 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask)
                        continue;
                if (!r->start && r->end) {
                        printk(KERN_ERR "PCI: Device %s not available "
-                               "because of resource collisions\n",
-                               pci_name(dev));
+                               "because of resource %d collisions\n",
+                               pci_name(dev), idx);
                        return -EINVAL;
                }
                if (r->flags & IORESOURCE_IO)
index e19185d..3b71f97 100644 (file)
@@ -14,6 +14,7 @@ config IA64
        select PCI if (!IA64_HP_SIM)
        select ACPI if (!IA64_HP_SIM)
        select PM if (!IA64_HP_SIM)
+       select ARCH_SUPPORTS_MSI
        default y
        help
          The Itanium Processor Family is Intel's 64-bit successor to
index fcf7f93..2c3f9df 100644 (file)
@@ -8,7 +8,6 @@
 
 #include <linux/types.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <asm/delay.h>
 #include <asm/sn/sn_sal.h>
 #include "ioerror.h"
index 49873aa..83f190f 100644 (file)
@@ -87,7 +87,6 @@ int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry)
        if (irq < 0)
                return irq;
 
-       set_irq_msi(irq, entry);
        /*
         * Set up the vector plumbing.  Let the prom (via sn_intr_alloc)
         * decide which cpu to direct this msi at by default.
@@ -144,10 +143,11 @@ int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry)
         */
        msg.data = 0x100 + irq;
 
+       set_irq_msi(irq, entry);
        write_msi_msg(irq, &msg);
        set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);
 
-       return irq;
+       return 0;
 }
 
 #ifdef CONFIG_SMP
index 5419acb..88fad85 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/netdevice.h>
index a8e1e60..b8536c7 100644 (file)
@@ -409,6 +409,9 @@ config STRAM_PROC
        help
          Say Y here to report ST-RAM usage statistics in /proc/stram.
 
+config ATARI_KBD_CORE
+       bool
+
 config HEARTBEAT
        bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
        default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300
index 34d826d..c20831a 100644 (file)
@@ -21,7 +21,7 @@ AS += -m68020
 LDFLAGS := -m m68kelf
 ifneq ($(COMPILE_ARCH),$(ARCH))
        # prefix for cross-compiling binaries
-       CROSS_COMPILE = m68k-linux-
+       CROSS_COMPILE = m68k-linux-gnu-
 endif
 
 ifdef CONFIG_SUN3
index 3204f41..3574853 100644 (file)
@@ -22,9 +22,7 @@
 #include <linux/vt_kern.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#ifdef CONFIG_ZORRO
 #include <linux/zorro.h>
-#endif
 
 #include <asm/bootinfo.h>
 #include <asm/setup.h>
@@ -62,55 +60,51 @@ static char s_cdtv[] __initdata = "CDTV";
 static char s_cd32[] __initdata = "CD32";
 static char s_draco[] __initdata = "Draco";
 static char *amiga_models[] __initdata = {
-    [AMI_500-AMI_500]          = s_a500,
-    [AMI_500PLUS-AMI_500]      = s_a500p,
-    [AMI_600-AMI_500]          = s_a600,
-    [AMI_1000-AMI_500]         = s_a1000,
-    [AMI_1200-AMI_500]         = s_a1200,
-    [AMI_2000-AMI_500]         = s_a2000,
-    [AMI_2500-AMI_500]         = s_a2500,
-    [AMI_3000-AMI_500]         = s_a3000,
-    [AMI_3000T-AMI_500]                = s_a3000t,
-    [AMI_3000PLUS-AMI_500]     = s_a3000p,
-    [AMI_4000-AMI_500]         = s_a4000,
-    [AMI_4000T-AMI_500]                = s_a4000t,
-    [AMI_CDTV-AMI_500]         = s_cdtv,
-    [AMI_CD32-AMI_500]         = s_cd32,
-    [AMI_DRACO-AMI_500]                = s_draco,
+       [AMI_500-AMI_500]       = s_a500,
+       [AMI_500PLUS-AMI_500]   = s_a500p,
+       [AMI_600-AMI_500]       = s_a600,
+       [AMI_1000-AMI_500]      = s_a1000,
+       [AMI_1200-AMI_500]      = s_a1200,
+       [AMI_2000-AMI_500]      = s_a2000,
+       [AMI_2500-AMI_500]      = s_a2500,
+       [AMI_3000-AMI_500]      = s_a3000,
+       [AMI_3000T-AMI_500]     = s_a3000t,
+       [AMI_3000PLUS-AMI_500]  = s_a3000p,
+       [AMI_4000-AMI_500]      = s_a4000,
+       [AMI_4000T-AMI_500]     = s_a4000t,
+       [AMI_CDTV-AMI_500]      = s_cdtv,
+       [AMI_CD32-AMI_500]      = s_cd32,
+       [AMI_DRACO-AMI_500]     = s_draco,
 };
 
 static char amiga_model_name[13] = "Amiga ";
 
-extern char m68k_debug_device[];
-
 static void amiga_sched_init(irq_handler_t handler);
 /* amiga specific irq functions */
-extern void amiga_init_IRQ (void);
+extern void amiga_init_IRQ(void);
 static void amiga_get_model(char *model);
 static int amiga_get_hardware_list(char *buffer);
 /* amiga specific timer functions */
-static unsigned long amiga_gettimeoffset (void);
-static int a3000_hwclk (int, struct rtc_time *);
-static int a2000_hwclk (int, struct rtc_time *);
-static int amiga_set_clock_mmss (unsigned long);
-static unsigned int amiga_get_ss (void);
-extern void amiga_mksound( unsigned int count, unsigned int ticks );
-static void amiga_reset (void);
+static unsigned long amiga_gettimeoffset(void);
+static int a3000_hwclk(int, struct rtc_time *);
+static int a2000_hwclk(int, struct rtc_time *);
+static int amiga_set_clock_mmss(unsigned long);
+static unsigned int amiga_get_ss(void);
+extern void amiga_mksound(unsigned int count, unsigned int ticks);
+static void amiga_reset(void);
 extern void amiga_init_sound(void);
-static void amiga_savekmsg_init(void);
 static void amiga_mem_console_write(struct console *co, const char *b,
                                    unsigned int count);
 void amiga_serial_console_write(struct console *co, const char *s,
                                unsigned int count);
-static void amiga_debug_init(void);
 #ifdef CONFIG_HEARTBEAT
 static void amiga_heartbeat(int on);
 #endif
 
 static struct console amiga_console_driver = {
-       .name =         "debug",
-       .flags =        CON_PRINTBUFFER,
-       .index =        -1,
+       .name   = "debug",
+       .flags  = CON_PRINTBUFFER,
+       .index  = -1,
 };
 
 
@@ -119,24 +113,24 @@ static struct console amiga_console_driver = {
      */
 
 static struct {
-    struct resource _ciab, _ciaa, _custom, _kickstart;
+       struct resource _ciab, _ciaa, _custom, _kickstart;
 } mb_resources = {
-    ._ciab = {
-       .name = "CIA B", .start = 0x00bfd000, .end = 0x00bfdfff
-    },
-    ._ciaa = {
-       .name = "CIA A", .start = 0x00bfe000, .end = 0x00bfefff
-    },
-    ._custom = {
-       .name = "Custom I/O", .start = 0x00dff000, .end = 0x00dfffff
-    },
-    ._kickstart = {
-       .name = "Kickstart ROM", .start = 0x00f80000, .end = 0x00ffffff
-    }
+       ._ciab = {
+               .name = "CIA B", .start = 0x00bfd000, .end = 0x00bfdfff
+       },
+       ._ciaa = {
+               .name = "CIA A", .start = 0x00bfe000, .end = 0x00bfefff
+       },
+       ._custom = {
+               .name = "Custom I/O", .start = 0x00dff000, .end = 0x00dfffff
+       },
+       ._kickstart = {
+               .name = "Kickstart ROM", .start = 0x00f80000, .end = 0x00ffffff
+       }
 };
 
 static struct resource rtc_resource = {
-    .start = 0x00dc0000, .end = 0x00dcffff
+       .start = 0x00dc0000, .end = 0x00dcffff
 };
 
 static struct resource ram_resource[NUM_MEMINFO];
@@ -148,57 +142,57 @@ static struct resource ram_resource[NUM_MEMINFO];
 
 int amiga_parse_bootinfo(const struct bi_record *record)
 {
-    int unknown = 0;
-    const unsigned long *data = record->data;
+       int unknown = 0;
+       const unsigned long *data = record->data;
 
-    switch (record->tag) {
+       switch (record->tag) {
        case BI_AMIGA_MODEL:
-           amiga_model = *data;
-           break;
+               amiga_model = *data;
+               break;
 
        case BI_AMIGA_ECLOCK:
-           amiga_eclock = *data;
-           break;
+               amiga_eclock = *data;
+               break;
 
        case BI_AMIGA_CHIPSET:
-           amiga_chipset = *data;
-           break;
+               amiga_chipset = *data;
+               break;
 
        case BI_AMIGA_CHIP_SIZE:
-           amiga_chip_size = *(const int *)data;
-           break;
+               amiga_chip_size = *(const int *)data;
+               break;
 
        case BI_AMIGA_VBLANK:
-           amiga_vblank = *(const unsigned char *)data;
-           break;
+               amiga_vblank = *(const unsigned char *)data;
+               break;
 
        case BI_AMIGA_PSFREQ:
-           amiga_psfreq = *(const unsigned char *)data;
-           break;
+               amiga_psfreq = *(const unsigned char *)data;
+               break;
 
        case BI_AMIGA_AUTOCON:
 #ifdef CONFIG_ZORRO
-           if (zorro_num_autocon < ZORRO_NUM_AUTO) {
-               const struct ConfigDev *cd = (struct ConfigDev *)data;
-               struct zorro_dev *dev = &zorro_autocon[zorro_num_autocon++];
-               dev->rom = cd->cd_Rom;
-               dev->slotaddr = cd->cd_SlotAddr;
-               dev->slotsize = cd->cd_SlotSize;
-               dev->resource.start = (unsigned long)cd->cd_BoardAddr;
-               dev->resource.end = dev->resource.start+cd->cd_BoardSize-1;
-           } else
-               printk("amiga_parse_bootinfo: too many AutoConfig devices\n");
+               if (zorro_num_autocon < ZORRO_NUM_AUTO) {
+                       const struct ConfigDev *cd = (struct ConfigDev *)data;
+                       struct zorro_dev *dev = &zorro_autocon[zorro_num_autocon++];
+                       dev->rom = cd->cd_Rom;
+                       dev->slotaddr = cd->cd_SlotAddr;
+                       dev->slotsize = cd->cd_SlotSize;
+                       dev->resource.start = (unsigned long)cd->cd_BoardAddr;
+                       dev->resource.end = dev->resource.start + cd->cd_BoardSize - 1;
+               } else
+                       printk("amiga_parse_bootinfo: too many AutoConfig devices\n");
 #endif /* CONFIG_ZORRO */
-           break;
+               break;
 
        case BI_AMIGA_SERPER:
-           /* serial port period: ignored here */
-           break;
+               /* serial port period: ignored here */
+               break;
 
        default:
-           unknown = 1;
-    }
-    return(unknown);
+               unknown = 1;
+       }
+       return unknown;
 }
 
     /*
@@ -207,159 +201,159 @@ int amiga_parse_bootinfo(const struct bi_record *record)
 
 static void __init amiga_identify(void)
 {
-  /* Fill in some default values, if necessary */
-  if (amiga_eclock == 0)
-    amiga_eclock = 709379;
-
-  memset(&amiga_hw_present, 0, sizeof(amiga_hw_present));
-
-  printk("Amiga hardware found: ");
-  if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) {
-    printk("[%s] ", amiga_models[amiga_model-AMI_500]);
-    strcat(amiga_model_name, amiga_models[amiga_model-AMI_500]);
-  }
-
-  switch(amiga_model) {
-  case AMI_UNKNOWN:
-    goto Generic;
-
-  case AMI_600:
-  case AMI_1200:
-    AMIGAHW_SET(A1200_IDE);
-    AMIGAHW_SET(PCMCIA);
-  case AMI_500:
-  case AMI_500PLUS:
-  case AMI_1000:
-  case AMI_2000:
-  case AMI_2500:
-    AMIGAHW_SET(A2000_CLK);    /* Is this correct for all models? */
-    goto Generic;
-
-  case AMI_3000:
-  case AMI_3000T:
-    AMIGAHW_SET(AMBER_FF);
-    AMIGAHW_SET(MAGIC_REKICK);
-    /* fall through */
-  case AMI_3000PLUS:
-    AMIGAHW_SET(A3000_SCSI);
-    AMIGAHW_SET(A3000_CLK);
-    AMIGAHW_SET(ZORRO3);
-    goto Generic;
-
-  case AMI_4000T:
-    AMIGAHW_SET(A4000_SCSI);
-    /* fall through */
-  case AMI_4000:
-    AMIGAHW_SET(A4000_IDE);
-    AMIGAHW_SET(A3000_CLK);
-    AMIGAHW_SET(ZORRO3);
-    goto Generic;
-
-  case AMI_CDTV:
-  case AMI_CD32:
-    AMIGAHW_SET(CD_ROM);
-    AMIGAHW_SET(A2000_CLK);             /* Is this correct? */
-    goto Generic;
-
-  Generic:
-    AMIGAHW_SET(AMI_VIDEO);
-    AMIGAHW_SET(AMI_BLITTER);
-    AMIGAHW_SET(AMI_AUDIO);
-    AMIGAHW_SET(AMI_FLOPPY);
-    AMIGAHW_SET(AMI_KEYBOARD);
-    AMIGAHW_SET(AMI_MOUSE);
-    AMIGAHW_SET(AMI_SERIAL);
-    AMIGAHW_SET(AMI_PARALLEL);
-    AMIGAHW_SET(CHIP_RAM);
-    AMIGAHW_SET(PAULA);
-
-    switch(amiga_chipset) {
-    case CS_OCS:
-    case CS_ECS:
-    case CS_AGA:
-      switch (amiga_custom.deniseid & 0xf) {
-      case 0x0c:
-       AMIGAHW_SET(DENISE_HR);
-       break;
-      case 0x08:
-       AMIGAHW_SET(LISA);
-       break;
-      }
-      break;
-    default:
-      AMIGAHW_SET(DENISE);
-      break;
-    }
-    switch ((amiga_custom.vposr>>8) & 0x7f) {
-    case 0x00:
-      AMIGAHW_SET(AGNUS_PAL);
-      break;
-    case 0x10:
-      AMIGAHW_SET(AGNUS_NTSC);
-      break;
-    case 0x20:
-    case 0x21:
-      AMIGAHW_SET(AGNUS_HR_PAL);
-      break;
-    case 0x30:
-    case 0x31:
-      AMIGAHW_SET(AGNUS_HR_NTSC);
-      break;
-    case 0x22:
-    case 0x23:
-      AMIGAHW_SET(ALICE_PAL);
-      break;
-    case 0x32:
-    case 0x33:
-      AMIGAHW_SET(ALICE_NTSC);
-      break;
-    }
-    AMIGAHW_SET(ZORRO);
-    break;
-
-  case AMI_DRACO:
-    panic("No support for Draco yet");
-
-  default:
-    panic("Unknown Amiga Model");
-  }
+       /* Fill in some default values, if necessary */
+       if (amiga_eclock == 0)
+               amiga_eclock = 709379;
 
-#define AMIGAHW_ANNOUNCE(name, str)                    \
-  if (AMIGAHW_PRESENT(name))                           \
-    printk(str)
-
-  AMIGAHW_ANNOUNCE(AMI_VIDEO, "VIDEO ");
-  AMIGAHW_ANNOUNCE(AMI_BLITTER, "BLITTER ");
-  AMIGAHW_ANNOUNCE(AMBER_FF, "AMBER_FF ");
-  AMIGAHW_ANNOUNCE(AMI_AUDIO, "AUDIO ");
-  AMIGAHW_ANNOUNCE(AMI_FLOPPY, "FLOPPY ");
-  AMIGAHW_ANNOUNCE(A3000_SCSI, "A3000_SCSI ");
-  AMIGAHW_ANNOUNCE(A4000_SCSI, "A4000_SCSI ");
-  AMIGAHW_ANNOUNCE(A1200_IDE, "A1200_IDE ");
-  AMIGAHW_ANNOUNCE(A4000_IDE, "A4000_IDE ");
-  AMIGAHW_ANNOUNCE(CD_ROM, "CD_ROM ");
-  AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "KEYBOARD ");
-  AMIGAHW_ANNOUNCE(AMI_MOUSE, "MOUSE ");
-  AMIGAHW_ANNOUNCE(AMI_SERIAL, "SERIAL ");
-  AMIGAHW_ANNOUNCE(AMI_PARALLEL, "PARALLEL ");
-  AMIGAHW_ANNOUNCE(A2000_CLK, "A2000_CLK ");
-  AMIGAHW_ANNOUNCE(A3000_CLK, "A3000_CLK ");
-  AMIGAHW_ANNOUNCE(CHIP_RAM, "CHIP_RAM ");
-  AMIGAHW_ANNOUNCE(PAULA, "PAULA ");
-  AMIGAHW_ANNOUNCE(DENISE, "DENISE ");
-  AMIGAHW_ANNOUNCE(DENISE_HR, "DENISE_HR ");
-  AMIGAHW_ANNOUNCE(LISA, "LISA ");
-  AMIGAHW_ANNOUNCE(AGNUS_PAL, "AGNUS_PAL ");
-  AMIGAHW_ANNOUNCE(AGNUS_NTSC, "AGNUS_NTSC ");
-  AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "AGNUS_HR_PAL ");
-  AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "AGNUS_HR_NTSC ");
-  AMIGAHW_ANNOUNCE(ALICE_PAL, "ALICE_PAL ");
-  AMIGAHW_ANNOUNCE(ALICE_NTSC, "ALICE_NTSC ");
-  AMIGAHW_ANNOUNCE(MAGIC_REKICK, "MAGIC_REKICK ");
-  AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA ");
-  if (AMIGAHW_PRESENT(ZORRO))
-    printk("ZORRO%s ", AMIGAHW_PRESENT(ZORRO3) ? "3" : "");
-  printk("\n");
+       memset(&amiga_hw_present, 0, sizeof(amiga_hw_present));
+
+       printk("Amiga hardware found: ");
+       if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) {
+               printk("[%s] ", amiga_models[amiga_model-AMI_500]);
+               strcat(amiga_model_name, amiga_models[amiga_model-AMI_500]);
+       }
+
+       switch (amiga_model) {
+       case AMI_UNKNOWN:
+               goto Generic;
+
+       case AMI_600:
+       case AMI_1200:
+               AMIGAHW_SET(A1200_IDE);
+               AMIGAHW_SET(PCMCIA);
+       case AMI_500:
+       case AMI_500PLUS:
+       case AMI_1000:
+       case AMI_2000:
+       case AMI_2500:
+               AMIGAHW_SET(A2000_CLK); /* Is this correct for all models? */
+               goto Generic;
+
+       case AMI_3000:
+       case AMI_3000T:
+               AMIGAHW_SET(AMBER_FF);
+               AMIGAHW_SET(MAGIC_REKICK);
+               /* fall through */
+       case AMI_3000PLUS:
+               AMIGAHW_SET(A3000_SCSI);
+               AMIGAHW_SET(A3000_CLK);
+               AMIGAHW_SET(ZORRO3);
+               goto Generic;
+
+       case AMI_4000T:
+               AMIGAHW_SET(A4000_SCSI);
+               /* fall through */
+       case AMI_4000:
+               AMIGAHW_SET(A4000_IDE);
+               AMIGAHW_SET(A3000_CLK);
+               AMIGAHW_SET(ZORRO3);
+               goto Generic;
+
+       case AMI_CDTV:
+       case AMI_CD32:
+               AMIGAHW_SET(CD_ROM);
+               AMIGAHW_SET(A2000_CLK);             /* Is this correct? */
+               goto Generic;
+
+       Generic:
+               AMIGAHW_SET(AMI_VIDEO);
+               AMIGAHW_SET(AMI_BLITTER);
+               AMIGAHW_SET(AMI_AUDIO);
+               AMIGAHW_SET(AMI_FLOPPY);
+               AMIGAHW_SET(AMI_KEYBOARD);
+               AMIGAHW_SET(AMI_MOUSE);
+               AMIGAHW_SET(AMI_SERIAL);
+               AMIGAHW_SET(AMI_PARALLEL);
+               AMIGAHW_SET(CHIP_RAM);
+               AMIGAHW_SET(PAULA);
+
+               switch (amiga_chipset) {
+               case CS_OCS:
+               case CS_ECS:
+               case CS_AGA:
+                       switch (amiga_custom.deniseid & 0xf) {
+                       case 0x0c:
+                               AMIGAHW_SET(DENISE_HR);
+                               break;
+                       case 0x08:
+                               AMIGAHW_SET(LISA);
+                               break;
+                       }
+                       break;
+               default:
+                       AMIGAHW_SET(DENISE);
+                       break;
+               }
+               switch ((amiga_custom.vposr>>8) & 0x7f) {
+               case 0x00:
+                       AMIGAHW_SET(AGNUS_PAL);
+                       break;
+               case 0x10:
+                       AMIGAHW_SET(AGNUS_NTSC);
+                       break;
+               case 0x20:
+               case 0x21:
+                       AMIGAHW_SET(AGNUS_HR_PAL);
+                       break;
+               case 0x30:
+               case 0x31:
+                       AMIGAHW_SET(AGNUS_HR_NTSC);
+                       break;
+               case 0x22:
+               case 0x23:
+                       AMIGAHW_SET(ALICE_PAL);
+                       break;
+               case 0x32:
+               case 0x33:
+                       AMIGAHW_SET(ALICE_NTSC);
+                       break;
+               }
+               AMIGAHW_SET(ZORRO);
+               break;
+
+       case AMI_DRACO:
+               panic("No support for Draco yet");
+
+       default:
+               panic("Unknown Amiga Model");
+       }
+
+#define AMIGAHW_ANNOUNCE(name, str)            \
+       if (AMIGAHW_PRESENT(name))              \
+               printk(str)
+
+       AMIGAHW_ANNOUNCE(AMI_VIDEO, "VIDEO ");
+       AMIGAHW_ANNOUNCE(AMI_BLITTER, "BLITTER ");
+       AMIGAHW_ANNOUNCE(AMBER_FF, "AMBER_FF ");
+       AMIGAHW_ANNOUNCE(AMI_AUDIO, "AUDIO ");
+       AMIGAHW_ANNOUNCE(AMI_FLOPPY, "FLOPPY ");
+       AMIGAHW_ANNOUNCE(A3000_SCSI, "A3000_SCSI ");
+       AMIGAHW_ANNOUNCE(A4000_SCSI, "A4000_SCSI ");
+       AMIGAHW_ANNOUNCE(A1200_IDE, "A1200_IDE ");
+       AMIGAHW_ANNOUNCE(A4000_IDE, "A4000_IDE ");
+       AMIGAHW_ANNOUNCE(CD_ROM, "CD_ROM ");
+       AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "KEYBOARD ");
+       AMIGAHW_ANNOUNCE(AMI_MOUSE, "MOUSE ");
+       AMIGAHW_ANNOUNCE(AMI_SERIAL, "SERIAL ");
+       AMIGAHW_ANNOUNCE(AMI_PARALLEL, "PARALLEL ");
+       AMIGAHW_ANNOUNCE(A2000_CLK, "A2000_CLK ");
+       AMIGAHW_ANNOUNCE(A3000_CLK, "A3000_CLK ");
+       AMIGAHW_ANNOUNCE(CHIP_RAM, "CHIP_RAM ");
+       AMIGAHW_ANNOUNCE(PAULA, "PAULA ");
+       AMIGAHW_ANNOUNCE(DENISE, "DENISE ");
+       AMIGAHW_ANNOUNCE(DENISE_HR, "DENISE_HR ");
+       AMIGAHW_ANNOUNCE(LISA, "LISA ");
+       AMIGAHW_ANNOUNCE(AGNUS_PAL, "AGNUS_PAL ");
+       AMIGAHW_ANNOUNCE(AGNUS_NTSC, "AGNUS_NTSC ");
+       AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "AGNUS_HR_PAL ");
+       AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "AGNUS_HR_NTSC ");
+       AMIGAHW_ANNOUNCE(ALICE_PAL, "ALICE_PAL ");
+       AMIGAHW_ANNOUNCE(ALICE_NTSC, "ALICE_NTSC ");
+       AMIGAHW_ANNOUNCE(MAGIC_REKICK, "MAGIC_REKICK ");
+       AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA ");
+       if (AMIGAHW_PRESENT(ZORRO))
+               printk("ZORRO%s ", AMIGAHW_PRESENT(ZORRO3) ? "3" : "");
+       printk("\n");
 
 #undef AMIGAHW_ANNOUNCE
 }
@@ -370,119 +364,105 @@ static void __init amiga_identify(void)
 
 void __init config_amiga(void)
 {
-  int i;
-
-  amiga_debug_init();
-  amiga_identify();
-
-  /* Yuk, we don't have PCI memory */
-  iomem_resource.name = "Memory";
-  for (i = 0; i < 4; i++)
-    request_resource(&iomem_resource, &((struct resource *)&mb_resources)[i]);
-
-  mach_sched_init      = amiga_sched_init;
-  mach_init_IRQ        = amiga_init_IRQ;
-  mach_get_model       = amiga_get_model;
-  mach_get_hardware_list = amiga_get_hardware_list;
-  mach_gettimeoffset   = amiga_gettimeoffset;
-  if (AMIGAHW_PRESENT(A3000_CLK)){
-    mach_hwclk         = a3000_hwclk;
-    rtc_resource.name = "A3000 RTC";
-    request_resource(&iomem_resource, &rtc_resource);
-  }
-  else{ /* if (AMIGAHW_PRESENT(A2000_CLK)) */
-    mach_hwclk         = a2000_hwclk;
-    rtc_resource.name = "A2000 RTC";
-    request_resource(&iomem_resource, &rtc_resource);
-  }
-
-  mach_max_dma_address = 0xffffffff; /*
-                                     * default MAX_DMA=0xffffffff
-                                     * on all machines. If we don't
-                                     * do so, the SCSI code will not
-                                     * be able to allocate any mem
-                                     * for transfers, unless we are
-                                     * dealing with a Z2 mem only
-                                     * system.                  /Jes
-                                     */
-
-  mach_set_clock_mmss  = amiga_set_clock_mmss;
-  mach_get_ss          = amiga_get_ss;
-  mach_reset           = amiga_reset;
+       int i;
+
+       amiga_identify();
+
+       /* Yuk, we don't have PCI memory */
+       iomem_resource.name = "Memory";
+       for (i = 0; i < 4; i++)
+               request_resource(&iomem_resource, &((struct resource *)&mb_resources)[i]);
+
+       mach_sched_init      = amiga_sched_init;
+       mach_init_IRQ        = amiga_init_IRQ;
+       mach_get_model       = amiga_get_model;
+       mach_get_hardware_list = amiga_get_hardware_list;
+       mach_gettimeoffset   = amiga_gettimeoffset;
+       if (AMIGAHW_PRESENT(A3000_CLK)) {
+               mach_hwclk         = a3000_hwclk;
+               rtc_resource.name = "A3000 RTC";
+               request_resource(&iomem_resource, &rtc_resource);
+       } else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ {
+               mach_hwclk         = a2000_hwclk;
+               rtc_resource.name = "A2000 RTC";
+               request_resource(&iomem_resource, &rtc_resource);
+       }
+
+       /*
+        * default MAX_DMA=0xffffffff on all machines. If we don't do so, the SCSI
+        * code will not be able to allocate any mem for transfers, unless we are
+        * dealing with a Z2 mem only system.                  /Jes
+        */
+       mach_max_dma_address = 0xffffffff;
+
+       mach_set_clock_mmss  = amiga_set_clock_mmss;
+       mach_get_ss          = amiga_get_ss;
+       mach_reset           = amiga_reset;
 #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
-  mach_beep            = amiga_mksound;
+       mach_beep            = amiga_mksound;
 #endif
 
 #ifdef CONFIG_HEARTBEAT
-  mach_heartbeat = amiga_heartbeat;
+       mach_heartbeat = amiga_heartbeat;
 #endif
 
-  /* Fill in the clock values (based on the 700 kHz E-Clock) */
-  amiga_masterclock = 40*amiga_eclock; /* 28 MHz */
-  amiga_colorclock = 5*amiga_eclock;   /* 3.5 MHz */
-
-  /* clear all DMA bits */
-  amiga_custom.dmacon = DMAF_ALL;
-  /* ensure that the DMA master bit is set */
-  amiga_custom.dmacon = DMAF_SETCLR | DMAF_MASTER;
-
-  /* don't use Z2 RAM as system memory on Z3 capable machines */
-  if (AMIGAHW_PRESENT(ZORRO3)) {
-    int i, j;
-    u32 disabled_z2mem = 0;
-    for (i = 0; i < m68k_num_memory; i++)
-      if (m68k_memory[i].addr < 16*1024*1024) {
-       if (i == 0) {
-         /* don't cut off the branch we're sitting on */
-         printk("Warning: kernel runs in Zorro II memory\n");
-         continue;
+       /* Fill in the clock values (based on the 700 kHz E-Clock) */
+       amiga_masterclock = 40*amiga_eclock;    /* 28 MHz */
+       amiga_colorclock = 5*amiga_eclock;      /* 3.5 MHz */
+
+       /* clear all DMA bits */
+       amiga_custom.dmacon = DMAF_ALL;
+       /* ensure that the DMA master bit is set */
+       amiga_custom.dmacon = DMAF_SETCLR | DMAF_MASTER;
+
+       /* don't use Z2 RAM as system memory on Z3 capable machines */
+       if (AMIGAHW_PRESENT(ZORRO3)) {
+               int i, j;
+               u32 disabled_z2mem = 0;
+
+               for (i = 0; i < m68k_num_memory; i++) {
+                       if (m68k_memory[i].addr < 16*1024*1024) {
+                               if (i == 0) {
+                                       /* don't cut off the branch we're sitting on */
+                                       printk("Warning: kernel runs in Zorro II memory\n");
+                                       continue;
+                               }
+                               disabled_z2mem += m68k_memory[i].size;
+                               m68k_num_memory--;
+                               for (j = i; j < m68k_num_memory; j++)
+                                       m68k_memory[j] = m68k_memory[j+1];
+                               i--;
+                       }
+               }
+               if (disabled_z2mem)
+               printk("%dK of Zorro II memory will not be used as system memory\n",
+               disabled_z2mem>>10);
        }
-       disabled_z2mem += m68k_memory[i].size;
-       m68k_num_memory--;
-       for (j = i; j < m68k_num_memory; j++)
-         m68k_memory[j] = m68k_memory[j+1];
-       i--;
-      }
-    if (disabled_z2mem)
-      printk("%dK of Zorro II memory will not be used as system memory\n",
-            disabled_z2mem>>10);
-  }
-
-  /* request all RAM */
-  for (i = 0; i < m68k_num_memory; i++) {
-    ram_resource[i].name =
-      (m68k_memory[i].addr >= 0x01000000) ? "32-bit Fast RAM" :
-      (m68k_memory[i].addr < 0x00c00000) ? "16-bit Fast RAM" :
-      "16-bit Slow RAM";
-    ram_resource[i].start = m68k_memory[i].addr;
-    ram_resource[i].end = m68k_memory[i].addr+m68k_memory[i].size-1;
-    request_resource(&iomem_resource, &ram_resource[i]);
-  }
-
-  /* initialize chipram allocator */
-  amiga_chip_init ();
-
-  /* debugging using chipram */
-  if (!strcmp( m68k_debug_device, "mem" )){
-         if (!AMIGAHW_PRESENT(CHIP_RAM))
-                 printk("Warning: no chipram present for debugging\n");
-         else {
-                 amiga_savekmsg_init();
-                 amiga_console_driver.write = amiga_mem_console_write;
-                 register_console(&amiga_console_driver);
-         }
-  }
-
-  /* our beloved beeper */
-  if (AMIGAHW_PRESENT(AMI_AUDIO))
-         amiga_init_sound();
-
-  /*
-   * if it is an A3000, set the magic bit that forces
-   * a hard rekick
-   */
-  if (AMIGAHW_PRESENT(MAGIC_REKICK))
-         *(unsigned char *)ZTWO_VADDR(0xde0002) |= 0x80;
+
+       /* request all RAM */
+       for (i = 0; i < m68k_num_memory; i++) {
+               ram_resource[i].name =
+                       (m68k_memory[i].addr >= 0x01000000) ? "32-bit Fast RAM" :
+                       (m68k_memory[i].addr < 0x00c00000) ? "16-bit Fast RAM" :
+                       "16-bit Slow RAM";
+               ram_resource[i].start = m68k_memory[i].addr;
+               ram_resource[i].end = m68k_memory[i].addr+m68k_memory[i].size-1;
+               request_resource(&iomem_resource, &ram_resource[i]);
+       }
+
+       /* initialize chipram allocator */
+       amiga_chip_init();
+
+       /* our beloved beeper */
+       if (AMIGAHW_PRESENT(AMI_AUDIO))
+               amiga_init_sound();
+
+       /*
+        * if it is an A3000, set the magic bit that forces
+        * a hard rekick
+        */
+       if (AMIGAHW_PRESENT(MAGIC_REKICK))
+               *(unsigned char *)ZTWO_VADDR(0xde0002) |= 0x80;
 }
 
 static unsigned short jiffy_ticks;
@@ -490,12 +470,12 @@ static unsigned short jiffy_ticks;
 static void __init amiga_sched_init(irq_handler_t timer_routine)
 {
        static struct resource sched_res = {
-           .name = "timer", .start = 0x00bfd400, .end = 0x00bfd5ff,
+               .name = "timer", .start = 0x00bfd400, .end = 0x00bfd5ff,
        };
        jiffy_ticks = (amiga_eclock+HZ/2)/HZ;
 
        if (request_resource(&mb_resources._ciab, &sched_res))
-           printk("Cannot allocate ciab.ta{lo,hi}\n");
+               printk("Cannot allocate ciab.ta{lo,hi}\n");
        ciab.cra &= 0xC0;   /* turn off timer A, continuous mode, from Eclk */
        ciab.talo = jiffy_ticks % 256;
        ciab.tahi = jiffy_ticks / 256;
@@ -513,7 +493,7 @@ static void __init amiga_sched_init(irq_handler_t timer_routine)
 #define TICK_SIZE 10000
 
 /* This is always executed with interrupts disabled.  */
-static unsigned long amiga_gettimeoffset (void)
+static unsigned long amiga_gettimeoffset(void)
 {
        unsigned short hi, lo, hi2;
        unsigned long ticks, offset = 0;
@@ -585,15 +565,15 @@ static int a2000_hwclk(int op, struct rtc_time *t)
 
        tod_2000.cntrl1 = TOD2000_CNTRL1_HOLD;
 
-       while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--)
-       {
-               tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
-               udelay(70);
-               tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
+       while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--) {
+               tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
+               udelay(70);
+               tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
        }
 
        if (!cnt)
-               printk(KERN_INFO "hwclk: timed out waiting for RTC (0x%x)\n", tod_2000.cntrl1);
+               printk(KERN_INFO "hwclk: timed out waiting for RTC (0x%x)\n",
+                       tod_2000.cntrl1);
 
        if (!op) { /* read */
                t->tm_sec  = tod_2000.second1     * 10 + tod_2000.second2;
@@ -606,7 +586,7 @@ static int a2000_hwclk(int op, struct rtc_time *t)
                if (t->tm_year <= 69)
                        t->tm_year += 100;
 
-               if (!(tod_2000.cntrl3 & TOD2000_CNTRL3_24HMODE)){
+               if (!(tod_2000.cntrl3 & TOD2000_CNTRL3_24HMODE)) {
                        if (!(tod_2000.hour1 & TOD2000_HOUR1_PM) && t->tm_hour == 12)
                                t->tm_hour = 0;
                        else if ((tod_2000.hour1 & TOD2000_HOUR1_PM) && t->tm_hour != 12)
@@ -642,7 +622,7 @@ static int a2000_hwclk(int op, struct rtc_time *t)
        return 0;
 }
 
-static int amiga_set_clock_mmss (unsigned long nowtime)
+static int amiga_set_clock_mmss(unsigned long nowtime)
 {
        short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
 
@@ -660,8 +640,7 @@ static int amiga_set_clock_mmss (unsigned long nowtime)
 
                tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
 
-               while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--)
-               {
+               while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--) {
                        tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
                        udelay(70);
                        tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
@@ -681,7 +660,7 @@ static int amiga_set_clock_mmss (unsigned long nowtime)
        return 0;
 }
 
-static unsigned int amiga_get_ss( void )
+static unsigned int amiga_get_ss(void)
 {
        unsigned int s;
 
@@ -695,71 +674,72 @@ static unsigned int amiga_get_ss( void )
        return s;
 }
 
-static NORET_TYPE void amiga_reset( void )
+static NORET_TYPE void amiga_reset(void)
     ATTRIB_NORET;
 
-static void amiga_reset (void)
+static void amiga_reset(void)
 {
-  unsigned long jmp_addr040 = virt_to_phys(&&jmp_addr_label040);
-  unsigned long jmp_addr = virt_to_phys(&&jmp_addr_label);
-
-  local_irq_disable();
-  if (CPU_IS_040_OR_060)
-    /* Setup transparent translation registers for mapping
-     * of 16 MB kernel segment before disabling translation
-     */
-    __asm__ __volatile__
-      ("movel    %0,%/d0\n\t"
-       "andl     #0xff000000,%/d0\n\t"
-       "orw      #0xe020,%/d0\n\t"   /* map 16 MB, enable, cacheable */
-       ".chip    68040\n\t"
-       "movec    %%d0,%%itt0\n\t"
-       "movec    %%d0,%%dtt0\n\t"
-       ".chip    68k\n\t"
-       "jmp      %0@\n\t"
-       : /* no outputs */
-       : "a" (jmp_addr040));
-  else
-    /* for 680[23]0, just disable translation and jump to the physical
-     * address of the label
-     */
-    __asm__ __volatile__
-      ("pmove  %/tc,%@\n\t"
-       "bclr   #7,%@\n\t"
-       "pmove  %@,%/tc\n\t"
-       "jmp    %0@\n\t"
-       : /* no outputs */
-       : "a" (jmp_addr));
- jmp_addr_label040:
-  /* disable translation on '040 now */
-  __asm__ __volatile__
-    ("moveq #0,%/d0\n\t"
-     ".chip 68040\n\t"
-     "movec %%d0,%%tc\n\t"     /* disable MMU */
-     ".chip 68k\n\t"
-     : /* no outputs */
-     : /* no inputs */
-     : "d0");
-
- jmp_addr_label:
-  /* pickup reset address from AmigaOS ROM, reset devices and jump
-   * to reset address
-   */
-  __asm__ __volatile__
-    ("movew #0x2700,%/sr\n\t"
-     "leal  0x01000000,%/a0\n\t"
-     "subl  %/a0@(-0x14),%/a0\n\t"
-     "movel %/a0@(4),%/a0\n\t"
-     "subql #2,%/a0\n\t"
-     "bra   1f\n\t"
-     /* align on a longword boundary */
-     __ALIGN_STR "\n"
-     "1:\n\t"
-     "reset\n\t"
-     "jmp   %/a0@" : /* Just that gcc scans it for % escapes */ );
-
-  for (;;);
-
+       unsigned long jmp_addr040 = virt_to_phys(&&jmp_addr_label040);
+       unsigned long jmp_addr = virt_to_phys(&&jmp_addr_label);
+
+       local_irq_disable();
+       if (CPU_IS_040_OR_060)
+               /* Setup transparent translation registers for mapping
+                * of 16 MB kernel segment before disabling translation
+                */
+               asm volatile ("\n"
+                       "       move.l  %0,%%d0\n"
+                       "       and.l   #0xff000000,%%d0\n"
+                       "       or.w    #0xe020,%%d0\n"   /* map 16 MB, enable, cacheable */
+                       "       .chip   68040\n"
+                       "       movec   %%d0,%%itt0\n"
+                       "       movec   %%d0,%%dtt0\n"
+                       "       .chip   68k\n"
+                       "       jmp     %0@\n"
+                       : /* no outputs */
+                       : "a" (jmp_addr040)
+                       : "d0");
+       else
+               /* for 680[23]0, just disable translation and jump to the physical
+                * address of the label
+                */
+               asm volatile ("\n"
+                       "       pmove   %%tc,%@\n"
+                       "       bclr    #7,%@\n"
+                       "       pmove   %@,%%tc\n"
+                       "       jmp     %0@\n"
+                       : /* no outputs */
+                       : "a" (jmp_addr));
+jmp_addr_label040:
+       /* disable translation on '040 now */
+       asm volatile ("\n"
+               "       moveq   #0,%%d0\n"
+               "       .chip   68040\n"
+               "       movec   %%d0,%%tc\n"    /* disable MMU */
+               "       .chip   68k\n"
+               : /* no outputs */
+               : /* no inputs */
+               : "d0");
+
+       jmp_addr_label:
+       /* pickup reset address from AmigaOS ROM, reset devices and jump
+        * to reset address
+        */
+       asm volatile ("\n"
+               "       move.w  #0x2700,%sr\n"
+               "       lea     0x01000000,%a0\n"
+               "       sub.l   %a0@(-0x14),%a0\n"
+               "       move.l  %a0@(4),%a0\n"
+               "       subq.l  #2,%a0\n"
+               "       jra     1f\n"
+               /* align on a longword boundary */
+               "       " __ALIGN_STR "\n"
+               "1:\n"
+               "       reset\n"
+               "       jmp   %a0@");
+
+       for (;;)
+               ;
 }
 
 
@@ -773,11 +753,11 @@ static void amiga_reset (void)
 #define SAVEKMSG_MAGIC2                0x4B4D5347      /* 'KMSG' */
 
 struct savekmsg {
-    unsigned long magic1;              /* SAVEKMSG_MAGIC1 */
-    unsigned long magic2;              /* SAVEKMSG_MAGIC2 */
-    unsigned long magicptr;            /* address of magic1 */
-    unsigned long size;
-    char data[0];
+       unsigned long magic1;           /* SAVEKMSG_MAGIC1 */
+       unsigned long magic2;           /* SAVEKMSG_MAGIC2 */
+       unsigned long magicptr;         /* address of magic1 */
+       unsigned long size;
+       char data[0];
 };
 
 static struct savekmsg *savekmsg;
@@ -785,113 +765,132 @@ static struct savekmsg *savekmsg;
 static void amiga_mem_console_write(struct console *co, const char *s,
                                    unsigned int count)
 {
-    if (savekmsg->size+count <= SAVEKMSG_MAXMEM-sizeof(struct savekmsg)) {
-        memcpy(savekmsg->data+savekmsg->size, s, count);
-        savekmsg->size += count;
-    }
+       if (savekmsg->size + count <= SAVEKMSG_MAXMEM-sizeof(struct savekmsg)) {
+               memcpy(savekmsg->data + savekmsg->size, s, count);
+               savekmsg->size += count;
+       }
 }
 
-static void amiga_savekmsg_init(void)
+static int __init amiga_savekmsg_setup(char *arg)
 {
-    static struct resource debug_res = { .name = "Debug" };
+       static struct resource debug_res = { .name = "Debug" };
+
+       if (!MACH_IS_AMIGA || strcmp(arg, "mem"))
+               goto done;
+
+       if (!AMIGAHW_PRESENT(CHIP_RAM)) {
+               printk("Warning: no chipram present for debugging\n");
+               goto done;
+       }
 
-    savekmsg = amiga_chip_alloc_res(SAVEKMSG_MAXMEM, &debug_res);
-    savekmsg->magic1 = SAVEKMSG_MAGIC1;
-    savekmsg->magic2 = SAVEKMSG_MAGIC2;
-    savekmsg->magicptr = ZTWO_PADDR(savekmsg);
-    savekmsg->size = 0;
+       savekmsg = amiga_chip_alloc_res(SAVEKMSG_MAXMEM, &debug_res);
+       savekmsg->magic1 = SAVEKMSG_MAGIC1;
+       savekmsg->magic2 = SAVEKMSG_MAGIC2;
+       savekmsg->magicptr = ZTWO_PADDR(savekmsg);
+       savekmsg->size = 0;
+
+       amiga_console_driver.write = amiga_mem_console_write;
+       register_console(&amiga_console_driver);
+
+done:
+       return 0;
 }
 
+early_param("debug", amiga_savekmsg_setup);
+
 static void amiga_serial_putc(char c)
 {
-    amiga_custom.serdat = (unsigned char)c | 0x100;
-    while (!(amiga_custom.serdatr & 0x2000))
-       ;
+       amiga_custom.serdat = (unsigned char)c | 0x100;
+       while (!(amiga_custom.serdatr & 0x2000))
+               ;
 }
 
 void amiga_serial_console_write(struct console *co, const char *s,
-                                      unsigned int count)
+                               unsigned int count)
 {
-    while (count--) {
-       if (*s == '\n')
-           amiga_serial_putc('\r');
-       amiga_serial_putc(*s++);
-    }
+       while (count--) {
+               if (*s == '\n')
+                       amiga_serial_putc('\r');
+               amiga_serial_putc(*s++);
+       }
 }
 
 #ifdef CONFIG_SERIAL_CONSOLE
 void amiga_serial_puts(const char *s)
 {
-    amiga_serial_console_write(NULL, s, strlen(s));
+       amiga_serial_console_write(NULL, s, strlen(s));
 }
 
 int amiga_serial_console_wait_key(struct console *co)
 {
-    int ch;
-
-    while (!(amiga_custom.intreqr & IF_RBF))
-       barrier();
-    ch = amiga_custom.serdatr & 0xff;
-    /* clear the interrupt, so that another character can be read */
-    amiga_custom.intreq = IF_RBF;
-    return ch;
+       int ch;
+
+       while (!(amiga_custom.intreqr & IF_RBF))
+               barrier();
+       ch = amiga_custom.serdatr & 0xff;
+       /* clear the interrupt, so that another character can be read */
+       amiga_custom.intreq = IF_RBF;
+       return ch;
 }
 
 void amiga_serial_gets(struct console *co, char *s, int len)
 {
-    int ch, cnt = 0;
-
-    while (1) {
-       ch = amiga_serial_console_wait_key(co);
-
-       /* Check for backspace. */
-       if (ch == 8 || ch == 127) {
-           if (cnt == 0) {
-               amiga_serial_putc('\007');
-               continue;
-           }
-           cnt--;
-           amiga_serial_puts("\010 \010");
-           continue;
-       }
+       int ch, cnt = 0;
+
+       while (1) {
+               ch = amiga_serial_console_wait_key(co);
+
+               /* Check for backspace. */
+               if (ch == 8 || ch == 127) {
+                       if (cnt == 0) {
+                               amiga_serial_putc('\007');
+                               continue;
+                       }
+                       cnt--;
+                       amiga_serial_puts("\010 \010");
+                       continue;
+               }
 
-       /* Check for enter. */
-       if (ch == 10 || ch == 13)
-           break;
+               /* Check for enter. */
+               if (ch == 10 || ch == 13)
+                       break;
 
-       /* See if line is too long. */
-       if (cnt >= len + 1) {
-           amiga_serial_putc(7);
-           cnt--;
-           continue;
-       }
+               /* See if line is too long. */
+               if (cnt >= len + 1) {
+                       amiga_serial_putc(7);
+                       cnt--;
+                       continue;
+               }
 
-       /* Store and echo character. */
-       s[cnt++] = ch;
-       amiga_serial_putc(ch);
-    }
-    /* Print enter. */
-    amiga_serial_puts("\r\n");
-    s[cnt] = 0;
+               /* Store and echo character. */
+               s[cnt++] = ch;
+               amiga_serial_putc(ch);
+       }
+       /* Print enter. */
+       amiga_serial_puts("\r\n");
+       s[cnt] = 0;
 }
 #endif
 
-static void __init amiga_debug_init(void)
+static int __init amiga_debug_setup(char *arg)
 {
-       if (!strcmp( m68k_debug_device, "ser" )) {
+       if (MACH_IS_AMIGA && !strcmp(arg, "ser")) {
                /* no initialization required (?) */
                amiga_console_driver.write = amiga_serial_console_write;
                register_console(&amiga_console_driver);
        }
+       return 0;
 }
 
+early_param("debug", amiga_debug_setup);
+
 #ifdef CONFIG_HEARTBEAT
 static void amiga_heartbeat(int on)
 {
-    if (on)
-       ciaa.pra &= ~2;
-    else
-       ciaa.pra |= 2;
+       if (on)
+               ciaa.pra &= ~2;
+       else
+               ciaa.pra |= 2;
 }
 #endif
 
@@ -901,81 +900,81 @@ static void amiga_heartbeat(int on)
 
 static void amiga_get_model(char *model)
 {
-    strcpy(model, amiga_model_name);
+       strcpy(model, amiga_model_name);
 }
 
 
 static int amiga_get_hardware_list(char *buffer)
 {
-    int len = 0;
-
-    if (AMIGAHW_PRESENT(CHIP_RAM))
-       len += sprintf(buffer+len, "Chip RAM:\t%ldK\n", amiga_chip_size>>10);
-    len += sprintf(buffer+len, "PS Freq:\t%dHz\nEClock Freq:\t%ldHz\n",
-                  amiga_psfreq, amiga_eclock);
-    if (AMIGAHW_PRESENT(AMI_VIDEO)) {
-       char *type;
-       switch(amiga_chipset) {
-           case CS_OCS:
-               type = "OCS";
-               break;
-           case CS_ECS:
-               type = "ECS";
-               break;
-           case CS_AGA:
-               type = "AGA";
-               break;
-           default:
-               type = "Old or Unknown";
-               break;
+       int len = 0;
+
+       if (AMIGAHW_PRESENT(CHIP_RAM))
+               len += sprintf(buffer+len, "Chip RAM:\t%ldK\n", amiga_chip_size>>10);
+       len += sprintf(buffer+len, "PS Freq:\t%dHz\nEClock Freq:\t%ldHz\n",
+                       amiga_psfreq, amiga_eclock);
+       if (AMIGAHW_PRESENT(AMI_VIDEO)) {
+               char *type;
+               switch (amiga_chipset) {
+               case CS_OCS:
+                       type = "OCS";
+                       break;
+               case CS_ECS:
+                       type = "ECS";
+                       break;
+               case CS_AGA:
+                       type = "AGA";
+                       break;
+               default:
+                       type = "Old or Unknown";
+                       break;
+               }
+               len += sprintf(buffer+len, "Graphics:\t%s\n", type);
        }
-       len += sprintf(buffer+len, "Graphics:\t%s\n", type);
-    }
 
 #define AMIGAHW_ANNOUNCE(name, str)                    \
-    if (AMIGAHW_PRESENT(name))                         \
-       len += sprintf (buffer+len, "\t%s\n", str)
-
-    len += sprintf (buffer + len, "Detected hardware:\n");
-
-    AMIGAHW_ANNOUNCE(AMI_VIDEO, "Amiga Video");
-    AMIGAHW_ANNOUNCE(AMI_BLITTER, "Blitter");
-    AMIGAHW_ANNOUNCE(AMBER_FF, "Amber Flicker Fixer");
-    AMIGAHW_ANNOUNCE(AMI_AUDIO, "Amiga Audio");
-    AMIGAHW_ANNOUNCE(AMI_FLOPPY, "Floppy Controller");
-    AMIGAHW_ANNOUNCE(A3000_SCSI, "SCSI Controller WD33C93 (A3000 style)");
-    AMIGAHW_ANNOUNCE(A4000_SCSI, "SCSI Controller NCR53C710 (A4000T style)");
-    AMIGAHW_ANNOUNCE(A1200_IDE, "IDE Interface (A1200 style)");
-    AMIGAHW_ANNOUNCE(A4000_IDE, "IDE Interface (A4000 style)");
-    AMIGAHW_ANNOUNCE(CD_ROM, "Internal CD ROM drive");
-    AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "Keyboard");
-    AMIGAHW_ANNOUNCE(AMI_MOUSE, "Mouse Port");
-    AMIGAHW_ANNOUNCE(AMI_SERIAL, "Serial Port");
-    AMIGAHW_ANNOUNCE(AMI_PARALLEL, "Parallel Port");
-    AMIGAHW_ANNOUNCE(A2000_CLK, "Hardware Clock (A2000 style)");
-    AMIGAHW_ANNOUNCE(A3000_CLK, "Hardware Clock (A3000 style)");
-    AMIGAHW_ANNOUNCE(CHIP_RAM, "Chip RAM");
-    AMIGAHW_ANNOUNCE(PAULA, "Paula 8364");
-    AMIGAHW_ANNOUNCE(DENISE, "Denise 8362");
-    AMIGAHW_ANNOUNCE(DENISE_HR, "Denise 8373");
-    AMIGAHW_ANNOUNCE(LISA, "Lisa 8375");
-    AMIGAHW_ANNOUNCE(AGNUS_PAL, "Normal/Fat PAL Agnus 8367/8371");
-    AMIGAHW_ANNOUNCE(AGNUS_NTSC, "Normal/Fat NTSC Agnus 8361/8370");
-    AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "Fat Hires PAL Agnus 8372");
-    AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "Fat Hires NTSC Agnus 8372");
-    AMIGAHW_ANNOUNCE(ALICE_PAL, "PAL Alice 8374");
-    AMIGAHW_ANNOUNCE(ALICE_NTSC, "NTSC Alice 8374");
-    AMIGAHW_ANNOUNCE(MAGIC_REKICK, "Magic Hard Rekick");
-    AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA Slot");
+       if (AMIGAHW_PRESENT(name))                      \
+               len += sprintf (buffer+len, "\t%s\n", str)
+
+       len += sprintf (buffer + len, "Detected hardware:\n");
+
+       AMIGAHW_ANNOUNCE(AMI_VIDEO, "Amiga Video");
+       AMIGAHW_ANNOUNCE(AMI_BLITTER, "Blitter");
+       AMIGAHW_ANNOUNCE(AMBER_FF, "Amber Flicker Fixer");
+       AMIGAHW_ANNOUNCE(AMI_AUDIO, "Amiga Audio");
+       AMIGAHW_ANNOUNCE(AMI_FLOPPY, "Floppy Controller");
+       AMIGAHW_ANNOUNCE(A3000_SCSI, "SCSI Controller WD33C93 (A3000 style)");
+       AMIGAHW_ANNOUNCE(A4000_SCSI, "SCSI Controller NCR53C710 (A4000T style)");
+       AMIGAHW_ANNOUNCE(A1200_IDE, "IDE Interface (A1200 style)");
+       AMIGAHW_ANNOUNCE(A4000_IDE, "IDE Interface (A4000 style)");
+       AMIGAHW_ANNOUNCE(CD_ROM, "Internal CD ROM drive");
+       AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "Keyboard");
+       AMIGAHW_ANNOUNCE(AMI_MOUSE, "Mouse Port");
+       AMIGAHW_ANNOUNCE(AMI_SERIAL, "Serial Port");
+       AMIGAHW_ANNOUNCE(AMI_PARALLEL, "Parallel Port");
+       AMIGAHW_ANNOUNCE(A2000_CLK, "Hardware Clock (A2000 style)");
+       AMIGAHW_ANNOUNCE(A3000_CLK, "Hardware Clock (A3000 style)");
+       AMIGAHW_ANNOUNCE(CHIP_RAM, "Chip RAM");
+       AMIGAHW_ANNOUNCE(PAULA, "Paula 8364");
+       AMIGAHW_ANNOUNCE(DENISE, "Denise 8362");
+       AMIGAHW_ANNOUNCE(DENISE_HR, "Denise 8373");
+       AMIGAHW_ANNOUNCE(LISA, "Lisa 8375");
+       AMIGAHW_ANNOUNCE(AGNUS_PAL, "Normal/Fat PAL Agnus 8367/8371");
+       AMIGAHW_ANNOUNCE(AGNUS_NTSC, "Normal/Fat NTSC Agnus 8361/8370");
+       AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "Fat Hires PAL Agnus 8372");
+       AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "Fat Hires NTSC Agnus 8372");
+       AMIGAHW_ANNOUNCE(ALICE_PAL, "PAL Alice 8374");
+       AMIGAHW_ANNOUNCE(ALICE_NTSC, "NTSC Alice 8374");
+       AMIGAHW_ANNOUNCE(MAGIC_REKICK, "Magic Hard Rekick");
+       AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA Slot");
 #ifdef CONFIG_ZORRO
-    if (AMIGAHW_PRESENT(ZORRO))
-       len += sprintf(buffer+len, "\tZorro II%s AutoConfig: %d Expansion "
-                                  "Device%s\n",
-                      AMIGAHW_PRESENT(ZORRO3) ? "I" : "",
-                      zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s");
+       if (AMIGAHW_PRESENT(ZORRO))
+               len += sprintf(buffer+len, "\tZorro II%s AutoConfig: %d Expansion "
+                               "Device%s\n",
+                               AMIGAHW_PRESENT(ZORRO3) ? "I" : "",
+                               zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s");
 #endif /* CONFIG_ZORRO */
 
 #undef AMIGAHW_ANNOUNCE
 
-    return(len);
+       return len;
 }
index 8cb6236..2cb8619 100644 (file)
@@ -8,3 +8,4 @@ obj-y           := config.o time.o debug.o ataints.o stdma.o \
 ifeq ($(CONFIG_PCI),y)
 obj-$(CONFIG_HADES)    += hades-pci.o
 endif
+obj-$(CONFIG_ATARI_KBD_CORE)   += atakeyb.o
diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c
new file mode 100644 (file)
index 0000000..1c29603
--- /dev/null
@@ -0,0 +1,730 @@
+/*
+ * linux/atari/atakeyb.c
+ *
+ * Atari Keyboard driver for 680x0 Linux
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+/*
+ * Atari support by Robert de Vries
+ * enhanced by Bjoern Brauel and Roman Hodek
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/keyboard.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/kd.h>
+#include <linux/random.h>
+#include <linux/init.h>
+#include <linux/kbd_kern.h>
+
+#include <asm/atariints.h>
+#include <asm/atarihw.h>
+#include <asm/atarikb.h>
+#include <asm/atari_joystick.h>
+#include <asm/irq.h>
+
+static void atakeyb_rep(unsigned long ignore);
+extern unsigned int keymap_count;
+
+/* Hook for MIDI serial driver */
+void (*atari_MIDI_interrupt_hook) (void);
+/* Hook for mouse driver */
+void (*atari_mouse_interrupt_hook) (char *);
+/* Hook for keyboard inputdev  driver */
+void (*atari_input_keyboard_interrupt_hook) (unsigned char, char);
+/* Hook for mouse inputdev  driver */
+void (*atari_input_mouse_interrupt_hook) (char *);
+
+/* variables for IKBD self test: */
+
+/* state: 0: off; >0: in progress; >1: 0xf1 received */
+static volatile int ikbd_self_test;
+/* timestamp when last received a char */
+static volatile unsigned long self_test_last_rcv;
+/* bitmap of keys reported as broken */
+static unsigned long broken_keys[128/(sizeof(unsigned long)*8)] = { 0, };
+
+#define BREAK_MASK     (0x80)
+
+/*
+ * ++roman: The following changes were applied manually:
+ *
+ *  - The Alt (= Meta) key works in combination with Shift and
+ *    Control, e.g. Alt+Shift+a sends Meta-A (0xc1), Alt+Control+A sends
+ *    Meta-Ctrl-A (0x81) ...
+ *
+ *  - The parentheses on the keypad send '(' and ')' with all
+ *    modifiers (as would do e.g. keypad '+'), but they cannot be used as
+ *    application keys (i.e. sending Esc O c).
+ *
+ *  - HELP and UNDO are mapped to be F21 and F24, resp, that send the
+ *    codes "\E[M" and "\E[P". (This is better than the old mapping to
+ *    F11 and F12, because these codes are on Shift+F1/2 anyway.) This
+ *    way, applications that allow their own keyboard mappings
+ *    (e.g. tcsh, X Windows) can be configured to use them in the way
+ *    the label suggests (providing help or undoing).
+ *
+ *  - Console switching is done with Alt+Fx (consoles 1..10) and
+ *    Shift+Alt+Fx (consoles 11..20).
+ *
+ *  - The misc. special function implemented in the kernel are mapped
+ *    to the following key combinations:
+ *
+ *      ClrHome          -> Home/Find
+ *      Shift + ClrHome  -> End/Select
+ *      Shift + Up       -> Page Up
+ *      Shift + Down     -> Page Down
+ *      Alt + Help       -> show system status
+ *      Shift + Help     -> show memory info
+ *      Ctrl + Help      -> show registers
+ *      Ctrl + Alt + Del -> Reboot
+ *      Alt + Undo       -> switch to last console
+ *      Shift + Undo     -> send interrupt
+ *      Alt + Insert     -> stop/start output (same as ^S/^Q)
+ *      Alt + Up         -> Scroll back console (if implemented)
+ *      Alt + Down       -> Scroll forward console (if implemented)
+ *      Alt + CapsLock   -> NumLock
+ *
+ * ++Andreas:
+ *
+ *  - Help mapped to K_HELP
+ *  - Undo mapped to K_UNDO (= K_F246)
+ *  - Keypad Left/Right Parenthesis mapped to new K_PPAREN[LR]
+ */
+
+static u_short ataplain_map[NR_KEYS] __initdata = {
+       0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036,
+       0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf008, 0xf009,
+       0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
+       0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73,
+       0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
+       0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76,
+       0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf200,
+       0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
+       0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114,
+       0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
+       0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200,
+       0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+       0xf200, 0xf1ff, 0xf11b, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307,
+       0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303,
+       0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+       0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
+};
+
+typedef enum kb_state_t {
+       KEYBOARD, AMOUSE, RMOUSE, JOYSTICK, CLOCK, RESYNC
+} KB_STATE_T;
+
+#define        IS_SYNC_CODE(sc)        ((sc) >= 0x04 && (sc) <= 0xfb)
+
+typedef struct keyboard_state {
+       unsigned char buf[6];
+       int len;
+       KB_STATE_T state;
+} KEYBOARD_STATE;
+
+KEYBOARD_STATE kb_state;
+
+#define        DEFAULT_KEYB_REP_DELAY  (HZ/4)
+#define        DEFAULT_KEYB_REP_RATE   (HZ/25)
+
+/* These could be settable by some ioctl() in future... */
+static unsigned int key_repeat_delay = DEFAULT_KEYB_REP_DELAY;
+static unsigned int key_repeat_rate = DEFAULT_KEYB_REP_RATE;
+
+static unsigned char rep_scancode;
+static struct timer_list atakeyb_rep_timer = {
+       .function = atakeyb_rep,
+};
+
+static void atakeyb_rep(unsigned long ignore)
+{
+       /* Disable keyboard for the time we call handle_scancode(), else a race
+        * in the keyboard tty queue may happen */
+       atari_disable_irq(IRQ_MFP_ACIA);
+       del_timer(&atakeyb_rep_timer);
+
+       /* A keyboard int may have come in before we disabled the irq, so
+        * double-check whether rep_scancode is still != 0 */
+       if (rep_scancode) {
+               init_timer(&atakeyb_rep_timer);
+               atakeyb_rep_timer.expires = jiffies + key_repeat_rate;
+               add_timer(&atakeyb_rep_timer);
+
+               //handle_scancode(rep_scancode, 1);
+               if (atari_input_keyboard_interrupt_hook)
+                       atari_input_keyboard_interrupt_hook(rep_scancode, 1);
+       }
+
+       atari_enable_irq(IRQ_MFP_ACIA);
+}
+
+
+/* ++roman: If a keyboard overrun happened, we can't tell in general how much
+ * bytes have been lost and in which state of the packet structure we are now.
+ * This usually causes keyboards bytes to be interpreted as mouse movements
+ * and vice versa, which is very annoying. It seems better to throw away some
+ * bytes (that are usually mouse bytes) than to misinterpret them. Therefor I
+ * introduced the RESYNC state for IKBD data. In this state, the bytes up to
+ * one that really looks like a key event (0x04..0xf2) or the start of a mouse
+ * packet (0xf8..0xfb) are thrown away, but at most 2 bytes. This at least
+ * speeds up the resynchronization of the event structure, even if maybe a
+ * mouse movement is lost. However, nothing is perfect. For bytes 0x01..0x03,
+ * it's really hard to decide whether they're mouse or keyboard bytes. Since
+ * overruns usually occur when moving the Atari mouse rapidly, they're seen as
+ * mouse bytes here. If this is wrong, only a make code of the keyboard gets
+ * lost, which isn't too bad. Loosing a break code would be disastrous,
+ * because then the keyboard repeat strikes...
+ */
+
+static irqreturn_t atari_keyboard_interrupt(int irq, void *dummy)
+{
+       u_char acia_stat;
+       int scancode;
+       int break_flag;
+
+repeat:
+       if (acia.mid_ctrl & ACIA_IRQ)
+               if (atari_MIDI_interrupt_hook)
+                       atari_MIDI_interrupt_hook();
+       acia_stat = acia.key_ctrl;
+       /* check out if the interrupt came from this ACIA */
+       if (!((acia_stat | acia.mid_ctrl) & ACIA_IRQ))
+               return IRQ_HANDLED;
+
+       if (acia_stat & ACIA_OVRN) {
+               /* a very fast typist or a slow system, give a warning */
+               /* ...happens often if interrupts were disabled for too long */
+               printk(KERN_DEBUG "Keyboard overrun\n");
+               scancode = acia.key_data;
+               /* Turn off autorepeating in case a break code has been lost */
+               del_timer(&atakeyb_rep_timer);
+               rep_scancode = 0;
+               if (ikbd_self_test)
+                       /* During self test, don't do resyncing, just process the code */
+                       goto interpret_scancode;
+               else if (IS_SYNC_CODE(scancode)) {
+                       /* This code seem already to be the start of a new packet or a
+                        * single scancode */
+                       kb_state.state = KEYBOARD;
+                       goto interpret_scancode;
+               } else {
+                       /* Go to RESYNC state and skip this byte */
+                       kb_state.state = RESYNC;
+                       kb_state.len = 1;       /* skip max. 1 another byte */
+                       goto repeat;
+               }
+       }
+
+       if (acia_stat & ACIA_RDRF) {
+               /* received a character */
+               scancode = acia.key_data;       /* get it or reset the ACIA, I'll get it! */
+               tasklet_schedule(&keyboard_tasklet);
+       interpret_scancode:
+               switch (kb_state.state) {
+               case KEYBOARD:
+                       switch (scancode) {
+                       case 0xF7:
+                               kb_state.state = AMOUSE;
+                               kb_state.len = 0;
+                               break;
+
+                       case 0xF8:
+                       case 0xF9:
+                       case 0xFA:
+                       case 0xFB:
+                               kb_state.state = RMOUSE;
+                               kb_state.len = 1;
+                               kb_state.buf[0] = scancode;
+                               break;
+
+                       case 0xFC:
+                               kb_state.state = CLOCK;
+                               kb_state.len = 0;
+                               break;
+
+                       case 0xFE:
+                       case 0xFF:
+                               kb_state.state = JOYSTICK;
+                               kb_state.len = 1;
+                               kb_state.buf[0] = scancode;
+                               break;
+
+                       case 0xF1:
+                               /* during self-test, note that 0xf1 received */
+                               if (ikbd_self_test) {
+                                       ++ikbd_self_test;
+                                       self_test_last_rcv = jiffies;
+                                       break;
+                               }
+                               /* FALL THROUGH */
+
+                       default:
+                               break_flag = scancode & BREAK_MASK;
+                               scancode &= ~BREAK_MASK;
+                               if (ikbd_self_test) {
+                                       /* Scancodes sent during the self-test stand for broken
+                                        * keys (keys being down). The code *should* be a break
+                                        * code, but nevertheless some AT keyboard interfaces send
+                                        * make codes instead. Therefore, simply ignore
+                                        * break_flag...
+                                        */
+                                       int keyval = plain_map[scancode], keytyp;
+
+                                       set_bit(scancode, broken_keys);
+                                       self_test_last_rcv = jiffies;
+                                       keyval = plain_map[scancode];
+                                       keytyp = KTYP(keyval) - 0xf0;
+                                       keyval = KVAL(keyval);
+
+                                       printk(KERN_WARNING "Key with scancode %d ", scancode);
+                                       if (keytyp == KT_LATIN || keytyp == KT_LETTER) {
+                                               if (keyval < ' ')
+                                                       printk("('^%c') ", keyval + '@');
+                                               else
+                                                       printk("('%c') ", keyval);
+                                       }
+                                       printk("is broken -- will be ignored.\n");
+                                       break;
+                               } else if (test_bit(scancode, broken_keys))
+                                       break;
+
+#if 0  // FIXME; hangs at boot
+                               if (break_flag) {
+                                       del_timer(&atakeyb_rep_timer);
+                                       rep_scancode = 0;
+                               } else {
+                                       del_timer(&atakeyb_rep_timer);
+                                       rep_scancode = scancode;
+                                       atakeyb_rep_timer.expires = jiffies + key_repeat_delay;
+                                       add_timer(&atakeyb_rep_timer);
+                               }
+#endif
+
+                               // handle_scancode(scancode, !break_flag);
+                               if (atari_input_keyboard_interrupt_hook)
+                                       atari_input_keyboard_interrupt_hook((unsigned char)scancode, !break_flag);
+                               break;
+                       }
+                       break;
+
+               case AMOUSE:
+                       kb_state.buf[kb_state.len++] = scancode;
+                       if (kb_state.len == 5) {
+                               kb_state.state = KEYBOARD;
+                               /* not yet used */
+                               /* wake up someone waiting for this */
+                       }
+                       break;
+
+               case RMOUSE:
+                       kb_state.buf[kb_state.len++] = scancode;
+                       if (kb_state.len == 3) {
+                               kb_state.state = KEYBOARD;
+                               if (atari_mouse_interrupt_hook)
+                                       atari_mouse_interrupt_hook(kb_state.buf);
+                       }
+                       break;
+
+               case JOYSTICK:
+                       kb_state.buf[1] = scancode;
+                       kb_state.state = KEYBOARD;
+#ifdef FIXED_ATARI_JOYSTICK
+                       atari_joystick_interrupt(kb_state.buf);
+#endif
+                       break;
+
+               case CLOCK:
+                       kb_state.buf[kb_state.len++] = scancode;
+                       if (kb_state.len == 6) {
+                               kb_state.state = KEYBOARD;
+                               /* wake up someone waiting for this.
+                                  But will this ever be used, as Linux keeps its own time.
+                                  Perhaps for synchronization purposes? */
+                               /* wake_up_interruptible(&clock_wait); */
+                       }
+                       break;
+
+               case RESYNC:
+                       if (kb_state.len <= 0 || IS_SYNC_CODE(scancode)) {
+                               kb_state.state = KEYBOARD;
+                               goto interpret_scancode;
+                       }
+                       kb_state.len--;
+                       break;
+               }
+       }
+
+#if 0
+       if (acia_stat & ACIA_CTS)
+               /* cannot happen */;
+#endif
+
+       if (acia_stat & (ACIA_FE | ACIA_PE)) {
+               printk("Error in keyboard communication\n");
+       }
+
+       /* handle_scancode() can take a lot of time, so check again if
+        * some character arrived
+        */
+       goto repeat;
+}
+
+/*
+ * I write to the keyboard without using interrupts, I poll instead.
+ * This takes for the maximum length string allowed (7) at 7812.5 baud
+ * 8 data 1 start 1 stop bit: 9.0 ms
+ * If this takes too long for normal operation, interrupt driven writing
+ * is the solution. (I made a feeble attempt in that direction but I
+ * kept it simple for now.)
+ */
+void ikbd_write(const char *str, int len)
+{
+       u_char acia_stat;
+
+       if ((len < 1) || (len > 7))
+               panic("ikbd: maximum string length exceeded");
+       while (len) {
+               acia_stat = acia.key_ctrl;
+               if (acia_stat & ACIA_TDRE) {
+                       acia.key_data = *str++;
+                       len--;
+               }
+       }
+}
+
+/* Reset (without touching the clock) */
+void ikbd_reset(void)
+{
+       static const char cmd[2] = { 0x80, 0x01 };
+
+       ikbd_write(cmd, 2);
+
+       /*
+        * if all's well code 0xF1 is returned, else the break codes of
+        * all keys making contact
+        */
+}
+
+/* Set mouse button action */
+void ikbd_mouse_button_action(int mode)
+{
+       char cmd[2] = { 0x07, mode };
+
+       ikbd_write(cmd, 2);
+}
+
+/* Set relative mouse position reporting */
+void ikbd_mouse_rel_pos(void)
+{
+       static const char cmd[1] = { 0x08 };
+
+       ikbd_write(cmd, 1);
+}
+
+/* Set absolute mouse position reporting */
+void ikbd_mouse_abs_pos(int xmax, int ymax)
+{
+       char cmd[5] = { 0x09, xmax>>8, xmax&0xFF, ymax>>8, ymax&0xFF };
+
+       ikbd_write(cmd, 5);
+}
+
+/* Set mouse keycode mode */
+void ikbd_mouse_kbd_mode(int dx, int dy)
+{
+       char cmd[3] = { 0x0A, dx, dy };
+
+       ikbd_write(cmd, 3);
+}
+
+/* Set mouse threshold */
+void ikbd_mouse_thresh(int x, int y)
+{
+       char cmd[3] = { 0x0B, x, y };
+
+       ikbd_write(cmd, 3);
+}
+
+/* Set mouse scale */
+void ikbd_mouse_scale(int x, int y)
+{
+       char cmd[3] = { 0x0C, x, y };
+
+       ikbd_write(cmd, 3);
+}
+
+/* Interrogate mouse position */
+void ikbd_mouse_pos_get(int *x, int *y)
+{
+       static const char cmd[1] = { 0x0D };
+
+       ikbd_write(cmd, 1);
+
+       /* wait for returning bytes */
+}
+
+/* Load mouse position */
+void ikbd_mouse_pos_set(int x, int y)
+{
+       char cmd[6] = { 0x0E, 0x00, x>>8, x&0xFF, y>>8, y&0xFF };
+
+       ikbd_write(cmd, 6);
+}
+
+/* Set Y=0 at bottom */
+void ikbd_mouse_y0_bot(void)
+{
+       static const char cmd[1] = { 0x0F };
+
+       ikbd_write(cmd, 1);
+}
+
+/* Set Y=0 at top */
+void ikbd_mouse_y0_top(void)
+{
+       static const char cmd[1] = { 0x10 };
+
+       ikbd_write(cmd, 1);
+}
+
+/* Resume */
+void ikbd_resume(void)
+{
+       static const char cmd[1] = { 0x11 };
+
+       ikbd_write(cmd, 1);
+}
+
+/* Disable mouse */
+void ikbd_mouse_disable(void)
+{
+       static const char cmd[1] = { 0x12 };
+
+       ikbd_write(cmd, 1);
+}
+
+/* Pause output */
+void ikbd_pause(void)
+{
+       static const char cmd[1] = { 0x13 };
+
+       ikbd_write(cmd, 1);
+}
+
+/* Set joystick event reporting */
+void ikbd_joystick_event_on(void)
+{
+       static const char cmd[1] = { 0x14 };
+
+       ikbd_write(cmd, 1);
+}
+
+/* Set joystick interrogation mode */
+void ikbd_joystick_event_off(void)
+{
+       static const char cmd[1] = { 0x15 };
+
+       ikbd_write(cmd, 1);
+}
+
+/* Joystick interrogation */
+void ikbd_joystick_get_state(void)
+{
+       static const char cmd[1] = { 0x16 };
+
+       ikbd_write(cmd, 1);
+}
+
+#if 0
+/* This disables all other ikbd activities !!!! */
+/* Set joystick monitoring */
+void ikbd_joystick_monitor(int rate)
+{
+       static const char cmd[2] = { 0x17, rate };
+
+       ikbd_write(cmd, 2);
+
+       kb_state.state = JOYSTICK_MONITOR;
+}
+#endif
+
+/* some joystick routines not in yet (0x18-0x19) */
+
+/* Disable joysticks */
+void ikbd_joystick_disable(void)
+{
+       static const char cmd[1] = { 0x1A };
+
+       ikbd_write(cmd, 1);
+}
+
+/* Time-of-day clock set */
+void ikbd_clock_set(int year, int month, int day, int hour, int minute, int second)
+{
+       char cmd[7] = { 0x1B, year, month, day, hour, minute, second };
+
+       ikbd_write(cmd, 7);
+}
+
+/* Interrogate time-of-day clock */
+void ikbd_clock_get(int *year, int *month, int *day, int *hour, int *minute, int second)
+{
+       static const char cmd[1] = { 0x1C };
+
+       ikbd_write(cmd, 1);
+}
+
+/* Memory load */
+void ikbd_mem_write(int address, int size, char *data)
+{
+       panic("Attempt to write data into keyboard memory");
+}
+
+/* Memory read */
+void ikbd_mem_read(int address, char data[6])
+{
+       char cmd[3] = { 0x21, address>>8, address&0xFF };
+
+       ikbd_write(cmd, 3);
+
+       /* receive data and put it in data */
+}
+
+/* Controller execute */
+void ikbd_exec(int address)
+{
+       char cmd[3] = { 0x22, address>>8, address&0xFF };
+
+       ikbd_write(cmd, 3);
+}
+
+/* Status inquiries (0x87-0x9A) not yet implemented */
+
+/* Set the state of the caps lock led. */
+void atari_kbd_leds(unsigned int leds)
+{
+       char cmd[6] = {32, 0, 4, 1, 254 + ((leds & 4) != 0), 0};
+
+       ikbd_write(cmd, 6);
+}
+
+/*
+ * The original code sometimes left the interrupt line of
+ * the ACIAs low forever. I hope, it is fixed now.
+ *
+ * Martin Rogge, 20 Aug 1995
+ */
+
+static int atari_keyb_done = 0;
+
+int __init atari_keyb_init(void)
+{
+       if (atari_keyb_done)
+               return 0;
+
+       /* setup key map */
+       memcpy(key_maps[0], ataplain_map, sizeof(plain_map));
+
+       kb_state.state = KEYBOARD;
+       kb_state.len = 0;
+
+       request_irq(IRQ_MFP_ACIA, atari_keyboard_interrupt, IRQ_TYPE_SLOW,
+                   "keyboard/mouse/MIDI", atari_keyboard_interrupt);
+
+       atari_turnoff_irq(IRQ_MFP_ACIA);
+       do {
+               /* reset IKBD ACIA */
+               acia.key_ctrl = ACIA_RESET |
+                               (atari_switches & ATARI_SWITCH_IKBD) ? ACIA_RHTID : 0;
+               (void)acia.key_ctrl;
+               (void)acia.key_data;
+
+               /* reset MIDI ACIA */
+               acia.mid_ctrl = ACIA_RESET |
+                               (atari_switches & ATARI_SWITCH_MIDI) ? ACIA_RHTID : 0;
+               (void)acia.mid_ctrl;
+               (void)acia.mid_data;
+
+               /* divide 500kHz by 64 gives 7812.5 baud */
+               /* 8 data no parity 1 start 1 stop bit */
+               /* receive interrupt enabled */
+               /* RTS low (except if switch selected), transmit interrupt disabled */
+               acia.key_ctrl = (ACIA_DIV64|ACIA_D8N1S|ACIA_RIE) |
+                               ((atari_switches & ATARI_SWITCH_IKBD) ?
+                                ACIA_RHTID : ACIA_RLTID);
+
+               acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S |
+                               (atari_switches & ATARI_SWITCH_MIDI) ? ACIA_RHTID : 0;
+
+       /* make sure the interrupt line is up */
+       } while ((mfp.par_dt_reg & 0x10) == 0);
+
+       /* enable ACIA Interrupts */
+       mfp.active_edge &= ~0x10;
+       atari_turnon_irq(IRQ_MFP_ACIA);
+
+       ikbd_self_test = 1;
+       ikbd_reset();
+       /* wait for a period of inactivity (here: 0.25s), then assume the IKBD's
+        * self-test is finished */
+       self_test_last_rcv = jiffies;
+       while (time_before(jiffies, self_test_last_rcv + HZ/4))
+               barrier();
+       /* if not incremented: no 0xf1 received */
+       if (ikbd_self_test == 1)
+               printk(KERN_ERR "WARNING: keyboard self test failed!\n");
+       ikbd_self_test = 0;
+
+       ikbd_mouse_disable();
+       ikbd_joystick_disable();
+
+#ifdef FIXED_ATARI_JOYSTICK
+       atari_joystick_init();
+#endif
+
+       // flag init done
+       atari_keyb_done = 1;
+       return 0;
+}
+
+
+int atari_kbdrate(struct kbd_repeat *k)
+{
+       if (k->delay > 0) {
+               /* convert from msec to jiffies */
+               key_repeat_delay = (k->delay * HZ + 500) / 1000;
+               if (key_repeat_delay < 1)
+                       key_repeat_delay = 1;
+       }
+       if (k->period > 0) {
+               key_repeat_rate = (k->period * HZ + 500) / 1000;
+               if (key_repeat_rate < 1)
+                       key_repeat_rate = 1;
+       }
+
+       k->delay  = key_repeat_delay * 1000 / HZ;
+       k->period = key_repeat_rate  * 1000 / HZ;
+
+       return 0;
+}
+
+int atari_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode)
+{
+#ifdef CONFIG_MAGIC_SYSRQ
+       /* ALT+HELP pressed? */
+       if ((keycode == 98) && ((shift_state & 0xff) == 8))
+               *keycodep = 0xff;
+       else
+#endif
+               *keycodep = keycode;
+       return 1;
+}
index ca5cd43..e40e5dc 100644 (file)
@@ -50,70 +50,25 @@ int atari_dont_touch_floppy_select;
 int atari_rtc_year_offset;
 
 /* local function prototypes */
-static void atari_reset( void );
+static void atari_reset(void);
 static void atari_get_model(char *model);
 static int atari_get_hardware_list(char *buffer);
 
 /* atari specific irq functions */
 extern void atari_init_IRQ (void);
-extern void atari_mksound( unsigned int count, unsigned int ticks );
+extern void atari_mksound(unsigned int count, unsigned int ticks);
 #ifdef CONFIG_HEARTBEAT
-static void atari_heartbeat( int on );
+static void atari_heartbeat(int on);
 #endif
 
 /* atari specific timer functions (in time.c) */
-extern void atari_sched_init(irq_handler_t );
+extern void atari_sched_init(irq_handler_t);
 extern unsigned long atari_gettimeoffset (void);
 extern int atari_mste_hwclk (int, struct rtc_time *);
 extern int atari_tt_hwclk (int, struct rtc_time *);
 extern int atari_mste_set_clock_mmss (unsigned long);
 extern int atari_tt_set_clock_mmss (unsigned long);
 
-/* atari specific debug functions (in debug.c) */
-extern void atari_debug_init(void);
-
-
-/* I've moved hwreg_present() and hwreg_present_bywrite() out into
- * mm/hwtest.c, to avoid having multiple copies of the same routine
- * in the kernel [I wanted them in hp300 and they were already used
- * in the nubus code. NB: I don't have an Atari so this might (just
- * conceivably) break something.
- * I've preserved the #if 0 version of hwreg_present_bywrite() here
- * for posterity.
- *   -- Peter Maydell <pmaydell@chiark.greenend.org.uk>, 05/1998
- */
-
-#if 0
-static int __init
-hwreg_present_bywrite(volatile void *regp, unsigned char val)
-{
-    int                ret;
-    long       save_sp, save_vbr;
-    static long tmp_vectors[3] = { [2] = (long)&&after_test };
-
-    __asm__ __volatile__
-       (       "movec  %/vbr,%2\n\t"   /* save vbr value            */
-                "movec %4,%/vbr\n\t"   /* set up temporary vectors  */
-               "movel  %/sp,%1\n\t"    /* save sp                   */
-               "moveq  #0,%0\n\t"      /* assume not present        */
-               "moveb  %5,%3@\n\t"     /* write the hardware reg    */
-               "cmpb   %3@,%5\n\t"     /* compare it                */
-               "seq    %0"             /* comes here only if reg    */
-                                        /* is present                */
-               : "=d&" (ret), "=r&" (save_sp), "=r&" (save_vbr)
-               : "a" (regp), "r" (tmp_vectors), "d" (val)
-                );
-  after_test:
-    __asm__ __volatile__
-      (        "movel  %0,%/sp\n\t"            /* restore sp                */
-        "movec %1,%/vbr"                       /* restore vbr               */
-        : : "r" (save_sp), "r" (save_vbr) : "sp"
-       );
-
-    return( ret );
-}
-#endif
-
 
 /* ++roman: This is a more elaborate test for an SCC chip, since the plain
  * Medusa board generates DTACK at the SCC's standard addresses, but a SCC
@@ -123,26 +78,34 @@ hwreg_present_bywrite(volatile void *regp, unsigned char val)
  * should be readable without trouble (from channel A!).
  */
 
-static int __init scc_test( volatile char *ctla )
+static int __init scc_test(volatile char *ctla)
 {
-       if (!hwreg_present( ctla ))
-               return( 0 );
+       if (!hwreg_present(ctla))
+               return 0;
        MFPDELAY();
 
-       *ctla = 2; MFPDELAY();
-       *ctla = 0x40; MFPDELAY();
+       *ctla = 2;
+       MFPDELAY();
+       *ctla = 0x40;
+       MFPDELAY();
 
-       *ctla = 2; MFPDELAY();
-       if (*ctla != 0x40) return( 0 );
+       *ctla = 2;
+       MFPDELAY();
+       if (*ctla != 0x40)
+               return 0;
        MFPDELAY();
 
-       *ctla = 2; MFPDELAY();
-       *ctla = 0x60; MFPDELAY();
+       *ctla = 2;
+       MFPDELAY();
+       *ctla = 0x60;
+       MFPDELAY();
 
-       *ctla = 2; MFPDELAY();
-       if (*ctla != 0x60) return( 0 );
+       *ctla = 2;
+       MFPDELAY();
+       if (*ctla != 0x60)
+               return 0;
 
-       return( 1 );
+       return 1;
 }
 
 
@@ -152,61 +115,66 @@ static int __init scc_test( volatile char *ctla )
 
 int __init atari_parse_bootinfo(const struct bi_record *record)
 {
-    int unknown = 0;
-    const u_long *data = record->data;
+       int unknown = 0;
+       const u_long *data = record->data;
 
-    switch (record->tag) {
+       switch (record->tag) {
        case BI_ATARI_MCH_COOKIE:
-           atari_mch_cookie = *data;
-           break;
+               atari_mch_cookie = *data;
+               break;
        case BI_ATARI_MCH_TYPE:
-           atari_mch_type = *data;
-           break;
+               atari_mch_type = *data;
+               break;
        default:
-           unknown = 1;
-    }
-    return(unknown);
+               unknown = 1;
+               break;
+       }
+       return unknown;
 }
 
 
 /* Parse the Atari-specific switches= option. */
-void __init atari_switches_setup( const char *str, unsigned len )
+static int __init atari_switches_setup(char *str)
 {
-    char switches[len+1];
-    char *p;
-    int ovsc_shift;
-    char *args = switches;
-
-    /* copy string to local array, strsep works destructively... */
-    strlcpy( switches, str, sizeof(switches) );
-    atari_switches = 0;
-
-    /* parse the options */
-    while ((p = strsep(&args, ",")) != NULL) {
-       if (!*p) continue;
-       ovsc_shift = 0;
-       if (strncmp( p, "ov_", 3 ) == 0) {
-           p += 3;
-           ovsc_shift = ATARI_SWITCH_OVSC_SHIFT;
-       }
-
-       if (strcmp( p, "ikbd" ) == 0) {
-           /* RTS line of IKBD ACIA */
-           atari_switches |= ATARI_SWITCH_IKBD << ovsc_shift;
-       }
-       else if (strcmp( p, "midi" ) == 0) {
-           /* RTS line of MIDI ACIA */
-           atari_switches |= ATARI_SWITCH_MIDI << ovsc_shift;
+       char switches[strlen(str) + 1];
+       char *p;
+       int ovsc_shift;
+       char *args = switches;
+
+       if (!MACH_IS_ATARI)
+               return 0;
+
+       /* copy string to local array, strsep works destructively... */
+       strcpy(switches, str);
+       atari_switches = 0;
+
+       /* parse the options */
+       while ((p = strsep(&args, ",")) != NULL) {
+               if (!*p)
+                       continue;
+               ovsc_shift = 0;
+               if (strncmp(p, "ov_", 3) == 0) {
+                       p += 3;
+                       ovsc_shift = ATARI_SWITCH_OVSC_SHIFT;
+               }
+
+               if (strcmp(p, "ikbd") == 0) {
+                       /* RTS line of IKBD ACIA */
+                       atari_switches |= ATARI_SWITCH_IKBD << ovsc_shift;
+               } else if (strcmp(p, "midi") == 0) {
+                       /* RTS line of MIDI ACIA */
+                       atari_switches |= ATARI_SWITCH_MIDI << ovsc_shift;
+               } else if (strcmp(p, "snd6") == 0) {
+                       atari_switches |= ATARI_SWITCH_SND6 << ovsc_shift;
+               } else if (strcmp(p, "snd7") == 0) {
+                       atari_switches |= ATARI_SWITCH_SND7 << ovsc_shift;
+               }
        }
-       else if (strcmp( p, "snd6" ) == 0) {
-           atari_switches |= ATARI_SWITCH_SND6 << ovsc_shift;
-       }
-       else if (strcmp( p, "snd7" ) == 0) {
-           atari_switches |= ATARI_SWITCH_SND7 << ovsc_shift;
-       }
-    }
+       return 0;
 }
 
+early_param("switches", atari_switches_setup);
+
 
     /*
      *  Setup the Atari configuration info
@@ -214,284 +182,281 @@ void __init atari_switches_setup( const char *str, unsigned len )
 
 void __init config_atari(void)
 {
-    unsigned short tos_version;
+       unsigned short tos_version;
 
-    memset(&atari_hw_present, 0, sizeof(atari_hw_present));
+       memset(&atari_hw_present, 0, sizeof(atari_hw_present));
 
-    atari_debug_init();
+       /* Change size of I/O space from 64KB to 4GB. */
+       ioport_resource.end  = 0xFFFFFFFF;
 
-    ioport_resource.end  = 0xFFFFFFFF;  /* Change size of I/O space from 64KB
-                                           to 4GB. */
-
-    mach_sched_init      = atari_sched_init;
-    mach_init_IRQ        = atari_init_IRQ;
-    mach_get_model      = atari_get_model;
-    mach_get_hardware_list = atari_get_hardware_list;
-    mach_gettimeoffset   = atari_gettimeoffset;
-    mach_reset           = atari_reset;
-    mach_max_dma_address = 0xffffff;
+       mach_sched_init      = atari_sched_init;
+       mach_init_IRQ        = atari_init_IRQ;
+       mach_get_model   = atari_get_model;
+       mach_get_hardware_list = atari_get_hardware_list;
+       mach_gettimeoffset   = atari_gettimeoffset;
+       mach_reset           = atari_reset;
+       mach_max_dma_address = 0xffffff;
 #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
-    mach_beep          = atari_mksound;
+       mach_beep          = atari_mksound;
 #endif
 #ifdef CONFIG_HEARTBEAT
-    mach_heartbeat = atari_heartbeat;
+       mach_heartbeat = atari_heartbeat;
 #endif
 
-    /* Set switches as requested by the user */
-    if (atari_switches & ATARI_SWITCH_IKBD)
-       acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID;
-    if (atari_switches & ATARI_SWITCH_MIDI)
-       acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
-    if (atari_switches & (ATARI_SWITCH_SND6|ATARI_SWITCH_SND7)) {
-       sound_ym.rd_data_reg_sel = 14;
-       sound_ym.wd_data = sound_ym.rd_data_reg_sel |
-                          ((atari_switches&ATARI_SWITCH_SND6) ? 0x40 : 0) |
-                          ((atari_switches&ATARI_SWITCH_SND7) ? 0x80 : 0);
-    }
-
-    /* ++bjoern:
-     * Determine hardware present
-     */
+       /* Set switches as requested by the user */
+       if (atari_switches & ATARI_SWITCH_IKBD)
+               acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID;
+       if (atari_switches & ATARI_SWITCH_MIDI)
+               acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
+       if (atari_switches & (ATARI_SWITCH_SND6|ATARI_SWITCH_SND7)) {
+               sound_ym.rd_data_reg_sel = 14;
+               sound_ym.wd_data = sound_ym.rd_data_reg_sel |
+                                  ((atari_switches&ATARI_SWITCH_SND6) ? 0x40 : 0) |
+                                  ((atari_switches&ATARI_SWITCH_SND7) ? 0x80 : 0);
+       }
 
-    printk( "Atari hardware found: " );
-    if (MACH_IS_MEDUSA || MACH_IS_HADES) {
-        /* There's no Atari video hardware on the Medusa, but all the
-         * addresses below generate a DTACK so no bus error occurs! */
-    }
-    else if (hwreg_present( f030_xreg )) {
-       ATARIHW_SET(VIDEL_SHIFTER);
-        printk( "VIDEL " );
-        /* This is a temporary hack: If there is Falcon video
-         * hardware, we assume that the ST-DMA serves SCSI instead of
-         * ACSI. In the future, there should be a better method for
-         * this...
-         */
-       ATARIHW_SET(ST_SCSI);
-        printk( "STDMA-SCSI " );
-    }
-    else if (hwreg_present( tt_palette )) {
-       ATARIHW_SET(TT_SHIFTER);
-        printk( "TT_SHIFTER " );
-    }
-    else if (hwreg_present( &shifter.bas_hi )) {
-        if (hwreg_present( &shifter.bas_lo ) &&
-           (shifter.bas_lo = 0x0aau, shifter.bas_lo == 0x0aau)) {
-           ATARIHW_SET(EXTD_SHIFTER);
-            printk( "EXTD_SHIFTER " );
-        }
-        else {
-           ATARIHW_SET(STND_SHIFTER);
-            printk( "STND_SHIFTER " );
-        }
-    }
-    if (hwreg_present( &mfp.par_dt_reg )) {
-       ATARIHW_SET(ST_MFP);
-        printk( "ST_MFP " );
-    }
-    if (hwreg_present( &tt_mfp.par_dt_reg )) {
-       ATARIHW_SET(TT_MFP);
-        printk( "TT_MFP " );
-    }
-    if (hwreg_present( &tt_scsi_dma.dma_addr_hi )) {
-       ATARIHW_SET(SCSI_DMA);
-        printk( "TT_SCSI_DMA " );
-    }
-    if (!MACH_IS_HADES && hwreg_present( &st_dma.dma_hi )) {
-       ATARIHW_SET(STND_DMA);
-        printk( "STND_DMA " );
-    }
-    if (MACH_IS_MEDUSA || /* The ST-DMA address registers aren't readable
-                          * on all Medusas, so the test below may fail */
-        (hwreg_present( &st_dma.dma_vhi ) &&
-         (st_dma.dma_vhi = 0x55) && (st_dma.dma_hi = 0xaa) &&
-         st_dma.dma_vhi == 0x55 && st_dma.dma_hi == 0xaa &&
-         (st_dma.dma_vhi = 0xaa) && (st_dma.dma_hi = 0x55) &&
-         st_dma.dma_vhi == 0xaa && st_dma.dma_hi == 0x55)) {
-       ATARIHW_SET(EXTD_DMA);
-        printk( "EXTD_DMA " );
-    }
-    if (hwreg_present( &tt_scsi.scsi_data )) {
-       ATARIHW_SET(TT_SCSI);
-        printk( "TT_SCSI " );
-    }
-    if (hwreg_present( &sound_ym.rd_data_reg_sel )) {
-       ATARIHW_SET(YM_2149);
-        printk( "YM2149 " );
-    }
-    if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
-       hwreg_present( &tt_dmasnd.ctrl )) {
-       ATARIHW_SET(PCM_8BIT);
-        printk( "PCM " );
-    }
-    if (!MACH_IS_HADES && hwreg_present( &falcon_codec.unused5 )) {
-       ATARIHW_SET(CODEC);
-        printk( "CODEC " );
-    }
-    if (hwreg_present( &dsp56k_host_interface.icr )) {
-       ATARIHW_SET(DSP56K);
-        printk( "DSP56K " );
-    }
-    if (hwreg_present( &tt_scc_dma.dma_ctrl ) &&
+       /* ++bjoern:
+        * Determine hardware present
+        */
+
+       printk("Atari hardware found: ");
+       if (MACH_IS_MEDUSA || MACH_IS_HADES) {
+               /* There's no Atari video hardware on the Medusa, but all the
+                * addresses below generate a DTACK so no bus error occurs! */
+       } else if (hwreg_present(f030_xreg)) {
+               ATARIHW_SET(VIDEL_SHIFTER);
+               printk("VIDEL ");
+               /* This is a temporary hack: If there is Falcon video
+                * hardware, we assume that the ST-DMA serves SCSI instead of
+                * ACSI. In the future, there should be a better method for
+                * this...
+                */
+               ATARIHW_SET(ST_SCSI);
+               printk("STDMA-SCSI ");
+       } else if (hwreg_present(tt_palette)) {
+               ATARIHW_SET(TT_SHIFTER);
+               printk("TT_SHIFTER ");
+       } else if (hwreg_present(&shifter.bas_hi)) {
+               if (hwreg_present(&shifter.bas_lo) &&
+                   (shifter.bas_lo = 0x0aau, shifter.bas_lo == 0x0aau)) {
+                       ATARIHW_SET(EXTD_SHIFTER);
+                       printk("EXTD_SHIFTER ");
+               } else {
+                       ATARIHW_SET(STND_SHIFTER);
+                       printk("STND_SHIFTER ");
+               }
+       }
+       if (hwreg_present(&mfp.par_dt_reg)) {
+               ATARIHW_SET(ST_MFP);
+               printk("ST_MFP ");
+       }
+       if (hwreg_present(&tt_mfp.par_dt_reg)) {
+               ATARIHW_SET(TT_MFP);
+               printk("TT_MFP ");
+       }
+       if (hwreg_present(&tt_scsi_dma.dma_addr_hi)) {
+               ATARIHW_SET(SCSI_DMA);
+               printk("TT_SCSI_DMA ");
+       }
+       if (!MACH_IS_HADES && hwreg_present(&st_dma.dma_hi)) {
+               ATARIHW_SET(STND_DMA);
+               printk("STND_DMA ");
+       }
+       /*
+        * The ST-DMA address registers aren't readable
+        * on all Medusas, so the test below may fail
+        */
+       if (MACH_IS_MEDUSA ||
+           (hwreg_present(&st_dma.dma_vhi) &&
+            (st_dma.dma_vhi = 0x55) && (st_dma.dma_hi = 0xaa) &&
+            st_dma.dma_vhi == 0x55 && st_dma.dma_hi == 0xaa &&
+            (st_dma.dma_vhi = 0xaa) && (st_dma.dma_hi = 0x55) &&
+            st_dma.dma_vhi == 0xaa && st_dma.dma_hi == 0x55)) {
+               ATARIHW_SET(EXTD_DMA);
+               printk("EXTD_DMA ");
+       }
+       if (hwreg_present(&tt_scsi.scsi_data)) {
+               ATARIHW_SET(TT_SCSI);
+               printk("TT_SCSI ");
+       }
+       if (hwreg_present(&sound_ym.rd_data_reg_sel)) {
+               ATARIHW_SET(YM_2149);
+               printk("YM2149 ");
+       }
+       if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
+               hwreg_present(&tt_dmasnd.ctrl)) {
+               ATARIHW_SET(PCM_8BIT);
+               printk("PCM ");
+       }
+       if (!MACH_IS_HADES && hwreg_present(&falcon_codec.unused5)) {
+               ATARIHW_SET(CODEC);
+               printk("CODEC ");
+       }
+       if (hwreg_present(&dsp56k_host_interface.icr)) {
+               ATARIHW_SET(DSP56K);
+               printk("DSP56K ");
+       }
+       if (hwreg_present(&tt_scc_dma.dma_ctrl) &&
 #if 0
-       /* This test sucks! Who knows some better? */
-       (tt_scc_dma.dma_ctrl = 0x01, (tt_scc_dma.dma_ctrl & 1) == 1) &&
-       (tt_scc_dma.dma_ctrl = 0x00, (tt_scc_dma.dma_ctrl & 1) == 0)
+           /* This test sucks! Who knows some better? */
+           (tt_scc_dma.dma_ctrl = 0x01, (tt_scc_dma.dma_ctrl & 1) == 1) &&
+           (tt_scc_dma.dma_ctrl = 0x00, (tt_scc_dma.dma_ctrl & 1) == 0)
 #else
-       !MACH_IS_MEDUSA && !MACH_IS_HADES
+           !MACH_IS_MEDUSA && !MACH_IS_HADES
 #endif
-       ) {
-       ATARIHW_SET(SCC_DMA);
-        printk( "SCC_DMA " );
-    }
-    if (scc_test( &scc.cha_a_ctrl )) {
-       ATARIHW_SET(SCC);
-        printk( "SCC " );
-    }
-    if (scc_test( &st_escc.cha_b_ctrl )) {
-       ATARIHW_SET( ST_ESCC );
-       printk( "ST_ESCC " );
-    }
-    if (MACH_IS_HADES)
-    {
-        ATARIHW_SET( VME );
-        printk( "VME " );
-    }
-    else if (hwreg_present( &tt_scu.sys_mask )) {
-       ATARIHW_SET(SCU);
-       /* Assume a VME bus if there's a SCU */
-       ATARIHW_SET( VME );
-        printk( "VME SCU " );
-    }
-    if (hwreg_present( (void *)(0xffff9210) )) {
-       ATARIHW_SET(ANALOG_JOY);
-        printk( "ANALOG_JOY " );
-    }
-    if (!MACH_IS_HADES && hwreg_present( blitter.halftone )) {
-       ATARIHW_SET(BLITTER);
-        printk( "BLITTER " );
-    }
-    if (hwreg_present((void *)0xfff00039)) {
-       ATARIHW_SET(IDE);
-        printk( "IDE " );
-    }
+           ) {
+               ATARIHW_SET(SCC_DMA);
+               printk("SCC_DMA ");
+       }
+       if (scc_test(&scc.cha_a_ctrl)) {
+               ATARIHW_SET(SCC);
+               printk("SCC ");
+       }
+       if (scc_test(&st_escc.cha_b_ctrl)) {
+               ATARIHW_SET(ST_ESCC);
+               printk("ST_ESCC ");
+       }
+       if (MACH_IS_HADES) {
+               ATARIHW_SET(VME);
+               printk("VME ");
+       } else if (hwreg_present(&tt_scu.sys_mask)) {
+               ATARIHW_SET(SCU);
+               /* Assume a VME bus if there's a SCU */
+               ATARIHW_SET(VME);
+               printk("VME SCU ");
+       }
+       if (hwreg_present((void *)(0xffff9210))) {
+               ATARIHW_SET(ANALOG_JOY);
+               printk("ANALOG_JOY ");
+       }
+       if (!MACH_IS_HADES && hwreg_present(blitter.halftone)) {
+               ATARIHW_SET(BLITTER);
+               printk("BLITTER ");
+       }
+       if (hwreg_present((void *)0xfff00039)) {
+               ATARIHW_SET(IDE);
+               printk("IDE ");
+       }
 #if 1 /* This maybe wrong */
-    if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
-       hwreg_present( &tt_microwire.data ) &&
-       hwreg_present( &tt_microwire.mask ) &&
-       (tt_microwire.mask = 0x7ff,
-        udelay(1),
-        tt_microwire.data = MW_LM1992_PSG_HIGH | MW_LM1992_ADDR,
-        udelay(1),
-        tt_microwire.data != 0)) {
-       ATARIHW_SET(MICROWIRE);
-       while (tt_microwire.mask != 0x7ff) ;
-        printk( "MICROWIRE " );
-    }
+       if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
+           hwreg_present(&tt_microwire.data) &&
+           hwreg_present(&tt_microwire.mask) &&
+           (tt_microwire.mask = 0x7ff,
+            udelay(1),
+            tt_microwire.data = MW_LM1992_PSG_HIGH | MW_LM1992_ADDR,
+            udelay(1),
+            tt_microwire.data != 0)) {
+               ATARIHW_SET(MICROWIRE);
+               while (tt_microwire.mask != 0x7ff)
+                       ;
+               printk("MICROWIRE ");
+       }
 #endif
-    if (hwreg_present( &tt_rtc.regsel )) {
-       ATARIHW_SET(TT_CLK);
-        printk( "TT_CLK " );
-        mach_hwclk = atari_tt_hwclk;
-        mach_set_clock_mmss = atari_tt_set_clock_mmss;
-    }
-    if (!MACH_IS_HADES && hwreg_present( &mste_rtc.sec_ones)) {
-       ATARIHW_SET(MSTE_CLK);
-        printk( "MSTE_CLK ");
-        mach_hwclk = atari_mste_hwclk;
-        mach_set_clock_mmss = atari_mste_set_clock_mmss;
-    }
-    if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
-       hwreg_present( &dma_wd.fdc_speed ) &&
-       hwreg_write( &dma_wd.fdc_speed, 0 )) {
-           ATARIHW_SET(FDCSPEED);
-           printk( "FDC_SPEED ");
-    }
-    if (!MACH_IS_HADES && !ATARIHW_PRESENT(ST_SCSI)) {
-       ATARIHW_SET(ACSI);
-        printk( "ACSI " );
-    }
-    printk("\n");
-
-    if (CPU_IS_040_OR_060)
-        /* Now it seems to be safe to turn of the tt0 transparent
-         * translation (the one that must not be turned off in
-         * head.S...)
-         */
-        __asm__ volatile ("moveq #0,%/d0\n\t"
-                          ".chip 68040\n\t"
-                         "movec %%d0,%%itt0\n\t"
-                         "movec %%d0,%%dtt0\n\t"
-                         ".chip 68k"
-                                                 : /* no outputs */
-                                                 : /* no inputs */
-                                                 : "d0");
-
-    /* allocator for memory that must reside in st-ram */
-    atari_stram_init ();
-
-    /* Set up a mapping for the VMEbus address region:
-     *
-     * VME is either at phys. 0xfexxxxxx (TT) or 0xa00000..0xdfffff
-     * (MegaSTE) In both cases, the whole 16 MB chunk is mapped at
-     * 0xfe000000 virt., because this can be done with a single
-     * transparent translation. On the 68040, lots of often unused
-     * page tables would be needed otherwise. On a MegaSTE or similar,
-     * the highest byte is stripped off by hardware due to the 24 bit
-     * design of the bus.
-     */
+       if (hwreg_present(&tt_rtc.regsel)) {
+               ATARIHW_SET(TT_CLK);
+               printk("TT_CLK ");
+               mach_hwclk = atari_tt_hwclk;
+               mach_set_clock_mmss = atari_tt_set_clock_mmss;
+       }
+       if (!MACH_IS_HADES && hwreg_present(&mste_rtc.sec_ones)) {
+               ATARIHW_SET(MSTE_CLK);
+               printk("MSTE_CLK ");
+               mach_hwclk = atari_mste_hwclk;
+               mach_set_clock_mmss = atari_mste_set_clock_mmss;
+       }
+       if (!MACH_IS_MEDUSA && !MACH_IS_HADES &&
+           hwreg_present(&dma_wd.fdc_speed) &&
+           hwreg_write(&dma_wd.fdc_speed, 0)) {
+               ATARIHW_SET(FDCSPEED);
+               printk("FDC_SPEED ");
+       }
+       if (!MACH_IS_HADES && !ATARIHW_PRESENT(ST_SCSI)) {
+               ATARIHW_SET(ACSI);
+               printk("ACSI ");
+       }
+       printk("\n");
+
+       if (CPU_IS_040_OR_060)
+               /* Now it seems to be safe to turn of the tt0 transparent
+                * translation (the one that must not be turned off in
+                * head.S...)
+                */
+               asm volatile ("\n"
+                       "       moveq   #0,%%d0\n"
+                       "       .chip   68040\n"
+                       "       movec   %%d0,%%itt0\n"
+                       "       movec   %%d0,%%dtt0\n"
+                       "       .chip   68k"
+                       : /* no outputs */
+                       : /* no inputs */
+                       : "d0");
+
+       /* allocator for memory that must reside in st-ram */
+       atari_stram_init();
+
+       /* Set up a mapping for the VMEbus address region:
+        *
+        * VME is either at phys. 0xfexxxxxx (TT) or 0xa00000..0xdfffff
+        * (MegaSTE) In both cases, the whole 16 MB chunk is mapped at
+        * 0xfe000000 virt., because this can be done with a single
+        * transparent translation. On the 68040, lots of often unused
+        * page tables would be needed otherwise. On a MegaSTE or similar,
+        * the highest byte is stripped off by hardware due to the 24 bit
+        * design of the bus.
+        */
+
+       if (CPU_IS_020_OR_030) {
+               unsigned long tt1_val;
+               tt1_val = 0xfe008543;   /* Translate 0xfexxxxxx, enable, cache
+                                        * inhibit, read and write, FDC mask = 3,
+                                        * FDC val = 4 -> Supervisor only */
+               asm volatile ("\n"
+                       "       .chip   68030\n"
+                       "       pmove   %0@,%/tt1\n"
+                       "       .chip   68k"
+                       : : "a" (&tt1_val));
+       } else {
+               asm volatile ("\n"
+                       "       .chip   68040\n"
+                       "       movec   %0,%%itt1\n"
+                       "       movec   %0,%%dtt1\n"
+                       "       .chip   68k"
+                       :
+                       : "d" (0xfe00a040));    /* Translate 0xfexxxxxx, enable,
+                                                * supervisor only, non-cacheable/
+                                                * serialized, writable */
+
+       }
 
-    if (CPU_IS_020_OR_030) {
-        unsigned long  tt1_val;
-        tt1_val = 0xfe008543;  /* Translate 0xfexxxxxx, enable, cache
-                                 * inhibit, read and write, FDC mask = 3,
-                                 * FDC val = 4 -> Supervisor only */
-        __asm__ __volatile__ ( ".chip 68030\n\t"
-                               "pmove  %0@,%/tt1\n\t"
-                               ".chip 68k"
-                               : : "a" (&tt1_val) );
-    }
-    else {
-        __asm__ __volatile__
-            ( "movel %0,%/d0\n\t"
-             ".chip 68040\n\t"
-             "movec %%d0,%%itt1\n\t"
-             "movec %%d0,%%dtt1\n\t"
-             ".chip 68k"
-              :
-              : "g" (0xfe00a040)       /* Translate 0xfexxxxxx, enable,
-                                         * supervisor only, non-cacheable/
-                                         * serialized, writable */
-              : "d0" );
-
-    }
-
-    /* Fetch tos version at Physical 2 */
-    /* We my not be able to access this address if the kernel is
-       loaded to st ram, since the first page is unmapped.  On the
-       Medusa this is always the case and there is nothing we can do
-       about this, so we just assume the smaller offset.  For the TT
-       we use the fact that in head.S we have set up a mapping
-       0xFFxxxxxx -> 0x00xxxxxx, so that the first 16MB is accessible
-       in the last 16MB of the address space. */
-    tos_version = (MACH_IS_MEDUSA || MACH_IS_HADES) ?
-                 0xfff : *(unsigned short *)0xff000002;
-    atari_rtc_year_offset = (tos_version < 0x306) ? 70 : 68;
+       /* Fetch tos version at Physical 2 */
+       /*
+        * We my not be able to access this address if the kernel is
+        * loaded to st ram, since the first page is unmapped.  On the
+        * Medusa this is always the case and there is nothing we can do
+        * about this, so we just assume the smaller offset.  For the TT
+        * we use the fact that in head.S we have set up a mapping
+        * 0xFFxxxxxx -> 0x00xxxxxx, so that the first 16MB is accessible
+        * in the last 16MB of the address space.
+        */
+       tos_version = (MACH_IS_MEDUSA || MACH_IS_HADES) ?
+                       0xfff : *(unsigned short *)0xff000002;
+       atari_rtc_year_offset = (tos_version < 0x306) ? 70 : 68;
 }
 
 #ifdef CONFIG_HEARTBEAT
-static void atari_heartbeat( int on )
+static void atari_heartbeat(int on)
 {
-    unsigned char tmp;
-    unsigned long flags;
+       unsigned char tmp;
+       unsigned long flags;
 
-    if (atari_dont_touch_floppy_select)
-       return;
+       if (atari_dont_touch_floppy_select)
+               return;
 
-    local_irq_save(flags);
-    sound_ym.rd_data_reg_sel = 14; /* Select PSG Port A */
-    tmp = sound_ym.rd_data_reg_sel;
-    sound_ym.wd_data = on ? (tmp & ~0x02) : (tmp | 0x02);
-    local_irq_restore(flags);
+       local_irq_save(flags);
+       sound_ym.rd_data_reg_sel = 14;  /* Select PSG Port A */
+       tmp = sound_ym.rd_data_reg_sel;
+       sound_ym.wd_data = on ? (tmp & ~0x02) : (tmp | 0x02);
+       local_irq_restore(flags);
 }
 #endif
 
@@ -526,180 +491,171 @@ static void atari_heartbeat( int on )
 
 /* ++andreas: no need for complicated code, just depend on prefetch */
 
-static void atari_reset (void)
+static void atari_reset(void)
 {
-    long tc_val = 0;
-    long reset_addr;
-
-    /* On the Medusa, phys. 0x4 may contain garbage because it's no
-       ROM.  See above for explanation why we cannot use PTOV(4). */
-    reset_addr = MACH_IS_HADES ? 0x7fe00030 :
-                 MACH_IS_MEDUSA || MACH_IS_AB40 ? 0xe00030 :
-                *(unsigned long *) 0xff000004;
-
-    /* reset ACIA for switch off OverScan, if it's active */
-    if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
-       acia.key_ctrl = ACIA_RESET;
-    if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
-       acia.mid_ctrl = ACIA_RESET;
-
-    /* processor independent: turn off interrupts and reset the VBR;
-     * the caches must be left enabled, else prefetching the final jump
-     * instruction doesn't work. */
-    local_irq_disable();
-    __asm__ __volatile__
-       ("moveq #0,%/d0\n\t"
-        "movec %/d0,%/vbr"
-        : : : "d0" );
-
-    if (CPU_IS_040_OR_060) {
-        unsigned long jmp_addr040 = virt_to_phys(&&jmp_addr_label040);
-       if (CPU_IS_060) {
-           /* 68060: clear PCR to turn off superscalar operation */
-           __asm__ __volatile__
-               ("moveq #0,%/d0\n\t"
-                ".chip 68060\n\t"
-                "movec %%d0,%%pcr\n\t"
-                ".chip 68k"
-                : : : "d0" );
-       }
-
-        __asm__ __volatile__
-            ("movel    %0,%/d0\n\t"
-             "andl     #0xff000000,%/d0\n\t"
-             "orw      #0xe020,%/d0\n\t"   /* map 16 MB, enable, cacheable */
-             ".chip 68040\n\t"
-            "movec    %%d0,%%itt0\n\t"
-             "movec    %%d0,%%dtt0\n\t"
-            ".chip 68k\n\t"
-             "jmp   %0@\n\t"
-             : /* no outputs */
-             : "a" (jmp_addr040)
-             : "d0" );
-      jmp_addr_label040:
-        __asm__ __volatile__
-          ("moveq #0,%/d0\n\t"
-          "nop\n\t"
-          ".chip 68040\n\t"
-          "cinva %%bc\n\t"
-          "nop\n\t"
-          "pflusha\n\t"
-          "nop\n\t"
-          "movec %%d0,%%tc\n\t"
-          "nop\n\t"
-          /* the following setup of transparent translations is needed on the
-           * Afterburner040 to successfully reboot. Other machines shouldn't
-           * care about a different tt regs setup, they also didn't care in
-           * the past that the regs weren't turned off. */
-          "movel #0xffc000,%%d0\n\t" /* whole insn space cacheable */
-          "movec %%d0,%%itt0\n\t"
-          "movec %%d0,%%itt1\n\t"
-          "orw   #0x40,%/d0\n\t" /* whole data space non-cacheable/ser. */
-          "movec %%d0,%%dtt0\n\t"
-          "movec %%d0,%%dtt1\n\t"
-          ".chip 68k\n\t"
-           "jmp %0@"
-           : /* no outputs */
-           : "a" (reset_addr)
-           : "d0");
-    }
-    else
-        __asm__ __volatile__
-            ("pmove %0@,%/tc\n\t"
-             "jmp %1@"
-             : /* no outputs */
-             : "a" (&tc_val), "a" (reset_addr));
+       long tc_val = 0;
+       long reset_addr;
+
+       /*
+        * On the Medusa, phys. 0x4 may contain garbage because it's no
+        * ROM.  See above for explanation why we cannot use PTOV(4).
+        */
+       reset_addr = MACH_IS_HADES ? 0x7fe00030 :
+                    MACH_IS_MEDUSA || MACH_IS_AB40 ? 0xe00030 :
+                    *(unsigned long *) 0xff000004;
+
+       /* reset ACIA for switch off OverScan, if it's active */
+       if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
+               acia.key_ctrl = ACIA_RESET;
+       if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
+               acia.mid_ctrl = ACIA_RESET;
+
+       /* processor independent: turn off interrupts and reset the VBR;
+        * the caches must be left enabled, else prefetching the final jump
+        * instruction doesn't work.
+        */
+       local_irq_disable();
+       asm volatile ("movec    %0,%%vbr"
+                       : : "d" (0));
+
+       if (CPU_IS_040_OR_060) {
+               unsigned long jmp_addr040 = virt_to_phys(&&jmp_addr_label040);
+               if (CPU_IS_060) {
+                       /* 68060: clear PCR to turn off superscalar operation */
+                       asm volatile ("\n"
+                               "       .chip 68060\n"
+                               "       movec %0,%%pcr\n"
+                               "       .chip 68k"
+                               : : "d" (0));
+               }
+
+               asm volatile ("\n"
+                       "       move.l  %0,%%d0\n"
+                       "       and.l   #0xff000000,%%d0\n"
+                       "       or.w    #0xe020,%%d0\n"   /* map 16 MB, enable, cacheable */
+                       "       .chip   68040\n"
+                       "       movec   %%d0,%%itt0\n"
+                       "       movec   %%d0,%%dtt0\n"
+                       "       .chip   68k\n"
+                       "       jmp     %0@"
+                       : : "a" (jmp_addr040)
+                       : "d0");
+       jmp_addr_label040:
+               asm volatile ("\n"
+                       "       moveq   #0,%%d0\n"
+                       "       nop\n"
+                       "       .chip   68040\n"
+                       "       cinva   %%bc\n"
+                       "       nop\n"
+                       "       pflusha\n"
+                       "       nop\n"
+                       "       movec   %%d0,%%tc\n"
+                       "       nop\n"
+                       /* the following setup of transparent translations is needed on the
+                        * Afterburner040 to successfully reboot. Other machines shouldn't
+                        * care about a different tt regs setup, they also didn't care in
+                        * the past that the regs weren't turned off. */
+                       "       move.l  #0xffc000,%%d0\n" /* whole insn space cacheable */
+                       "       movec   %%d0,%%itt0\n"
+                       "       movec   %%d0,%%itt1\n"
+                       "       or.w    #0x40,%/d0\n" /* whole data space non-cacheable/ser. */
+                       "       movec   %%d0,%%dtt0\n"
+                       "       movec   %%d0,%%dtt1\n"
+                       "       .chip   68k\n"
+                       "       jmp     %0@"
+                       : /* no outputs */
+                       : "a" (reset_addr)
+                       : "d0");
+       } else
+               asm volatile ("\n"
+                       "       pmove   %0@,%%tc\n"
+                       "       jmp     %1@"
+                       : /* no outputs */
+                       : "a" (&tc_val), "a" (reset_addr));
 }
 
 
 static void atari_get_model(char *model)
 {
-    strcpy(model, "Atari ");
-    switch (atari_mch_cookie >> 16) {
+       strcpy(model, "Atari ");
+       switch (atari_mch_cookie >> 16) {
        case ATARI_MCH_ST:
-           if (ATARIHW_PRESENT(MSTE_CLK))
-               strcat (model, "Mega ST");
-           else
-               strcat (model, "ST");
-           break;
+               if (ATARIHW_PRESENT(MSTE_CLK))
+                       strcat(model, "Mega ST");
+               else
+                       strcat(model, "ST");
+               break;
        case ATARI_MCH_STE:
-           if (MACH_IS_MSTE)
-               strcat (model, "Mega STE");
-           else
-               strcat (model, "STE");
-           break;
+               if (MACH_IS_MSTE)
+                       strcat(model, "Mega STE");
+               else
+                       strcat(model, "STE");
+               break;
        case ATARI_MCH_TT:
-           if (MACH_IS_MEDUSA)
-               /* Medusa has TT _MCH cookie */
-               strcat (model, "Medusa");
-           else if (MACH_IS_HADES)
-               strcat(model, "Hades");
-           else
-               strcat (model, "TT");
-           break;
+               if (MACH_IS_MEDUSA)
+                       /* Medusa has TT _MCH cookie */
+                       strcat(model, "Medusa");
+               else if (MACH_IS_HADES)
+                       strcat(model, "Hades");
+               else
+                       strcat(model, "TT");
+               break;
        case ATARI_MCH_FALCON:
-           strcat (model, "Falcon");
-           if (MACH_IS_AB40)
-               strcat (model, " (with Afterburner040)");
-           break;
+               strcat(model, "Falcon");
+               if (MACH_IS_AB40)
+                       strcat(model, " (with Afterburner040)");
+               break;
        default:
-           sprintf (model + strlen (model), "(unknown mach cookie 0x%lx)",
-                    atari_mch_cookie);
-           break;
-    }
+               sprintf(model + strlen(model), "(unknown mach cookie 0x%lx)",
+                       atari_mch_cookie);
+               break;
+       }
 }
 
 
 static int atari_get_hardware_list(char *buffer)
 {
-    int len = 0, i;
-
-    for (i = 0; i < m68k_num_memory; i++)
-       len += sprintf (buffer+len, "\t%3ld MB at 0x%08lx (%s)\n",
-                       m68k_memory[i].size >> 20, m68k_memory[i].addr,
-                       (m68k_memory[i].addr & 0xff000000 ?
-                        "alternate RAM" : "ST-RAM"));
-
-#define ATARIHW_ANNOUNCE(name,str)                             \
-    if (ATARIHW_PRESENT(name))                 \
-       len += sprintf (buffer + len, "\t%s\n", str)
-
-    len += sprintf (buffer + len, "Detected hardware:\n");
-    ATARIHW_ANNOUNCE(STND_SHIFTER, "ST Shifter");
-    ATARIHW_ANNOUNCE(EXTD_SHIFTER, "STe Shifter");
-    ATARIHW_ANNOUNCE(TT_SHIFTER, "TT Shifter");
-    ATARIHW_ANNOUNCE(VIDEL_SHIFTER, "Falcon Shifter");
-    ATARIHW_ANNOUNCE(YM_2149, "Programmable Sound Generator");
-    ATARIHW_ANNOUNCE(PCM_8BIT, "PCM 8 Bit Sound");
-    ATARIHW_ANNOUNCE(CODEC, "CODEC Sound");
-    ATARIHW_ANNOUNCE(TT_SCSI, "SCSI Controller NCR5380 (TT style)");
-    ATARIHW_ANNOUNCE(ST_SCSI, "SCSI Controller NCR5380 (Falcon style)");
-    ATARIHW_ANNOUNCE(ACSI, "ACSI Interface");
-    ATARIHW_ANNOUNCE(IDE, "IDE Interface");
-    ATARIHW_ANNOUNCE(FDCSPEED, "8/16 Mhz Switch for FDC");
-    ATARIHW_ANNOUNCE(ST_MFP, "Multi Function Peripheral MFP 68901");
-    ATARIHW_ANNOUNCE(TT_MFP, "Second Multi Function Peripheral MFP 68901");
-    ATARIHW_ANNOUNCE(SCC, "Serial Communications Controller SCC 8530");
-    ATARIHW_ANNOUNCE(ST_ESCC, "Extended Serial Communications Controller SCC 85230");
-    ATARIHW_ANNOUNCE(ANALOG_JOY, "Paddle Interface");
-    ATARIHW_ANNOUNCE(MICROWIRE, "MICROWIRE(tm) Interface");
-    ATARIHW_ANNOUNCE(STND_DMA, "DMA Controller (24 bit)");
-    ATARIHW_ANNOUNCE(EXTD_DMA, "DMA Controller (32 bit)");
-    ATARIHW_ANNOUNCE(SCSI_DMA, "DMA Controller for NCR5380");
-    ATARIHW_ANNOUNCE(SCC_DMA, "DMA Controller for SCC");
-    ATARIHW_ANNOUNCE(TT_CLK, "Clock Chip MC146818A");
-    ATARIHW_ANNOUNCE(MSTE_CLK, "Clock Chip RP5C15");
-    ATARIHW_ANNOUNCE(SCU, "System Control Unit");
-    ATARIHW_ANNOUNCE(BLITTER, "Blitter");
-    ATARIHW_ANNOUNCE(VME, "VME Bus");
-    ATARIHW_ANNOUNCE(DSP56K, "DSP56001 processor");
-
-    return(len);
+       int len = 0, i;
+
+       for (i = 0; i < m68k_num_memory; i++)
+               len += sprintf(buffer+len, "\t%3ld MB at 0x%08lx (%s)\n",
+                               m68k_memory[i].size >> 20, m68k_memory[i].addr,
+                               (m68k_memory[i].addr & 0xff000000 ?
+                                "alternate RAM" : "ST-RAM"));
+
+#define ATARIHW_ANNOUNCE(name, str)                    \
+       if (ATARIHW_PRESENT(name))                      \
+               len += sprintf(buffer + len, "\t%s\n", str)
+
+       len += sprintf(buffer + len, "Detected hardware:\n");
+       ATARIHW_ANNOUNCE(STND_SHIFTER, "ST Shifter");
+       ATARIHW_ANNOUNCE(EXTD_SHIFTER, "STe Shifter");
+       ATARIHW_ANNOUNCE(TT_SHIFTER, "TT Shifter");
+       ATARIHW_ANNOUNCE(VIDEL_SHIFTER, "Falcon Shifter");
+       ATARIHW_ANNOUNCE(YM_2149, "Programmable Sound Generator");
+       ATARIHW_ANNOUNCE(PCM_8BIT, "PCM 8 Bit Sound");
+       ATARIHW_ANNOUNCE(CODEC, "CODEC Sound");
+       ATARIHW_ANNOUNCE(TT_SCSI, "SCSI Controller NCR5380 (TT style)");
+       ATARIHW_ANNOUNCE(ST_SCSI, "SCSI Controller NCR5380 (Falcon style)");
+       ATARIHW_ANNOUNCE(ACSI, "ACSI Interface");
+       ATARIHW_ANNOUNCE(IDE, "IDE Interface");
+       ATARIHW_ANNOUNCE(FDCSPEED, "8/16 Mhz Switch for FDC");
+       ATARIHW_ANNOUNCE(ST_MFP, "Multi Function Peripheral MFP 68901");
+       ATARIHW_ANNOUNCE(TT_MFP, "Second Multi Function Peripheral MFP 68901");
+       ATARIHW_ANNOUNCE(SCC, "Serial Communications Controller SCC 8530");
+       ATARIHW_ANNOUNCE(ST_ESCC, "Extended Serial Communications Controller SCC 85230");
+       ATARIHW_ANNOUNCE(ANALOG_JOY, "Paddle Interface");
+       ATARIHW_ANNOUNCE(MICROWIRE, "MICROWIRE(tm) Interface");
+       ATARIHW_ANNOUNCE(STND_DMA, "DMA Controller (24 bit)");
+       ATARIHW_ANNOUNCE(EXTD_DMA, "DMA Controller (32 bit)");
+       ATARIHW_ANNOUNCE(SCSI_DMA, "DMA Controller for NCR5380");
+       ATARIHW_ANNOUNCE(SCC_DMA, "DMA Controller for SCC");
+       ATARIHW_ANNOUNCE(TT_CLK, "Clock Chip MC146818A");
+       ATARIHW_ANNOUNCE(MSTE_CLK, "Clock Chip RP5C15");
+       ATARIHW_ANNOUNCE(SCU, "System Control Unit");
+       ATARIHW_ANNOUNCE(BLITTER, "Blitter");
+       ATARIHW_ANNOUNCE(VME, "VME Bus");
+       ATARIHW_ANNOUNCE(DSP56K, "DSP56001 processor");
+
+       return len;
 }
-
-/*
- * Local variables:
- *  c-indent-level: 4
- *  tab-width: 8
- * End:
- */
index 4ae0100..fbeed8c 100644 (file)
@@ -19,8 +19,6 @@
 #include <asm/atarihw.h>
 #include <asm/atariints.h>
 
-extern char m68k_debug_device[];
-
 /* Flag that Modem1 port is already initialized and used */
 int atari_MFP_init_done;
 /* Flag that Modem1 port is already initialized and used */
@@ -30,317 +28,317 @@ int atari_SCC_init_done;
 int atari_SCC_reset_done;
 
 static struct console atari_console_driver = {
-       .name =         "debug",
-       .flags =        CON_PRINTBUFFER,
-       .index =        -1,
+       .name   = "debug",
+       .flags  = CON_PRINTBUFFER,
+       .index  = -1,
 };
 
 
-static inline void ata_mfp_out (char c)
+static inline void ata_mfp_out(char c)
 {
-    while (!(mfp.trn_stat & 0x80)) /* wait for tx buf empty */
-       barrier ();
-    mfp.usart_dta = c;
+       while (!(mfp.trn_stat & 0x80))  /* wait for tx buf empty */
+               barrier();
+       mfp.usart_dta = c;
 }
 
-void atari_mfp_console_write (struct console *co, const char *str,
-                             unsigned int count)
+void atari_mfp_console_write(struct console *co, const char *str,
+                            unsigned int count)
 {
-    while (count--) {
-       if (*str == '\n')
-           ata_mfp_out( '\r' );
-       ata_mfp_out( *str++ );
-    }
+       while (count--) {
+               if (*str == '\n')
+                       ata_mfp_out('\r');
+               ata_mfp_out(*str++);
+       }
 }
 
-static inline void ata_scc_out (char c)
+static inline void ata_scc_out(char c)
 {
-    do {
+       do {
+               MFPDELAY();
+       } while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
        MFPDELAY();
-    } while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
-    MFPDELAY();
-    scc.cha_b_data = c;
+       scc.cha_b_data = c;
 }
 
-void atari_scc_console_write (struct console *co, const char *str,
-                             unsigned int count)
+void atari_scc_console_write(struct console *co, const char *str,
+                            unsigned int count)
 {
-    while (count--) {
-       if (*str == '\n')
-           ata_scc_out( '\r' );
-       ata_scc_out( *str++ );
-    }
+       while (count--) {
+               if (*str == '\n')
+                       ata_scc_out('\r');
+               ata_scc_out(*str++);
+       }
 }
 
-static inline void ata_midi_out (char c)
+static inline void ata_midi_out(char c)
 {
-    while (!(acia.mid_ctrl & ACIA_TDRE)) /* wait for tx buf empty */
-       barrier ();
-    acia.mid_data = c;
+       while (!(acia.mid_ctrl & ACIA_TDRE))    /* wait for tx buf empty */
+               barrier();
+       acia.mid_data = c;
 }
 
-void atari_midi_console_write (struct console *co, const char *str,
-                              unsigned int count)
+void atari_midi_console_write(struct console *co, const char *str,
+                             unsigned int count)
 {
-    while (count--) {
-       if (*str == '\n')
-           ata_midi_out( '\r' );
-       ata_midi_out( *str++ );
-    }
+       while (count--) {
+               if (*str == '\n')
+                       ata_midi_out('\r');
+               ata_midi_out(*str++);
+       }
 }
 
-static int ata_par_out (char c)
+static int ata_par_out(char c)
 {
-    unsigned char tmp;
-    /* This a some-seconds timeout in case no printer is connected */
-    unsigned long i = loops_per_jiffy > 1 ? loops_per_jiffy : 10000000/HZ;
-
-    while( (mfp.par_dt_reg & 1) && --i ) /* wait for BUSY == L */
-       ;
-    if (!i) return( 0 );
-
-    sound_ym.rd_data_reg_sel = 15;  /* select port B */
-    sound_ym.wd_data = c;           /* put char onto port */
-    sound_ym.rd_data_reg_sel = 14;  /* select port A */
-    tmp = sound_ym.rd_data_reg_sel;
-    sound_ym.wd_data = tmp & ~0x20; /* set strobe L */
-    MFPDELAY();                     /* wait a bit */
-    sound_ym.wd_data = tmp | 0x20;  /* set strobe H */
-    return( 1 );
+       unsigned char tmp;
+       /* This a some-seconds timeout in case no printer is connected */
+       unsigned long i = loops_per_jiffy > 1 ? loops_per_jiffy : 10000000/HZ;
+
+       while ((mfp.par_dt_reg & 1) && --i) /* wait for BUSY == L */
+               ;
+       if (!i)
+               return 0;
+
+       sound_ym.rd_data_reg_sel = 15;  /* select port B */
+       sound_ym.wd_data = c;           /* put char onto port */
+       sound_ym.rd_data_reg_sel = 14;  /* select port A */
+       tmp = sound_ym.rd_data_reg_sel;
+       sound_ym.wd_data = tmp & ~0x20; /* set strobe L */
+       MFPDELAY();                     /* wait a bit */
+       sound_ym.wd_data = tmp | 0x20;  /* set strobe H */
+       return 1;
 }
 
-static void atari_par_console_write (struct console *co, const char *str,
-                                    unsigned int count)
+static void atari_par_console_write(struct console *co, const char *str,
+                                   unsigned int count)
 {
-    static int printer_present = 1;
+       static int printer_present = 1;
 
-    if (!printer_present)
-       return;
-
-    while (count--) {
-       if (*str == '\n')
-           if (!ata_par_out( '\r' )) {
-               printer_present = 0;
+       if (!printer_present)
                return;
-           }
-       if (!ata_par_out( *str++ )) {
-           printer_present = 0;
-           return;
+
+       while (count--) {
+               if (*str == '\n') {
+                       if (!ata_par_out('\r')) {
+                               printer_present = 0;
+                               return;
+                       }
+               }
+               if (!ata_par_out(*str++)) {
+                       printer_present = 0;
+                       return;
+               }
        }
-    }
 }
 
 #ifdef CONFIG_SERIAL_CONSOLE
 int atari_mfp_console_wait_key(struct console *co)
 {
-    while( !(mfp.rcv_stat & 0x80) ) /* wait for rx buf filled */
-       barrier();
-    return( mfp.usart_dta );
+       while (!(mfp.rcv_stat & 0x80))  /* wait for rx buf filled */
+               barrier();
+       return mfp.usart_dta;
 }
 
 int atari_scc_console_wait_key(struct console *co)
 {
-    do {
+       do {
+               MFPDELAY();
+       } while (!(scc.cha_b_ctrl & 0x01)); /* wait for rx buf filled */
        MFPDELAY();
-    } while( !(scc.cha_b_ctrl & 0x01) ); /* wait for rx buf filled */
-    MFPDELAY();
-    return( scc.cha_b_data );
+       return scc.cha_b_data;
 }
 
 int atari_midi_console_wait_key(struct console *co)
 {
-    while( !(acia.mid_ctrl & ACIA_RDRF) ) /* wait for rx buf filled */
-       barrier();
-    return( acia.mid_data );
+       while (!(acia.mid_ctrl & ACIA_RDRF)) /* wait for rx buf filled */
+               barrier();
+       return acia.mid_data;
 }
 #endif
 
-/* The following two functions do a quick'n'dirty initialization of the MFP or
+/*
+ * The following two functions do a quick'n'dirty initialization of the MFP or
  * SCC serial ports. They're used by the debugging interface, kgdb, and the
- * serial console code. */
+ * serial console code.
+ */
 #ifndef CONFIG_SERIAL_CONSOLE
-static void __init atari_init_mfp_port( int cflag )
+static void __init atari_init_mfp_port(int cflag)
 #else
-void atari_init_mfp_port( int cflag )
+void atari_init_mfp_port(int cflag)
 #endif
 {
-    /* timer values for 1200...115200 bps; > 38400 select 110, 134, or 150
-     * bps, resp., and work only correct if there's a RSVE or RSSPEED */
-    static int baud_table[9] = { 16, 11, 8, 4, 2, 1, 175, 143, 128 };
-    int baud = cflag & CBAUD;
-    int parity = (cflag & PARENB) ? ((cflag & PARODD) ? 0x04 : 0x06) : 0;
-    int csize = ((cflag & CSIZE) == CS7) ? 0x20 : 0x00;
-
-    if (cflag & CBAUDEX)
-       baud += B38400;
-    if (baud < B1200 || baud > B38400+2)
-       baud = B9600; /* use default 9600bps for non-implemented rates */
-    baud -= B1200; /* baud_table[] starts at 1200bps */
-
-    mfp.trn_stat &= ~0x01; /* disable TX */
-    mfp.usart_ctr = parity | csize | 0x88; /* 1:16 clk mode, 1 stop bit */
-    mfp.tim_ct_cd &= 0x70;  /* stop timer D */
-    mfp.tim_dt_d = baud_table[baud];
-    mfp.tim_ct_cd |= 0x01;  /* start timer D, 1:4 */
-    mfp.trn_stat |= 0x01;  /* enable TX */
-
-    atari_MFP_init_done = 1;
+       /*
+        * timer values for 1200...115200 bps; > 38400 select 110, 134, or 150
+        * bps, resp., and work only correct if there's a RSVE or RSSPEED
+        */
+       static int baud_table[9] = { 16, 11, 8, 4, 2, 1, 175, 143, 128 };
+       int baud = cflag & CBAUD;
+       int parity = (cflag & PARENB) ? ((cflag & PARODD) ? 0x04 : 0x06) : 0;
+       int csize = ((cflag & CSIZE) == CS7) ? 0x20 : 0x00;
+
+       if (cflag & CBAUDEX)
+               baud += B38400;
+       if (baud < B1200 || baud > B38400+2)
+               baud = B9600;           /* use default 9600bps for non-implemented rates */
+       baud -= B1200;                  /* baud_table[] starts at 1200bps */
+
+       mfp.trn_stat &= ~0x01;          /* disable TX */
+       mfp.usart_ctr = parity | csize | 0x88; /* 1:16 clk mode, 1 stop bit */
+       mfp.tim_ct_cd &= 0x70;          /* stop timer D */
+       mfp.tim_dt_d = baud_table[baud];
+       mfp.tim_ct_cd |= 0x01;          /* start timer D, 1:4 */
+       mfp.trn_stat |= 0x01;           /* enable TX */
+
+       atari_MFP_init_done = 1;
 }
 
-#define SCC_WRITE(reg,val)                             \
-    do {                                               \
-       scc.cha_b_ctrl = (reg);                         \
-       MFPDELAY();                                     \
-       scc.cha_b_ctrl = (val);                         \
-       MFPDELAY();                                     \
-    } while(0)
+#define SCC_WRITE(reg, val)                            \
+       do {                                            \
+               scc.cha_b_ctrl = (reg);                 \
+               MFPDELAY();                             \
+               scc.cha_b_ctrl = (val);                 \
+               MFPDELAY();                             \
+       } while (0)
 
 /* loops_per_jiffy isn't initialized yet, so we can't use udelay(). This does a
  * delay of ~ 60us. */
-#define LONG_DELAY()                           \
-    do {                                       \
-       int i;                                  \
-       for( i = 100; i > 0; --i )              \
-           MFPDELAY();                         \
-    } while(0)
+#define LONG_DELAY()                                   \
+       do {                                            \
+               int i;                                  \
+               for (i = 100; i > 0; --i)               \
+                       MFPDELAY();                     \
+       } while (0)
 
 #ifndef CONFIG_SERIAL_CONSOLE
-static void __init atari_init_scc_port( int cflag )
+static void __init atari_init_scc_port(int cflag)
 #else
-void atari_init_scc_port( int cflag )
+void atari_init_scc_port(int cflag)
 #endif
 {
-    extern int atari_SCC_reset_done;
-    static int clksrc_table[9] =
-       /* reg 11: 0x50 = BRG, 0x00 = RTxC, 0x28 = TRxC */
-       { 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 };
-    static int brgsrc_table[9] =
-       /* reg 14: 0 = RTxC, 2 = PCLK */
-       { 2, 2, 2, 2, 2, 2, 0, 2, 2 };
-    static int clkmode_table[9] =
-       /* reg 4: 0x40 = x16, 0x80 = x32, 0xc0 = x64 */
-       { 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0, 0x80 };
-    static int div_table[9] =
-       /* reg12 (BRG low) */
-       { 208, 138, 103, 50, 24, 11, 1, 0, 0 };
-
-    int baud = cflag & CBAUD;
-    int clksrc, clkmode, div, reg3, reg5;
-
-    if (cflag & CBAUDEX)
-       baud += B38400;
-    if (baud < B1200 || baud > B38400+2)
-       baud = B9600; /* use default 9600bps for non-implemented rates */
-    baud -= B1200; /* tables starts at 1200bps */
-
-    clksrc  = clksrc_table[baud];
-    clkmode = clkmode_table[baud];
-    div     = div_table[baud];
-    if (ATARIHW_PRESENT(TT_MFP) && baud >= 6) {
-       /* special treatment for TT, where rates >= 38400 are done via TRxC */
-       clksrc = 0x28; /* TRxC */
-       clkmode = baud == 6 ? 0xc0 :
-                 baud == 7 ? 0x80 : /* really 76800bps */
-                             0x40;  /* really 153600bps */
-       div = 0;
-    }
-
-    reg3 = (cflag & CSIZE) == CS8 ? 0xc0 : 0x40;
-    reg5 = (cflag & CSIZE) == CS8 ? 0x60 : 0x20 | 0x82 /* assert DTR/RTS */;
-
-    (void)scc.cha_b_ctrl;      /* reset reg pointer */
-    SCC_WRITE( 9, 0xc0 );      /* reset */
-    LONG_DELAY();              /* extra delay after WR9 access */
-    SCC_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
-                 0x04 /* 1 stopbit */ |
-                 clkmode );
-    SCC_WRITE( 3, reg3 );
-    SCC_WRITE( 5, reg5 );
-    SCC_WRITE( 9, 0 );         /* no interrupts */
-    LONG_DELAY();              /* extra delay after WR9 access */
-    SCC_WRITE( 10, 0 );                /* NRZ mode */
-    SCC_WRITE( 11, clksrc );   /* main clock source */
-    SCC_WRITE( 12, div );      /* BRG value */
-    SCC_WRITE( 13, 0 );                /* BRG high byte */
-    SCC_WRITE( 14, brgsrc_table[baud] );
-    SCC_WRITE( 14, brgsrc_table[baud] | (div ? 1 : 0) );
-    SCC_WRITE( 3, reg3 | 1 );
-    SCC_WRITE( 5, reg5 | 8 );
-
-    atari_SCC_reset_done = 1;
-    atari_SCC_init_done = 1;
+       extern int atari_SCC_reset_done;
+       static int clksrc_table[9] =
+               /* reg 11: 0x50 = BRG, 0x00 = RTxC, 0x28 = TRxC */
+               { 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 };
+       static int brgsrc_table[9] =
+               /* reg 14: 0 = RTxC, 2 = PCLK */
+               { 2, 2, 2, 2, 2, 2, 0, 2, 2 };
+       static int clkmode_table[9] =
+               /* reg 4: 0x40 = x16, 0x80 = x32, 0xc0 = x64 */
+               { 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0, 0x80 };
+       static int div_table[9] =
+               /* reg12 (BRG low) */
+               { 208, 138, 103, 50, 24, 11, 1, 0, 0 };
+
+       int baud = cflag & CBAUD;
+       int clksrc, clkmode, div, reg3, reg5;
+
+       if (cflag & CBAUDEX)
+               baud += B38400;
+       if (baud < B1200 || baud > B38400+2)
+               baud = B9600;           /* use default 9600bps for non-implemented rates */
+       baud -= B1200;                  /* tables starts at 1200bps */
+
+       clksrc  = clksrc_table[baud];
+       clkmode = clkmode_table[baud];
+       div     = div_table[baud];
+       if (ATARIHW_PRESENT(TT_MFP) && baud >= 6) {
+               /* special treatment for TT, where rates >= 38400 are done via TRxC */
+               clksrc = 0x28;          /* TRxC */
+               clkmode = baud == 6 ? 0xc0 :
+                         baud == 7 ? 0x80 : /* really 76800bps */
+                                     0x40;  /* really 153600bps */
+               div = 0;
+       }
+
+       reg3 = (cflag & CSIZE) == CS8 ? 0xc0 : 0x40;
+       reg5 = (cflag & CSIZE) == CS8 ? 0x60 : 0x20 | 0x82 /* assert DTR/RTS */;
+
+       (void)scc.cha_b_ctrl;           /* reset reg pointer */
+       SCC_WRITE(9, 0xc0);             /* reset */
+       LONG_DELAY();                   /* extra delay after WR9 access */
+       SCC_WRITE(4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03)
+                                     : 0 | 0x04 /* 1 stopbit */ | clkmode);
+       SCC_WRITE(3, reg3);
+       SCC_WRITE(5, reg5);
+       SCC_WRITE(9, 0);                /* no interrupts */
+       LONG_DELAY();                   /* extra delay after WR9 access */
+       SCC_WRITE(10, 0);               /* NRZ mode */
+       SCC_WRITE(11, clksrc);          /* main clock source */
+       SCC_WRITE(12, div);             /* BRG value */
+       SCC_WRITE(13, 0);               /* BRG high byte */
+       SCC_WRITE(14, brgsrc_table[baud]);
+       SCC_WRITE(14, brgsrc_table[baud] | (div ? 1 : 0));
+       SCC_WRITE(3, reg3 | 1);
+       SCC_WRITE(5, reg5 | 8);
+
+       atari_SCC_reset_done = 1;
+       atari_SCC_init_done = 1;
 }
 
 #ifndef CONFIG_SERIAL_CONSOLE
-static void __init atari_init_midi_port( int cflag )
+static void __init atari_init_midi_port(int cflag)
 #else
-void atari_init_midi_port( int cflag )
+void atari_init_midi_port(int cflag)
 #endif
 {
-    int baud = cflag & CBAUD;
-    int csize = ((cflag & CSIZE) == CS8) ? 0x10 : 0x00;
-    /* warning 7N1 isn't possible! (instead 7O2 is used...) */
-    int parity = (cflag & PARENB) ? ((cflag & PARODD) ? 0x0c : 0x08) : 0x04;
-    int div;
-
-    /* 4800 selects 7812.5, 115200 selects 500000, all other (incl. 9600 as
-     * default) the standard MIDI speed 31250. */
-    if (cflag & CBAUDEX)
-       baud += B38400;
-    if (baud == B4800)
-       div = ACIA_DIV64; /* really 7812.5 bps */
-    else if (baud == B38400+2 /* 115200 */)
-       div = ACIA_DIV1; /* really 500 kbps (does that work??) */
-    else
-       div = ACIA_DIV16; /* 31250 bps, standard for MIDI */
-
-    /* RTS low, ints disabled */
-    acia.mid_ctrl = div | csize | parity |
+       int baud = cflag & CBAUD;
+       int csize = ((cflag & CSIZE) == CS8) ? 0x10 : 0x00;
+       /* warning 7N1 isn't possible! (instead 7O2 is used...) */
+       int parity = (cflag & PARENB) ? ((cflag & PARODD) ? 0x0c : 0x08) : 0x04;
+       int div;
+
+       /* 4800 selects 7812.5, 115200 selects 500000, all other (incl. 9600 as
+        * default) the standard MIDI speed 31250. */
+       if (cflag & CBAUDEX)
+               baud += B38400;
+       if (baud == B4800)
+               div = ACIA_DIV64;       /* really 7812.5 bps */
+       else if (baud == B38400+2 /* 115200 */)
+               div = ACIA_DIV1;        /* really 500 kbps (does that work??) */
+       else
+               div = ACIA_DIV16;       /* 31250 bps, standard for MIDI */
+
+       /* RTS low, ints disabled */
+       acia.mid_ctrl = div | csize | parity |
                    ((atari_switches & ATARI_SWITCH_MIDI) ?
                     ACIA_RHTID : ACIA_RLTID);
 }
 
-void __init atari_debug_init(void)
+static int __init atari_debug_setup(char *arg)
 {
-    if (!strcmp( m68k_debug_device, "ser" )) {
-       /* defaults to ser2 for a Falcon and ser1 otherwise */
-       strcpy( m68k_debug_device, MACH_IS_FALCON ? "ser2" : "ser1" );
-
-    }
-
-    if (!strcmp( m68k_debug_device, "ser1" )) {
-       /* ST-MFP Modem1 serial port */
-       atari_init_mfp_port( B9600|CS8 );
-       atari_console_driver.write = atari_mfp_console_write;
-    }
-    else if (!strcmp( m68k_debug_device, "ser2" )) {
-       /* SCC Modem2 serial port */
-       atari_init_scc_port( B9600|CS8 );
-       atari_console_driver.write = atari_scc_console_write;
-    }
-    else if (!strcmp( m68k_debug_device, "midi" )) {
-       /* MIDI port */
-       atari_init_midi_port( B9600|CS8 );
-       atari_console_driver.write = atari_midi_console_write;
-    }
-    else if (!strcmp( m68k_debug_device, "par" )) {
-       /* parallel printer */
-       atari_turnoff_irq( IRQ_MFP_BUSY ); /* avoid ints */
-       sound_ym.rd_data_reg_sel = 7;  /* select mixer control */
-       sound_ym.wd_data = 0xff;       /* sound off, ports are output */
-       sound_ym.rd_data_reg_sel = 15; /* select port B */
-       sound_ym.wd_data = 0;          /* no char */
-       sound_ym.rd_data_reg_sel = 14; /* select port A */
-       sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x20; /* strobe H */
-       atari_console_driver.write = atari_par_console_write;
-    }
-    if (atari_console_driver.write)
-       register_console(&atari_console_driver);
+       if (!MACH_IS_ATARI)
+               return 0;
+
+       if (!strcmp(arg, "ser"))
+               /* defaults to ser2 for a Falcon and ser1 otherwise */
+               arg = MACH_IS_FALCON ? "ser2" : "ser1";
+
+       if (!strcmp(arg, "ser1")) {
+               /* ST-MFP Modem1 serial port */
+               atari_init_mfp_port(B9600|CS8);
+               atari_console_driver.write = atari_mfp_console_write;
+       } else if (!strcmp(arg, "ser2")) {
+               /* SCC Modem2 serial port */
+               atari_init_scc_port(B9600|CS8);
+               atari_console_driver.write = atari_scc_console_write;
+       } else if (!strcmp(arg, "midi")) {
+               /* MIDI port */
+               atari_init_midi_port(B9600|CS8);
+               atari_console_driver.write = atari_midi_console_write;
+       } else if (!strcmp(arg, "par")) {
+               /* parallel printer */
+               atari_turnoff_irq(IRQ_MFP_BUSY); /* avoid ints */
+               sound_ym.rd_data_reg_sel = 7;   /* select mixer control */
+               sound_ym.wd_data = 0xff;        /* sound off, ports are output */
+               sound_ym.rd_data_reg_sel = 15;  /* select port B */
+               sound_ym.wd_data = 0;           /* no char */
+               sound_ym.rd_data_reg_sel = 14;  /* select port A */
+               sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x20; /* strobe H */
+               atari_console_driver.write = atari_par_console_write;
+       }
+       if (atari_console_driver.write)
+               register_console(&atari_console_driver);
+
+       return 0;
 }
 
-/*
- * Local variables:
- *  c-indent-level: 4
- *  tab-width: 8
- * End:
- */
+early_param("debug", atari_debug_setup);
index 222ce42..e162ee6 100644 (file)
@@ -692,7 +692,7 @@ sys_call_table:
        .long sys_tgkill        /* 265 */
        .long sys_utimes
        .long sys_fadvise64_64
-       .long sys_mbind 
+       .long sys_mbind
        .long sys_get_mempolicy
        .long sys_set_mempolicy /* 270 */
        .long sys_mq_open
index 6739e87..05741f2 100644 (file)
@@ -3195,7 +3195,7 @@ func_start        serial_putc,%d0/%d1/%a0/%a1
        jbra    L(serial_putc_done)
 3:
 #endif
-       
+
 L(serial_putc_done):
 func_return    serial_putc
 
index 42b8fd0..6103193 100644 (file)
@@ -71,9 +71,6 @@ static struct mem_info m68k_ramdisk;
 
 static char m68k_command_line[CL_SIZE];
 
-char m68k_debug_device[6] = "";
-EXPORT_SYMBOL(m68k_debug_device);
-
 void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL;
 /* machine dependent irq functions */
 void (*mach_init_IRQ) (void) __initdata = NULL;
@@ -133,78 +130,78 @@ extern void config_hp300(void);
 extern void config_q40(void);
 extern void config_sun3x(void);
 
-extern void mac_debugging_short (int, short);
-extern void mac_debugging_long  (int, long);
-
 #define MASK_256K 0xfffc0000
 
 extern void paging_init(void);
 
 static void __init m68k_parse_bootinfo(const struct bi_record *record)
 {
-    while (record->tag != BI_LAST) {
-       int unknown = 0;
-       const unsigned long *data = record->data;
-       switch (record->tag) {
-           case BI_MACHTYPE:
-           case BI_CPUTYPE:
-           case BI_FPUTYPE:
-           case BI_MMUTYPE:
-               /* Already set up by head.S */
-               break;
-
-           case BI_MEMCHUNK:
-               if (m68k_num_memory < NUM_MEMINFO) {
-                   m68k_memory[m68k_num_memory].addr = data[0];
-                   m68k_memory[m68k_num_memory].size = data[1];
-                   m68k_num_memory++;
-               } else
-                   printk("m68k_parse_bootinfo: too many memory chunks\n");
-               break;
-
-           case BI_RAMDISK:
-               m68k_ramdisk.addr = data[0];
-               m68k_ramdisk.size = data[1];
-               break;
-
-           case BI_COMMAND_LINE:
-               strlcpy(m68k_command_line, (const char *)data, sizeof(m68k_command_line));
-               break;
-
-           default:
-               if (MACH_IS_AMIGA)
-                   unknown = amiga_parse_bootinfo(record);
-               else if (MACH_IS_ATARI)
-                   unknown = atari_parse_bootinfo(record);
-               else if (MACH_IS_MAC)
-                   unknown = mac_parse_bootinfo(record);
-               else if (MACH_IS_Q40)
-                   unknown = q40_parse_bootinfo(record);
-               else if (MACH_IS_BVME6000)
-                   unknown = bvme6000_parse_bootinfo(record);
-               else if (MACH_IS_MVME16x)
-                   unknown = mvme16x_parse_bootinfo(record);
-               else if (MACH_IS_MVME147)
-                   unknown = mvme147_parse_bootinfo(record);
-               else if (MACH_IS_HP300)
-                   unknown = hp300_parse_bootinfo(record);
-               else
-                   unknown = 1;
+       while (record->tag != BI_LAST) {
+               int unknown = 0;
+               const unsigned long *data = record->data;
+
+               switch (record->tag) {
+               case BI_MACHTYPE:
+               case BI_CPUTYPE:
+               case BI_FPUTYPE:
+               case BI_MMUTYPE:
+                       /* Already set up by head.S */
+                       break;
+
+               case BI_MEMCHUNK:
+                       if (m68k_num_memory < NUM_MEMINFO) {
+                               m68k_memory[m68k_num_memory].addr = data[0];
+                               m68k_memory[m68k_num_memory].size = data[1];
+                               m68k_num_memory++;
+                       } else
+                               printk("m68k_parse_bootinfo: too many memory chunks\n");
+                       break;
+
+               case BI_RAMDISK:
+                       m68k_ramdisk.addr = data[0];
+                       m68k_ramdisk.size = data[1];
+                       break;
+
+               case BI_COMMAND_LINE:
+                       strlcpy(m68k_command_line, (const char *)data,
+                               sizeof(m68k_command_line));
+                       break;
+
+               default:
+                       if (MACH_IS_AMIGA)
+                               unknown = amiga_parse_bootinfo(record);
+                       else if (MACH_IS_ATARI)
+                               unknown = atari_parse_bootinfo(record);
+                       else if (MACH_IS_MAC)
+                               unknown = mac_parse_bootinfo(record);
+                       else if (MACH_IS_Q40)
+                               unknown = q40_parse_bootinfo(record);
+                       else if (MACH_IS_BVME6000)
+                               unknown = bvme6000_parse_bootinfo(record);
+                       else if (MACH_IS_MVME16x)
+                               unknown = mvme16x_parse_bootinfo(record);
+                       else if (MACH_IS_MVME147)
+                               unknown = mvme147_parse_bootinfo(record);
+                       else if (MACH_IS_HP300)
+                               unknown = hp300_parse_bootinfo(record);
+                       else
+                               unknown = 1;
+               }
+               if (unknown)
+                       printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
+                              record->tag);
+               record = (struct bi_record *)((unsigned long)record +
+                                             record->size);
        }
-       if (unknown)
-           printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
-                  record->tag);
-       record = (struct bi_record *)((unsigned long)record+record->size);
-    }
 
-    m68k_realnum_memory = m68k_num_memory;
+       m68k_realnum_memory = m68k_num_memory;
 #ifdef CONFIG_SINGLE_MEMORY_CHUNK
-    if (m68k_num_memory > 1) {
-       printk("Ignoring last %i chunks of physical memory\n",
-              (m68k_num_memory - 1));
-       m68k_num_memory = 1;
-    }
-    m68k_memoffset = m68k_memory[0].addr-PAGE_OFFSET;
+       if (m68k_num_memory > 1) {
+               printk("Ignoring last %i chunks of physical memory\n",
+                      (m68k_num_memory - 1));
+               m68k_num_memory = 1;
+       }
+       m68k_memoffset = m68k_memory[0].addr-PAGE_OFFSET;
 #endif
 }
 
@@ -215,7 +212,6 @@ void __init setup_arch(char **cmdline_p)
        unsigned long endmem, startmem;
 #endif
        int i;
-       char *p, *q;
 
        /* The bootinfo is located right after the kernel bss */
        m68k_parse_bootinfo((const struct bi_record *)&_end);
@@ -234,7 +230,7 @@ void __init setup_arch(char **cmdline_p)
        /* clear the fpu if we have one */
        if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
                volatile int zero = 0;
-               asm __volatile__ ("frestore %0" : : "m" (zero));
+               asm volatile ("frestore %0" : : "m" (zero));
        }
 #endif
 
@@ -258,37 +254,7 @@ void __init setup_arch(char **cmdline_p)
        *cmdline_p = m68k_command_line;
        memcpy(boot_command_line, *cmdline_p, CL_SIZE);
 
-       /* Parse the command line for arch-specific options.
-        * For the m68k, this is currently only "debug=xxx" to enable printing
-        * certain kernel messages to some machine-specific device.
-        */
-       for( p = *cmdline_p; p && *p; ) {
-           i = 0;
-           if (!strncmp( p, "debug=", 6 )) {
-               strlcpy( m68k_debug_device, p+6, sizeof(m68k_debug_device) );
-               if ((q = strchr( m68k_debug_device, ' ' ))) *q = 0;
-               i = 1;
-           }
-#ifdef CONFIG_ATARI
-           /* This option must be parsed very early */
-           if (!strncmp( p, "switches=", 9 )) {
-               extern void atari_switches_setup( const char *, int );
-               atari_switches_setup( p+9, (q = strchr( p+9, ' ' )) ?
-                                          (q - (p+9)) : strlen(p+9) );
-               i = 1;
-           }
-#endif
-
-           if (i) {
-               /* option processed, delete it */
-               if ((q = strchr( p, ' ' )))
-                   strcpy( p, q+1 );
-               else
-                   *p = 0;
-           } else {
-               if ((p = strchr( p, ' ' ))) ++p;
-           }
-       }
+       parse_early_param();
 
 #ifdef CONFIG_DUMMY_CONSOLE
        conswitchp = &dummy_con;
@@ -296,62 +262,62 @@ void __init setup_arch(char **cmdline_p)
 
        switch (m68k_machtype) {
 #ifdef CONFIG_AMIGA
-           case MACH_AMIGA:
+       case MACH_AMIGA:
                config_amiga();
                break;
 #endif
 #ifdef CONFIG_ATARI
-           case MACH_ATARI:
+       case MACH_ATARI:
                config_atari();
                break;
 #endif
 #ifdef CONFIG_MAC
-           case MACH_MAC:
+       case MACH_MAC:
                config_mac();
                break;
 #endif
 #ifdef CONFIG_SUN3
-           case MACH_SUN3:
+       case MACH_SUN3:
                config_sun3();
                break;
 #endif
 #ifdef CONFIG_APOLLO
-           case MACH_APOLLO:
+       case MACH_APOLLO:
                config_apollo();
                break;
 #endif
 #ifdef CONFIG_MVME147
-           case MACH_MVME147:
+       case MACH_MVME147:
                config_mvme147();
                break;
 #endif
 #ifdef CONFIG_MVME16x
-           case MACH_MVME16x:
+       case MACH_MVME16x:
                config_mvme16x();
                break;
 #endif
 #ifdef CONFIG_BVME6000
-           case MACH_BVME6000:
+       case MACH_BVME6000:
                config_bvme6000();
                break;
 #endif
 #ifdef CONFIG_HP300
-           case MACH_HP300:
+       case MACH_HP300:
                config_hp300();
                break;
 #endif
 #ifdef CONFIG_Q40
-           case MACH_Q40:
-               config_q40();
+       case MACH_Q40:
+               config_q40();
                break;
 #endif
 #ifdef CONFIG_SUN3X
-           case MACH_SUN3X:
+       case MACH_SUN3X:
                config_sun3x();
                break;
 #endif
-           default:
-               panic ("No configuration setup");
+       default:
+               panic("No configuration setup");
        }
 
 #ifndef CONFIG_SUN3
@@ -380,7 +346,7 @@ void __init setup_arch(char **cmdline_p)
                reserve_bootmem(m68k_ramdisk.addr, m68k_ramdisk.size);
                initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
                initrd_end = initrd_start + m68k_ramdisk.size;
-               printk ("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
+               printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
        }
 #endif
 
@@ -402,18 +368,18 @@ void __init setup_arch(char **cmdline_p)
 #if defined(CONFIG_ISA) && defined(MULTI_ISA)
 #if defined(CONFIG_Q40)
        if (MACH_IS_Q40) {
-           isa_type = Q40_ISA;
-           isa_sex = 0;
+               isa_type = Q40_ISA;
+               isa_sex = 0;
        }
 #elif defined(CONFIG_GG2)
-       if (MACH_IS_AMIGA && AMIGAHW_PRESENT(GG2_ISA)){
-           isa_type = GG2_ISA;
-           isa_sex = 0;
+       if (MACH_IS_AMIGA && AMIGAHW_PRESENT(GG2_ISA)) {
+               isa_type = GG2_ISA;
+               isa_sex = 0;
        }
 #elif defined(CONFIG_AMIGA_PCMCIA)
-       if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)){
-           isa_type = AG_ISA;
-           isa_sex = 1;
+       if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)) {
+               isa_type = AG_ISA;
+               isa_sex = 1;
        }
 #endif
 #endif
@@ -421,66 +387,66 @@ void __init setup_arch(char **cmdline_p)
 
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
-    const char *cpu, *mmu, *fpu;
-    unsigned long clockfreq, clockfactor;
+       const char *cpu, *mmu, *fpu;
+       unsigned long clockfreq, clockfactor;
 
 #define LOOP_CYCLES_68020      (8)
 #define LOOP_CYCLES_68030      (8)
 #define LOOP_CYCLES_68040      (3)
 #define LOOP_CYCLES_68060      (1)
 
-    if (CPU_IS_020) {
-       cpu = "68020";
-       clockfactor = LOOP_CYCLES_68020;
-    } else if (CPU_IS_030) {
-       cpu = "68030";
-       clockfactor = LOOP_CYCLES_68030;
-    } else if (CPU_IS_040) {
-       cpu = "68040";
-       clockfactor = LOOP_CYCLES_68040;
-    } else if (CPU_IS_060) {
-       cpu = "68060";
-       clockfactor = LOOP_CYCLES_68060;
-    } else {
-       cpu = "680x0";
-       clockfactor = 0;
-    }
+       if (CPU_IS_020) {
+               cpu = "68020";
+               clockfactor = LOOP_CYCLES_68020;
+       } else if (CPU_IS_030) {
+               cpu = "68030";
+               clockfactor = LOOP_CYCLES_68030;
+       } else if (CPU_IS_040) {
+               cpu = "68040";
+               clockfactor = LOOP_CYCLES_68040;
+       } else if (CPU_IS_060) {
+               cpu = "68060";
+               clockfactor = LOOP_CYCLES_68060;
+       } else {
+               cpu = "680x0";
+               clockfactor = 0;
+       }
 
 #ifdef CONFIG_M68KFPU_EMU_ONLY
-    fpu="none(soft float)";
+       fpu = "none(soft float)";
 #else
-    if (m68k_fputype & FPU_68881)
-       fpu = "68881";
-    else if (m68k_fputype & FPU_68882)
-       fpu = "68882";
-    else if (m68k_fputype & FPU_68040)
-       fpu = "68040";
-    else if (m68k_fputype & FPU_68060)
-       fpu = "68060";
-    else if (m68k_fputype & FPU_SUNFPA)
-       fpu = "Sun FPA";
-    else
-       fpu = "none";
+       if (m68k_fputype & FPU_68881)
+               fpu = "68881";
+       else if (m68k_fputype & FPU_68882)
+               fpu = "68882";
+       else if (m68k_fputype & FPU_68040)
+               fpu = "68040";
+       else if (m68k_fputype & FPU_68060)
+               fpu = "68060";
+       else if (m68k_fputype & FPU_SUNFPA)
+               fpu = "Sun FPA";
+       else
+               fpu = "none";
 #endif
 
-    if (m68k_mmutype & MMU_68851)
-       mmu = "68851";
-    else if (m68k_mmutype & MMU_68030)
-       mmu = "68030";
-    else if (m68k_mmutype & MMU_68040)
-       mmu = "68040";
-    else if (m68k_mmutype & MMU_68060)
-       mmu = "68060";
-    else if (m68k_mmutype & MMU_SUN3)
-       mmu = "Sun-3";
-    else if (m68k_mmutype & MMU_APOLLO)
-       mmu = "Apollo";
-    else
-       mmu = "unknown";
-
-    clockfreq = loops_per_jiffy*HZ*clockfactor;
-
-    seq_printf(m, "CPU:\t\t%s\n"
+       if (m68k_mmutype & MMU_68851)
+               mmu = "68851";
+       else if (m68k_mmutype & MMU_68030)
+               mmu = "68030";
+       else if (m68k_mmutype & MMU_68040)
+               mmu = "68040";
+       else if (m68k_mmutype & MMU_68060)
+               mmu = "68060";
+       else if (m68k_mmutype & MMU_SUN3)
+               mmu = "Sun-3";
+       else if (m68k_mmutype & MMU_APOLLO)
+               mmu = "Apollo";
+       else
+               mmu = "unknown";
+
+       clockfreq = loops_per_jiffy * HZ * clockfactor;
+
+       seq_printf(m, "CPU:\t\t%s\n"
                   "MMU:\t\t%s\n"
                   "FPU:\t\t%s\n"
                   "Clocking:\t%lu.%1luMHz\n"
@@ -490,7 +456,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                   clockfreq/1000000,(clockfreq/100000)%10,
                   loops_per_jiffy/(500000/HZ),(loops_per_jiffy/(5000/HZ))%100,
                   loops_per_jiffy);
-    return 0;
+       return 0;
 }
 
 static void *c_start(struct seq_file *m, loff_t *pos)
@@ -506,44 +472,54 @@ static void c_stop(struct seq_file *m, void *v)
 {
 }
 struct seq_operations cpuinfo_op = {
-       .start =        c_start,
-       .next =         c_next,
-       .stop =         c_stop,
-       .show =         show_cpuinfo,
+       .start  = c_start,
+       .next   = c_next,
+       .stop   = c_stop,
+       .show   = show_cpuinfo,
 };
 
 int get_hardware_list(char *buffer)
 {
-    int len = 0;
-    char model[80];
-    unsigned long mem;
-    int i;
+       int len = 0;
+       char model[80];
+       unsigned long mem;
+       int i;
 
-    if (mach_get_model)
-       mach_get_model(model);
-    else
-       strcpy(model, "Unknown m68k");
+       if (mach_get_model)
+               mach_get_model(model);
+       else
+               strcpy(model, "Unknown m68k");
 
-    len += sprintf(buffer+len, "Model:\t\t%s\n", model);
-    for (mem = 0, i = 0; i < m68k_num_memory; i++)
-       mem += m68k_memory[i].size;
-    len += sprintf(buffer+len, "System Memory:\t%ldK\n", mem>>10);
+       len += sprintf(buffer + len, "Model:\t\t%s\n", model);
+       for (mem = 0, i = 0; i < m68k_num_memory; i++)
+               mem += m68k_memory[i].size;
+       len += sprintf(buffer + len, "System Memory:\t%ldK\n", mem >> 10);
 
-    if (mach_get_hardware_list)
-       len += mach_get_hardware_list(buffer+len);
+       if (mach_get_hardware_list)
+               len += mach_get_hardware_list(buffer + len);
 
-    return(len);
+       return len;
 }
 
 void check_bugs(void)
 {
 #ifndef CONFIG_M68KFPU_EMU
        if (m68k_fputype == 0) {
-               printk( KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
-                               "WHICH IS REQUIRED BY LINUX/M68K ***\n" );
-               printk( KERN_EMERG "Upgrade your hardware or join the FPU "
-                               "emulation project\n" );
-               panic( "no FPU" );
+               printk(KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
+                       "WHICH IS REQUIRED BY LINUX/M68K ***\n");
+               printk(KERN_EMERG "Upgrade your hardware or join the FPU "
+                       "emulation project\n");
+               panic("no FPU");
        }
 #endif /* !CONFIG_M68KFPU_EMU */
 }
+
+#ifdef CONFIG_ADB
+static int __init adb_probe_sync_enable (char *str) {
+       extern int __adb_probe_sync;
+       __adb_probe_sync = 1;
+       return 1;
+}
+
+__setup("adb_sync", adb_probe_sync_enable);
+#endif /* CONFIG_ADB */
index aed3be2..cf6bb51 100644 (file)
@@ -320,6 +320,9 @@ csum_partial_copy_from_user(const void __user *src, void *dst,
        return(sum);
 }
 
+EXPORT_SYMBOL(csum_partial_copy_from_user);
+
+
 /*
  * copy from kernel space while checksumming, otherwise like csum_partial
  */
index a1c7ec7..673a108 100644 (file)
@@ -22,7 +22,7 @@
 /* #define DEBUG_BABOON */
 /* #define DEBUG_IRQS */
 
-int baboon_present,baboon_active;
+int baboon_present;
 volatile struct baboon *baboon;
 
 irqreturn_t baboon_irq(int, void *);
@@ -45,7 +45,6 @@ void __init baboon_init(void)
 
        baboon = (struct baboon *) BABOON_BASE;
        baboon_present = 1;
-       baboon_active = 0;
 
        printk("Baboon detected at %p\n", baboon);
 }
@@ -66,26 +65,28 @@ void __init baboon_register_interrupts(void)
 
 irqreturn_t baboon_irq(int irq, void *dev_id)
 {
-       int irq_bit,i;
+       int irq_bit, irq_num;
        unsigned char events;
 
 #ifdef DEBUG_IRQS
-       printk("baboon_irq: mb_control %02X mb_ifr %02X mb_status %02X active %02X\n",
+       printk("baboon_irq: mb_control %02X mb_ifr %02X mb_status %02X\n",
                (uint) baboon->mb_control, (uint) baboon->mb_ifr,
-               (uint) baboon->mb_status,  baboon_active);
+               (uint) baboon->mb_status);
 #endif
 
        if (!(events = baboon->mb_ifr & 0x07))
                return IRQ_NONE;
 
-       for (i = 0, irq_bit = 1 ; i < 3 ; i++, irq_bit <<= 1) {
-               if (events & irq_bit/* & baboon_active*/) {
-                       baboon_active &= ~irq_bit;
-                       m68k_handle_int(IRQ_BABOON_0 + i);
-                       baboon_active |= irq_bit;
+       irq_num = IRQ_BABOON_0;
+       irq_bit = 1;
+       do {
+               if (events & irq_bit) {
                        baboon->mb_ifr &= ~irq_bit;
+                       m68k_handle_int(irq_num);
                }
-       }
+               irq_bit <<= 1;
+               irq_num++;
+       } while(events >= irq_bit);
 #if 0
        if (baboon->mb_ifr & 0x02) macide_ack_intr(NULL);
        /* for now we need to smash all interrupts */
@@ -95,21 +96,18 @@ irqreturn_t baboon_irq(int irq, void *dev_id)
 }
 
 void baboon_irq_enable(int irq) {
-       int irq_idx     = IRQ_IDX(irq);
-
 #ifdef DEBUG_IRQUSE
        printk("baboon_irq_enable(%d)\n", irq);
 #endif
-       baboon_active |= (1 << irq_idx);
+       /* FIXME: figure out how to mask and unmask baboon interrupt sources */
+       enable_irq(IRQ_NUBUS_C);
 }
 
 void baboon_irq_disable(int irq) {
-       int irq_idx     = IRQ_IDX(irq);
-
 #ifdef DEBUG_IRQUSE
        printk("baboon_irq_disable(%d)\n", irq);
 #endif
-       baboon_active &= ~(1 << irq_idx);
+       disable_irq(IRQ_NUBUS_C);
 }
 
 void baboon_irq_clear(int irq) {
index 562b38d..5fd4132 100644 (file)
@@ -59,15 +59,15 @@ extern struct mem_info m68k_ramdisk;
 
 extern char m68k_command_line[CL_SIZE];
 
-void *mac_env;         /* Loaded by the boot asm */
+void *mac_env;                                 /* Loaded by the boot asm */
 
 /* The phys. video addr. - might be bogus on some machines */
 unsigned long mac_orig_videoaddr;
 
 /* Mac specific timer functions */
-extern unsigned long mac_gettimeoffset (void);
-extern int mac_hwclk (int, struct rtc_time *);
-extern int mac_set_clock_mmss (unsigned long);
+extern unsigned long mac_gettimeoffset(void);
+extern int mac_hwclk(int, struct rtc_time *);
+extern int mac_set_clock_mmss(unsigned long);
 extern int show_mac_interrupts(struct seq_file *, void *);
 extern void iop_preinit(void);
 extern void iop_init(void);
@@ -82,10 +82,6 @@ extern void mac_mksound(unsigned int, unsigned int);
 
 extern void nubus_sweep_video(void);
 
-/* Mac specific debug functions (in debug.c) */
-extern void mac_debug_init(void);
-extern void mac_debugging_long(int, long);
-
 static void mac_get_model(char *str);
 
 static void mac_sched_init(irq_handler_t vector)
@@ -99,51 +95,52 @@ static void mac_sched_init(irq_handler_t vector)
 
 int __init mac_parse_bootinfo(const struct bi_record *record)
 {
-    int unknown = 0;
-    const u_long *data = record->data;
+       int unknown = 0;
+       const u_long *data = record->data;
 
-    switch (record->tag) {
+       switch (record->tag) {
        case BI_MAC_MODEL:
-           mac_bi_data.id = *data;
-           break;
+               mac_bi_data.id = *data;
+               break;
        case BI_MAC_VADDR:
-           mac_bi_data.videoaddr = *data;
-           break;
+               mac_bi_data.videoaddr = *data;
+               break;
        case BI_MAC_VDEPTH:
-           mac_bi_data.videodepth = *data;
-           break;
+               mac_bi_data.videodepth = *data;
+               break;
        case BI_MAC_VROW:
-           mac_bi_data.videorow = *data;
-           break;
+               mac_bi_data.videorow = *data;
+               break;
        case BI_MAC_VDIM:
-           mac_bi_data.dimensions = *data;
-           break;
+               mac_bi_data.dimensions = *data;
+               break;
        case BI_MAC_VLOGICAL:
-           mac_bi_data.videological = VIDEOMEMBASE + (*data & ~VIDEOMEMMASK);
-           mac_orig_videoaddr = *data;
-           break;
+               mac_bi_data.videological = VIDEOMEMBASE + (*data & ~VIDEOMEMMASK);
+               mac_orig_videoaddr = *data;
+               break;
        case BI_MAC_SCCBASE:
-           mac_bi_data.sccbase = *data;
-           break;
+               mac_bi_data.sccbase = *data;
+               break;
        case BI_MAC_BTIME:
-           mac_bi_data.boottime = *data;
-           break;
+               mac_bi_data.boottime = *data;
+               break;
        case BI_MAC_GMTBIAS:
-           mac_bi_data.gmtbias = *data;
-           break;
+               mac_bi_data.gmtbias = *data;
+               break;
        case BI_MAC_MEMSIZE:
-           mac_bi_data.memsize = *data;
-           break;
+               mac_bi_data.memsize = *data;
+               break;
        case BI_MAC_CPUID:
-           mac_bi_data.cpuid = *data;
-           break;
-        case BI_MAC_ROMBASE:
-           mac_bi_data.rombase = *data;
-           break;
+               mac_bi_data.cpuid = *data;
+               break;
+       case BI_MAC_ROMBASE:
+               mac_bi_data.rombase = *data;
+               break;
        default:
-           unknown = 1;
-    }
-    return(unknown);
+               unknown = 1;
+               break;
+       }
+       return unknown;
 }
 
 /*
@@ -155,6 +152,7 @@ int __init mac_parse_bootinfo(const struct bi_record *record)
 static void mac_cache_card_flush(int writeback)
 {
        unsigned long flags;
+
        local_irq_save(flags);
        via_flush_cache();
        local_irq_restore(flags);
@@ -162,28 +160,24 @@ static void mac_cache_card_flush(int writeback)
 
 void __init config_mac(void)
 {
-       if (!MACH_IS_MAC) {
-         printk(KERN_ERR "ERROR: no Mac, but config_mac() called!! \n");
-       }
+       if (!MACH_IS_MAC)
+               printk(KERN_ERR "ERROR: no Mac, but config_mac() called!! \n");
 
-       mach_sched_init      = mac_sched_init;
-       mach_init_IRQ        = mac_init_IRQ;
-       mach_get_model   = mac_get_model;
-       mach_gettimeoffset   = mac_gettimeoffset;
+       mach_sched_init = mac_sched_init;
+       mach_init_IRQ = mac_init_IRQ;
+       mach_get_model = mac_get_model;
+       mach_gettimeoffset = mac_gettimeoffset;
 #warning move to adb/via init
 #if 0
-       mach_hwclk           = mac_hwclk;
+       mach_hwclk = mac_hwclk;
 #endif
-       mach_set_clock_mmss      = mac_set_clock_mmss;
-       mach_reset           = mac_reset;
-       mach_halt            = mac_poweroff;
-       mach_power_off       = mac_poweroff;
+       mach_set_clock_mmss = mac_set_clock_mmss;
+       mach_reset = mac_reset;
+       mach_halt = mac_poweroff;
+       mach_power_off = mac_poweroff;
        mach_max_dma_address = 0xffffffff;
-#if 0
-       mach_debug_init  = mac_debug_init;
-#endif
 #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
-        mach_beep            = mac_mksound;
+       mach_beep = mac_mksound;
 #endif
 #ifdef CONFIG_HEARTBEAT
 #if 0
@@ -199,21 +193,22 @@ void __init config_mac(void)
        mac_identify();
        mac_report_hardware();
 
-       /* AFAIK only the IIci takes a cache card.  The IIfx has onboard
-          cache ... someone needs to figure out how to tell if it's on or
-          not. */
+       /*
+        * AFAIK only the IIci takes a cache card.  The IIfx has onboard
+        * cache ... someone needs to figure out how to tell if it's on or
+        * not.
+        */
 
        if (macintosh_config->ident == MAC_MODEL_IICI
-           || macintosh_config->ident == MAC_MODEL_IIFX) {
+           || macintosh_config->ident == MAC_MODEL_IIFX)
                mach_l2_flush = mac_cache_card_flush;
-       }
 
        /*
         * Check for machine specific fixups.
         */
 
 #ifdef OLD_NUBUS_CODE
-        nubus_sweep_video();
+       nubus_sweep_video();
 #endif
 }
 
@@ -233,8 +228,7 @@ void __init config_mac(void)
 struct mac_model *macintosh_config;
 EXPORT_SYMBOL(macintosh_config);
 
-static struct mac_model mac_data_table[]=
-{
+static struct mac_model mac_data_table[] = {
        /*
         *      We'll pretend to be a Macintosh II, that's pretty safe.
         */
@@ -784,12 +778,12 @@ void mac_identify(void)
        if (!model) {
                /* no bootinfo model id -> NetBSD booter was used! */
                /* XXX FIXME: breaks for model > 31 */
-               model=(mac_bi_data.cpuid>>2)&63;
-               printk (KERN_WARNING "No bootinfo model ID, using cpuid instead (hey, use Penguin!)\n");
+               model = (mac_bi_data.cpuid >> 2) & 63;
+               printk(KERN_WARNING "No bootinfo model ID, using cpuid instead (hey, use Penguin!)\n");
        }
 
        macintosh_config = mac_data_table;
-       for (m = macintosh_config ; m->ident != -1 ; m++) {
+       for (m = macintosh_config; m->ident != -1; m++) {
                if (m->ident == model) {
                        macintosh_config = m;
                        break;
@@ -801,27 +795,26 @@ void mac_identify(void)
        /* the serial ports set to "Faster" mode in MacOS. */
 
        iop_preinit();
-       mac_debug_init();
 
-       printk (KERN_INFO "Detected Macintosh model: %d \n", model);
+       printk(KERN_INFO "Detected Macintosh model: %d \n", model);
 
        /*
         * Report booter data:
         */
-       printk (KERN_DEBUG " Penguin bootinfo data:\n");
-       printk (KERN_DEBUG " Video: addr 0x%lx row 0x%lx depth %lx dimensions %ld x %ld\n",
+       printk(KERN_DEBUG " Penguin bootinfo data:\n");
+       printk(KERN_DEBUG " Video: addr 0x%lx row 0x%lx depth %lx dimensions %ld x %ld\n",
                mac_bi_data.videoaddr, mac_bi_data.videorow,
                mac_bi_data.videodepth, mac_bi_data.dimensions & 0xFFFF,
                mac_bi_data.dimensions >> 16);
-       printk (KERN_DEBUG " Videological 0x%lx phys. 0x%lx, SCC at 0x%lx \n",
+       printk(KERN_DEBUG " Videological 0x%lx phys. 0x%lx, SCC at 0x%lx \n",
                mac_bi_data.videological, mac_orig_videoaddr,
                mac_bi_data.sccbase);
-       printk (KERN_DEBUG " Boottime: 0x%lx GMTBias: 0x%lx \n",
+       printk(KERN_DEBUG " Boottime: 0x%lx GMTBias: 0x%lx \n",
                mac_bi_data.boottime, mac_bi_data.gmtbias);
-       printk (KERN_DEBUG " Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n",
+       printk(KERN_DEBUG " Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n",
                mac_bi_data.id, mac_bi_data.cpuid, mac_bi_data.memsize);
 #if 0
-       printk ("Ramdisk: addr 0x%lx size 0x%lx\n",
+       printk("Ramdisk: addr 0x%lx size 0x%lx\n",
                m68k_ramdisk.addr, m68k_ramdisk.size);
 #endif
 
@@ -830,22 +823,22 @@ void mac_identify(void)
         */
        switch (macintosh_config->scsi_type) {
        case MAC_SCSI_OLD:
-         MACHW_SET(MAC_SCSI_80);
-         break;
+               MACHW_SET(MAC_SCSI_80);
+               break;
        case MAC_SCSI_QUADRA:
        case MAC_SCSI_QUADRA2:
        case MAC_SCSI_QUADRA3:
-         MACHW_SET(MAC_SCSI_96);
-         if ((macintosh_config->ident == MAC_MODEL_Q900) ||
-             (macintosh_config->ident == MAC_MODEL_Q950))
-           MACHW_SET(MAC_SCSI_96_2);
-         break;
+               MACHW_SET(MAC_SCSI_96);
+               if ((macintosh_config->ident == MAC_MODEL_Q900) ||
+                   (macintosh_config->ident == MAC_MODEL_Q950))
+                       MACHW_SET(MAC_SCSI_96_2);
+               break;
        default:
-         printk(KERN_WARNING "config.c: wtf: unknown scsi, using 53c80\n");
-         MACHW_SET(MAC_SCSI_80);
-         break;
-
+               printk(KERN_WARNING "config.c: wtf: unknown scsi, using 53c80\n");
+               MACHW_SET(MAC_SCSI_80);
+               break;
        }
+
        iop_init();
        via_init();
        oss_init();
@@ -860,6 +853,6 @@ void mac_report_hardware(void)
 
 static void mac_get_model(char *str)
 {
-       strcpy(str,"Macintosh ");
+       strcpy(str, "Macintosh ");
        strcat(str, macintosh_config->name);
 }
index 4eeb09d..7a5bed5 100644 (file)
 #include <asm/machw.h>
 #include <asm/macints.h>
 
-extern char m68k_debug_device[];
-
-extern struct compat_bootinfo compat_boot_info;
-
 extern unsigned long mac_videobase;
 extern unsigned long mac_videodepth;
 extern unsigned long mac_rowbytes;
@@ -52,7 +48,7 @@ extern void mac_serial_print(const char *);
  */
 
 #ifdef DEBUG_SCREEN
-static int peng=0, line=0;
+static int peng, line;
 #endif
 
 void mac_debugging_short(int pos, short num)
@@ -74,15 +70,14 @@ void mac_debugging_short(int pos, short num)
        }
 
        /* calculate current offset */
-       pengoffset=(unsigned char *)(mac_videobase+(150+line*2)*mac_rowbytes)
-                   +80*peng;
+       pengoffset = (unsigned char *)mac_videobase +
+               (150+line*2) * mac_rowbytes) + 80 * peng;
 
-       pptr=pengoffset;
+       pptr = pengoffset;
 
-       for(i=0;i<8*sizeof(short);i++) /* # of bits */
-       {
+       for (i = 0; i < 8 * sizeof(short); i++) { /* # of bits */
                /*        value        mask for bit i, reverse order */
-               *pptr++ = (num & ( 1 << (8*sizeof(short)-i-1) ) ? 0xFF : 0x00);
+               *pptr++ = (num & (1 << (8*sizeof(short)-i-1)) ? 0xFF : 0x00);
        }
 
        peng++;
@@ -115,11 +110,10 @@ void mac_debugging_long(int pos, long addr)
        pengoffset=(unsigned char *)(mac_videobase+(150+line*2)*mac_rowbytes)
                    +80*peng;
 
-       pptr=pengoffset;
+       pptr = pengoffset;
 
-       for(i=0;i<8*sizeof(long);i++) /* # of bits */
-       {
-               *pptr++ = (addr & ( 1 << (8*sizeof(long)-i-1) ) ? 0xFF : 0x00);
+       for (i = 0; i < 8 * sizeof(long); i++) { /* # of bits */
+               *pptr++ = (addr & (1 << (8*sizeof(long)-i-1)) ? 0xFF : 0x00);
        }
 
        peng++;
@@ -136,16 +130,15 @@ void mac_debugging_long(int pos, long addr)
  * TODO: serial debug code
  */
 
-struct mac_SCC
- {
-  u_char cha_b_ctrl;
-  u_char char_dummy1;
-  u_char cha_a_ctrl;
-  u_char char_dummy2;
-  u_char cha_b_data;
-  u_char char_dummy3;
-  u_char cha_a_data;
- };
+struct mac_SCC {
+       u_char cha_b_ctrl;
+       u_char char_dummy1;
+       u_char cha_a_ctrl;
+       u_char char_dummy2;
+       u_char cha_b_data;
+       u_char char_dummy3;
+       u_char cha_a_data;
+};
 
 # define scc (*((volatile struct mac_SCC*)mac_bi_data.sccbase))
 
@@ -158,9 +151,9 @@ int mac_SCC_reset_done;
 static int scc_port = -1;
 
 static struct console mac_console_driver = {
-       .name =         "debug",
-       .flags =        CON_PRINTBUFFER,
-       .index =        -1,
+       .name   = "debug",
+       .flags  = CON_PRINTBUFFER,
+       .index  = -1,
 };
 
 /*
@@ -178,8 +171,8 @@ static struct console mac_console_driver = {
  * this driver if Mac.
  */
 
-void mac_debug_console_write (struct console *co, const char *str,
-                             unsigned int count)
+void mac_debug_console_write(struct console *co, const char *str,
+                            unsigned int count)
 {
        mac_serial_print(str);
 }
@@ -190,48 +183,50 @@ void mac_debug_console_write (struct console *co, const char *str,
 
 #define uSEC 1
 
-static inline void mac_sccb_out (char c)
+static inline void mac_sccb_out(char c)
 {
-    int i;
-    do {
-       for( i = uSEC; i > 0; --i )
+       int i;
+
+       do {
+               for (i = uSEC; i > 0; --i)
+                       barrier();
+       } while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
+       for (i = uSEC; i > 0; --i)
                barrier();
-    } while (!(scc.cha_b_ctrl & 0x04)); /* wait for tx buf empty */
-    for( i = uSEC; i > 0; --i )
-       barrier();
-    scc.cha_b_data = c;
+       scc.cha_b_data = c;
 }
 
-static inline void mac_scca_out (char c)
+static inline void mac_scca_out(char c)
 {
-    int i;
-    do {
-       for( i = uSEC; i > 0; --i )
+       int i;
+
+       do {
+               for (i = uSEC; i > 0; --i)
+                       barrier();
+       } while (!(scc.cha_a_ctrl & 0x04)); /* wait for tx buf empty */
+       for (i = uSEC; i > 0; --i)
                barrier();
-    } while (!(scc.cha_a_ctrl & 0x04)); /* wait for tx buf empty */
-    for( i = uSEC; i > 0; --i )
-       barrier();
-    scc.cha_a_data = c;
+       scc.cha_a_data = c;
 }
 
-void mac_sccb_console_write (struct console *co, const char *str,
-                             unsigned int count)
+void mac_sccb_console_write(struct console *co, const char *str,
+                           unsigned int count)
 {
-    while (count--) {
-       if (*str == '\n')
-           mac_sccb_out( '\r' );
-       mac_sccb_out( *str++ );
-    }
+       while (count--) {
+               if (*str == '\n')
+                       mac_sccb_out('\r');
+               mac_sccb_out(*str++);
+       }
 }
 
-void mac_scca_console_write (struct console *co, const char *str,
-                             unsigned int count)
+void mac_scca_console_write(struct console *co, const char *str,
+                           unsigned int count)
 {
-    while (count--) {
-       if (*str == '\n')
-           mac_scca_out( '\r' );
-       mac_scca_out( *str++ );
-    }
+       while (count--) {
+               if (*str == '\n')
+                       mac_scca_out('\r');
+               mac_scca_out(*str++);
+       }
 }
 
 
@@ -239,41 +234,41 @@ void mac_scca_console_write (struct console *co, const char *str,
  * SCC serial ports. They're used by the debugging interface, kgdb, and the
  * serial console code. */
 #define SCCB_WRITE(reg,val)                            \
-    do {                                               \
-       int i;                                          \
-       scc.cha_b_ctrl = (reg);                         \
-       for( i = uSEC; i > 0; --i )                     \
-               barrier();                              \
-       scc.cha_b_ctrl = (val);                         \
-       for( i = uSEC; i > 0; --i )                     \
-               barrier();                              \
-    } while(0)
+       do {                                            \
+               int i;                                  \
+               scc.cha_b_ctrl = (reg);                 \
+               for (i = uSEC; i > 0; --i)              \
+                       barrier();                      \
+               scc.cha_b_ctrl = (val);                 \
+               for (i = uSEC; i > 0; --i)              \
+                       barrier();                      \
+       } while(0)
 
 #define SCCA_WRITE(reg,val)                            \
-    do {                                               \
-       int i;                                          \
-       scc.cha_a_ctrl = (reg);                         \
-       for( i = uSEC; i > 0; --i )                     \
-               barrier();                              \
-       scc.cha_a_ctrl = (val);                         \
-       for( i = uSEC; i > 0; --i )                     \
-               barrier();                              \
-    } while(0)
+       do {                                            \
+               int i;                                  \
+               scc.cha_a_ctrl = (reg);                 \
+               for (i = uSEC; i > 0; --i)              \
+                       barrier();                      \
+               scc.cha_a_ctrl = (val);                 \
+               for (i = uSEC; i > 0; --i)              \
+                       barrier();                      \
+       } while(0)
 
 /* loops_per_jiffy isn't initialized yet, so we can't use udelay(). This does a
  * delay of ~ 60us. */
 /* Mac: loops_per_jiffy min. 19000 ^= .5 us; MFPDELAY was 0.6 us*/
-#define LONG_DELAY()                           \
-    do {                                       \
-       int i;                                  \
-       for( i = 60*uSEC; i > 0; --i )          \
-           barrier();                          \
-    } while(0)
+#define LONG_DELAY()                                   \
+       do {                                            \
+               int i;                                  \
+               for (i = 60*uSEC; i > 0; --i)           \
+                   barrier();                          \
+       } while(0)
 
 #ifndef CONFIG_SERIAL_CONSOLE
-static void __init mac_init_scc_port( int cflag, int port )
+static void __init mac_init_scc_port(int cflag, int port)
 #else
-void mac_init_scc_port( int cflag, int port )
+void mac_init_scc_port(int cflag, int port)
 #endif
 {
        extern int mac_SCC_reset_done;
@@ -292,106 +287,102 @@ void mac_init_scc_port( int cflag, int port )
                /* reg12 (BRG low) */
                { 94, 62, 46, 22, 10, 4, 1, 0, 0 };
 
-    int baud = cflag & CBAUD;
-    int clksrc, clkmode, div, reg3, reg5;
-
-    if (cflag & CBAUDEX)
-       baud += B38400;
-    if (baud < B1200 || baud > B38400+2)
-       baud = B9600; /* use default 9600bps for non-implemented rates */
-    baud -= B1200; /* tables starts at 1200bps */
-
-    clksrc  = clksrc_table[baud];
-    clkmode = clkmode_table[baud];
-    div     = div_table[baud];
-
-    reg3 = (((cflag & CSIZE) == CS8) ? 0xc0 : 0x40);
-    reg5 = (((cflag & CSIZE) == CS8) ? 0x60 : 0x20) | 0x82 /* assert DTR/RTS */;
-
-    if (port == 1) {
-           (void)scc.cha_b_ctrl;       /* reset reg pointer */
-           SCCB_WRITE( 9, 0xc0 );      /* reset */
-           LONG_DELAY();               /* extra delay after WR9 access */
-           SCCB_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
+       int baud = cflag & CBAUD;
+       int clksrc, clkmode, div, reg3, reg5;
+
+       if (cflag & CBAUDEX)
+               baud += B38400;
+       if (baud < B1200 || baud > B38400+2)
+               baud = B9600; /* use default 9600bps for non-implemented rates */
+       baud -= B1200; /* tables starts at 1200bps */
+
+       clksrc  = clksrc_table[baud];
+       clkmode = clkmode_table[baud];
+       div     = div_table[baud];
+
+       reg3 = (((cflag & CSIZE) == CS8) ? 0xc0 : 0x40);
+       reg5 = (((cflag & CSIZE) == CS8) ? 0x60 : 0x20) | 0x82 /* assert DTR/RTS */;
+
+       if (port == 1) {
+               (void)scc.cha_b_ctrl;   /* reset reg pointer */
+               SCCB_WRITE(9, 0xc0);    /* reset */
+               LONG_DELAY();           /* extra delay after WR9 access */
+               SCCB_WRITE(4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
+                          0x04 /* 1 stopbit */ |
+                          clkmode);
+               SCCB_WRITE(3, reg3);
+               SCCB_WRITE(5, reg5);
+               SCCB_WRITE(9, 0);       /* no interrupts */
+               LONG_DELAY();           /* extra delay after WR9 access */
+               SCCB_WRITE(10, 0);      /* NRZ mode */
+               SCCB_WRITE(11, clksrc); /* main clock source */
+               SCCB_WRITE(12, div);    /* BRG value */
+               SCCB_WRITE(13, 0);      /* BRG high byte */
+               SCCB_WRITE(14, 1);
+               SCCB_WRITE(3, reg3 | 1);
+               SCCB_WRITE(5, reg5 | 8);
+       } else if (port == 0) {
+               (void)scc.cha_a_ctrl;   /* reset reg pointer */
+               SCCA_WRITE(9, 0xc0);    /* reset */
+               LONG_DELAY();           /* extra delay after WR9 access */
+               SCCA_WRITE(4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
                          0x04 /* 1 stopbit */ |
-                         clkmode );
-           SCCB_WRITE( 3, reg3 );
-           SCCB_WRITE( 5, reg5 );
-           SCCB_WRITE( 9, 0 );         /* no interrupts */
-           LONG_DELAY();               /* extra delay after WR9 access */
-           SCCB_WRITE( 10, 0 );        /* NRZ mode */
-           SCCB_WRITE( 11, clksrc );   /* main clock source */
-           SCCB_WRITE( 12, div );      /* BRG value */
-           SCCB_WRITE( 13, 0 );                /* BRG high byte */
-           SCCB_WRITE( 14, 1 );
-           SCCB_WRITE( 3, reg3 | 1 );
-           SCCB_WRITE( 5, reg5 | 8 );
-    } else if (port == 0) {
-           (void)scc.cha_a_ctrl;       /* reset reg pointer */
-           SCCA_WRITE( 9, 0xc0 );      /* reset */
-           LONG_DELAY();               /* extra delay after WR9 access */
-           SCCA_WRITE( 4, (cflag & PARENB) ? ((cflag & PARODD) ? 0x01 : 0x03) : 0 |
-                         0x04 /* 1 stopbit */ |
-                         clkmode );
-           SCCA_WRITE( 3, reg3 );
-           SCCA_WRITE( 5, reg5 );
-           SCCA_WRITE( 9, 0 );         /* no interrupts */
-           LONG_DELAY();               /* extra delay after WR9 access */
-           SCCA_WRITE( 10, 0 );        /* NRZ mode */
-           SCCA_WRITE( 11, clksrc );   /* main clock source */
-           SCCA_WRITE( 12, div );      /* BRG value */
-           SCCA_WRITE( 13, 0 );                /* BRG high byte */
-           SCCA_WRITE( 14, 1 );
-           SCCA_WRITE( 3, reg3 | 1 );
-           SCCA_WRITE( 5, reg5 | 8 );
-    }
-
-    mac_SCC_reset_done = 1;
-    mac_SCC_init_done = 1;
+                         clkmode);
+               SCCA_WRITE(3, reg3);
+               SCCA_WRITE(5, reg5);
+               SCCA_WRITE(9, 0);       /* no interrupts */
+               LONG_DELAY();           /* extra delay after WR9 access */
+               SCCA_WRITE(10, 0);      /* NRZ mode */
+               SCCA_WRITE(11, clksrc); /* main clock source */
+               SCCA_WRITE(12, div);    /* BRG value */
+               SCCA_WRITE(13, 0);      /* BRG high byte */
+               SCCA_WRITE(14, 1);
+               SCCA_WRITE(3, reg3 | 1);
+               SCCA_WRITE(5, reg5 | 8);
+       }
+
+       mac_SCC_reset_done = 1;
+       mac_SCC_init_done = 1;
 }
 #endif /* DEBUG_SERIAL */
 
-void mac_init_scca_port( int cflag )
+void mac_init_scca_port(int cflag)
 {
        mac_init_scc_port(cflag, 0);
 }
 
-void mac_init_sccb_port( int cflag )
+void mac_init_sccb_port(int cflag)
 {
        mac_init_scc_port(cflag, 1);
 }
 
-void __init mac_debug_init(void)
+static int __init mac_debug_setup(char *arg)
 {
+       if (!MACH_IS_MAC)
+               return 0;
+
 #ifdef DEBUG_SERIAL
-    if (   !strcmp( m68k_debug_device, "ser"  )
-        || !strcmp( m68k_debug_device, "ser1" )) {
-       /* Mac modem port */
-       mac_init_scc_port( B9600|CS8, 0 );
-       mac_console_driver.write = mac_scca_console_write;
-       scc_port = 0;
-    }
-    else if (!strcmp( m68k_debug_device, "ser2" )) {
-       /* Mac printer port */
-       mac_init_scc_port( B9600|CS8, 1 );
-       mac_console_driver.write = mac_sccb_console_write;
-       scc_port = 1;
-    }
+       if (!strcmp(arg, "ser") || !strcmp(arg, "ser1")) {
+               /* Mac modem port */
+               mac_init_scc_port(B9600|CS8, 0);
+               mac_console_driver.write = mac_scca_console_write;
+               scc_port = 0;
+       } else if (!strcmp(arg, "ser2")) {
+               /* Mac printer port */
+               mac_init_scc_port(B9600|CS8, 1);
+               mac_console_driver.write = mac_sccb_console_write;
+               scc_port = 1;
+       }
 #endif
 #ifdef DEBUG_HEADS
-    if (   !strcmp( m68k_debug_device, "scn"  )
-        || !strcmp( m68k_debug_device, "con" )) {
-       /* display, using head.S console routines */
-       mac_console_driver.write = mac_debug_console_write;
-    }
+       if (!strcmp(arg, "scn") || !strcmp(arg, "con")) {
+               /* display, using head.S console routines */
+               mac_console_driver.write = mac_debug_console_write;
+       }
 #endif
-    if (mac_console_driver.write)
-       register_console(&mac_console_driver);
+       if (mac_console_driver.write)
+               register_console(&mac_console_driver);
+       return 0;
 }
 
-/*
- * Local variables:
- *  c-indent-level: 4
- *  tab-width: 8
- * End:
- */
+early_param("debug", mac_debug_setup);
index 6369081..d7be169 100644 (file)
@@ -109,13 +109,11 @@ irqreturn_t oss_irq(int irq, void *dev_id)
        /* FIXME: how do you clear a pending IRQ?    */
 
        if (events & OSS_IP_SOUND) {
-               /* FIXME: call sound handler */
                oss->irq_pending &= ~OSS_IP_SOUND;
+               /* FIXME: call sound handler */
        } else if (events & OSS_IP_SCSI) {
-               oss->irq_level[OSS_SCSI] = OSS_IRQLEV_DISABLED;
-               m68k_handle_int(IRQ_MAC_SCSI);
                oss->irq_pending &= ~OSS_IP_SCSI;
-               oss->irq_level[OSS_SCSI] = OSS_IRQLEV_SCSI;
+               m68k_handle_int(IRQ_MAC_SCSI);
        } else {
                /* FIXME: error check here? */
        }
@@ -143,14 +141,16 @@ irqreturn_t oss_nubus_irq(int irq, void *dev_id)
 #endif
        /* There are only six slots on the OSS, not seven */
 
-       for (i = 0, irq_bit = 1 ; i < 6 ; i++, irq_bit <<= 1) {
+       i = 6;
+       irq_bit = 0x40;
+       do {
+               --i;
+               irq_bit >>= 1;
                if (events & irq_bit) {
-                       oss->irq_level[i] = OSS_IRQLEV_DISABLED;
-                       m68k_handle_int(NUBUS_SOURCE_BASE + i);
                        oss->irq_pending &= ~irq_bit;
-                       oss->irq_level[i] = OSS_IRQLEV_NUBUS;
+                       m68k_handle_int(NUBUS_SOURCE_BASE + i);
                }
-       }
+       } while(events & (irq_bit - 1));
        return IRQ_HANDLED;
 }
 
index 15378a5..d66f723 100644 (file)
@@ -131,11 +131,8 @@ irqreturn_t psc_irq(int irq, void *dev_id)
 {
        int pIFR        = pIFRbase + ((int) dev_id);
        int pIER        = pIERbase + ((int) dev_id);
-       int base_irq;
-       int irq_bit,i;
-       unsigned char events;
-
-       base_irq = irq << 3;
+       int irq_num;
+       unsigned char irq_bit, events;
 
 #ifdef DEBUG_IRQS
        printk("psc_irq: irq %d pIFR = 0x%02X pIER = 0x%02X\n",
@@ -146,14 +143,16 @@ irqreturn_t psc_irq(int irq, void *dev_id)
        if (!events)
                return IRQ_NONE;
 
-       for (i = 0, irq_bit = 1 ; i < 4 ; i++, irq_bit <<= 1) {
-               if (events & irq_bit) {
-                       psc_write_byte(pIER, irq_bit);
-                       m68k_handle_int(base_irq + i);
+       irq_num = irq << 3;
+       irq_bit = 1;
+       do {
+               if (events & irq_bit) {
                        psc_write_byte(pIFR, irq_bit);
-                       psc_write_byte(pIER, irq_bit | 0x80);
+                       m68k_handle_int(irq_num);
                }
-       }
+               irq_num++;
+               irq_bit <<= 1;
+       } while (events >= irq_bit);
        return IRQ_HANDLED;
 }
 
index e27735b..d5cac72 100644 (file)
  * for info.  A full-text web search on 6522 AND VIA will probably also
  * net some usefulness. <cananian@alumni.princeton.edu> 20apr1999
  *
+ * Additional data is here (the SY6522 was used in the Mac II etc):
+ *     http://www.6502.org/documents/datasheets/synertek/synertek_sy6522.pdf
+ *     http://www.6502.org/documents/datasheets/synertek/synertek_sy6522_programming_reference.pdf
+ *
  * PRAM/RTC access algorithms are from the NetBSD RTC toolkit version 1.08b
  * by Erik Vogan and adapted to Linux by Joshua M. Thompson (funaho@jurai.org)
  *
@@ -37,7 +41,7 @@ volatile __u8 *via1, *via2;
 /* See note in mac_via.h about how this is possibly not useful */
 volatile long *via_memory_bogon=(long *)&via_memory_bogon;
 #endif
-int  rbv_present,via_alt_mapping;
+int rbv_present, via_alt_mapping;
 __u8 rbv_clear;
 
 /*
@@ -60,7 +64,19 @@ static int gIER,gIFR,gBufA,gBufB;
 #define MAC_CLOCK_LOW          (MAC_CLOCK_TICK&0xFF)
 #define MAC_CLOCK_HIGH         (MAC_CLOCK_TICK>>8)
 
-static int  nubus_active;
+/* To disable a NuBus slot on Quadras we make the slot IRQ lines outputs, set
+ * high. On RBV we just use the slot interrupt enable register. On Macs with
+ * genuine VIA chips we must use nubus_disabled to keep track of disabled slot
+ * interrupts. When any slot IRQ is disabled we mask the (edge triggered) CA1
+ * or "SLOTS" interrupt. When no slot is disabled, we unmask the CA1 interrupt.
+ * So, on genuine VIAs, having more than one NuBus IRQ can mean trouble,
+ * because closing one of those drivers can mask all of the NuBus interrupts.
+ * Also, since we can't mask the unregistered slot IRQs on genuine VIAs, it's
+ * possible to get interrupts from cards that MacOS or the ROM has configured
+ * but we have not. FWIW, "Designing Cards and Drivers for Macintosh II and
+ * Macintosh SE", page 9-8, says, a slot IRQ with no driver would crash MacOS.
+ */
+static u8 nubus_disabled;
 
 void via_debug_dump(void);
 irqreturn_t via1_irq(int, void *);
@@ -138,11 +154,11 @@ void __init via_init(void)
 
        printk(KERN_INFO "VIA2 at %p is ", via2);
        if (rbv_present) {
-               printk(KERN_INFO "an RBV\n");
+               printk("an RBV\n");
        } else if (oss_present) {
-               printk(KERN_INFO "an OSS\n");
+               printk("an OSS\n");
        } else {
-               printk(KERN_INFO "a 6522 or clone\n");
+               printk("a 6522 or clone\n");
        }
 
 #ifdef DEBUG_VIA
@@ -163,6 +179,7 @@ void __init via_init(void)
        via1[vT2CL] = 0;
        via1[vT2CH] = 0;
        via1[vACR] &= 0x3F;
+       via1[vACR] &= ~0x03; /* disable port A & B latches */
 
        /*
         * SE/30: disable video IRQ
@@ -193,8 +210,14 @@ void __init via_init(void)
        /* that the IIfx emulates this alternate mapping using the OSS. */
 
        switch(macintosh_config->ident) {
+               case MAC_MODEL_P475:
+               case MAC_MODEL_P475F:
+               case MAC_MODEL_P575:
+               case MAC_MODEL_Q605:
+               case MAC_MODEL_Q605_ACC:
                case MAC_MODEL_C610:
                case MAC_MODEL_Q610:
+               case MAC_MODEL_Q630:
                case MAC_MODEL_C650:
                case MAC_MODEL_Q650:
                case MAC_MODEL_Q700:
@@ -228,6 +251,22 @@ void __init via_init(void)
                via2[vT2CL] = 0;
                via2[vT2CH] = 0;
                via2[vACR] &= 0x3F;
+               via2[vACR] &= ~0x03; /* disable port A & B latches */
+       }
+
+       /*
+        * Set vPCR for SCSI interrupts (but not on RBV)
+        */
+       if (!rbv_present) {
+               if (macintosh_config->scsi_type == MAC_SCSI_OLD) {
+                       /* CB2 (IRQ) indep. input, positive edge */
+                       /* CA2 (DRQ) indep. input, positive edge */
+                       via2[vPCR] = 0x66;
+               } else {
+                       /* CB2 (IRQ) indep. input, negative edge */
+                       /* CA2 (DRQ) indep. input, negative edge */
+                       via2[vPCR] = 0x22;
+               }
        }
 }
 
@@ -356,78 +395,75 @@ int via_get_cache_disable(void)
 
 void __init via_nubus_init(void)
 {
-       /* don't set nubus_active = 0 here, it kills the Baboon */
-       /* interrupt that we've already registered.             */
-
        /* unlock nubus transactions */
 
-       if (!rbv_present) {
+       if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
+           (macintosh_config->adb_type != MAC_ADB_PB2)) {
                /* set the line to be an output on non-RBV machines */
-               if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
-                  (macintosh_config->adb_type != MAC_ADB_PB2)) {
+               if (!rbv_present)
                        via2[vDirB] |= 0x02;
-               }
-       }
 
-       /* this seems to be an ADB bit on PMU machines */
-       /* according to MkLinux.  -- jmt               */
-
-       if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
-           (macintosh_config->adb_type != MAC_ADB_PB2)) {
+               /* this seems to be an ADB bit on PMU machines */
+               /* according to MkLinux.  -- jmt               */
                via2[gBufB] |= 0x02;
        }
 
-       /* disable nubus slot interrupts. */
-       if (rbv_present) {
+       /* Disable all the slot interrupts (where possible). */
+
+       switch (macintosh_config->via_type) {
+       case MAC_VIA_II:
+               /* Just make the port A lines inputs. */
+               switch(macintosh_config->ident) {
+               case MAC_MODEL_II:
+               case MAC_MODEL_IIX:
+               case MAC_MODEL_IICX:
+               case MAC_MODEL_SE30:
+                       /* The top two bits are RAM size outputs. */
+                       via2[vDirA] &= 0xC0;
+                       break;
+               default:
+                       via2[vDirA] &= 0x80;
+               }
+               break;
+       case MAC_VIA_IIci:
+               /* RBV. Disable all the slot interrupts. SIER works like IER. */
                via2[rSIER] = 0x7F;
-               via2[rSIER] = nubus_active | 0x80;
-       } else {
-               /* These are ADB bits on PMU */
+               break;
+       case MAC_VIA_QUADRA:
+               /* Disable the inactive slot interrupts by making those lines outputs. */
                if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
-                  (macintosh_config->adb_type != MAC_ADB_PB2)) {
-                       switch(macintosh_config->ident)
-                       {
-                               case MAC_MODEL_II:
-                               case MAC_MODEL_IIX:
-                               case MAC_MODEL_IICX:
-                               case MAC_MODEL_SE30:
-                                       via2[vBufA] |= 0x3F;
-                                       via2[vDirA] = ~nubus_active | 0xc0;
-                                       break;
-                               default:
-                                       via2[vBufA] = 0xFF;
-                                       via2[vDirA] = ~nubus_active;
-                       }
+                   (macintosh_config->adb_type != MAC_ADB_PB2)) {
+                       via2[vBufA] |= 0x7F;
+                       via2[vDirA] |= 0x7F;
                }
+               break;
        }
 }
 
 /*
  * The generic VIA interrupt routines (shamelessly stolen from Alan Cox's
  * via6522.c :-), disable/pending masks added.
- *
- * The new interrupt architecture in macints.c takes care of a lot of the
- * gruntwork for us, including tallying the interrupts and calling the
- * handlers on the linked list. All we need to do here is basically generate
- * the machspec interrupt number after clearing the interrupt.
  */
 
 irqreturn_t via1_irq(int irq, void *dev_id)
 {
-       int irq_bit, i;
-       unsigned char events, mask;
+       int irq_num;
+       unsigned char irq_bit, events;
 
-       mask = via1[vIER] & 0x7F;
-       if (!(events = via1[vIFR] & mask))
+       events = via1[vIFR] & via1[vIER] & 0x7F;
+       if (!events)
                return IRQ_NONE;
 
-       for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
+       irq_num = VIA1_SOURCE_BASE;
+       irq_bit = 1;
+       do {
                if (events & irq_bit) {
-                       via1[vIER] = irq_bit;
-                       m68k_handle_int(VIA1_SOURCE_BASE + i);
                        via1[vIFR] = irq_bit;
-                       via1[vIER] = irq_bit | 0x80;
+                       m68k_handle_int(irq_num);
                }
+               ++irq_num;
+               irq_bit <<= 1;
+       } while (events >= irq_bit);
 
 #if 0 /* freakin' pmu is doing weird stuff */
        if (!oss_present) {
@@ -448,20 +484,23 @@ irqreturn_t via1_irq(int irq, void *dev_id)
 
 irqreturn_t via2_irq(int irq, void *dev_id)
 {
-       int irq_bit, i;
-       unsigned char events, mask;
+       int irq_num;
+       unsigned char irq_bit, events;
 
-       mask = via2[gIER] & 0x7F;
-       if (!(events = via2[gIFR] & mask))
+       events = via2[gIFR] & via2[gIER] & 0x7F;
+       if (!events)
                return IRQ_NONE;
 
-       for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
+       irq_num = VIA2_SOURCE_BASE;
+       irq_bit = 1;
+       do {
                if (events & irq_bit) {
-                       via2[gIER] = irq_bit;
                        via2[gIFR] = irq_bit | rbv_clear;
-                       m68k_handle_int(VIA2_SOURCE_BASE + i);
-                       via2[gIER] = irq_bit | 0x80;
+                       m68k_handle_int(irq_num);
                }
+               ++irq_num;
+               irq_bit <<= 1;
+       } while (events >= irq_bit);
        return IRQ_HANDLED;
 }
 
@@ -472,71 +511,75 @@ irqreturn_t via2_irq(int irq, void *dev_id)
 
 irqreturn_t via_nubus_irq(int irq, void *dev_id)
 {
-       int irq_bit, i;
-       unsigned char events;
-
-       if (!(events = ~via2[gBufA] & nubus_active))
+       int slot_irq;
+       unsigned char slot_bit, events;
+
+       events = ~via2[gBufA] & 0x7F;
+       if (rbv_present)
+               events &= via2[rSIER];
+       else
+               events &= ~via2[vDirA];
+       if (!events)
                return IRQ_NONE;
 
-       for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) {
-               if (events & irq_bit) {
-                       via_irq_disable(NUBUS_SOURCE_BASE + i);
-                       m68k_handle_int(NUBUS_SOURCE_BASE + i);
-                       via_irq_enable(NUBUS_SOURCE_BASE + i);
-               }
-       }
+       do {
+               slot_irq = IRQ_NUBUS_F;
+               slot_bit = 0x40;
+               do {
+                       if (events & slot_bit) {
+                               events &= ~slot_bit;
+                               m68k_handle_int(slot_irq);
+                       }
+                       --slot_irq;
+                       slot_bit >>= 1;
+               } while (events);
+
+               /* clear the CA1 interrupt and make certain there's no more. */
+               via2[gIFR] = 0x02 | rbv_clear;
+               events = ~via2[gBufA] & 0x7F;
+               if (rbv_present)
+                       events &= via2[rSIER];
+               else
+                       events &= ~via2[vDirA];
+       } while (events);
        return IRQ_HANDLED;
 }
 
 void via_irq_enable(int irq) {
        int irq_src     = IRQ_SRC(irq);
        int irq_idx     = IRQ_IDX(irq);
-       int irq_bit     = 1 << irq_idx;
 
 #ifdef DEBUG_IRQUSE
        printk(KERN_DEBUG "via_irq_enable(%d)\n", irq);
 #endif
 
        if (irq_src == 1) {
-               via1[vIER] = irq_bit | 0x80;
+               via1[vIER] = IER_SET_BIT(irq_idx);
        } else if (irq_src == 2) {
-               /*
-                * Set vPCR for SCSI interrupts (but not on RBV)
-                */
-               if ((irq_idx == 0) && !rbv_present) {
-                       if (macintosh_config->scsi_type == MAC_SCSI_OLD) {
-                               /* CB2 (IRQ) indep. input, positive edge */
-                               /* CA2 (DRQ) indep. input, positive edge */
-                               via2[vPCR] = 0x66;
-                       } else {
-                               /* CB2 (IRQ) indep. input, negative edge */
-                               /* CA2 (DRQ) indep. input, negative edge */
-                               via2[vPCR] = 0x22;
-                       }
-               }
-               via2[gIER] = irq_bit | 0x80;
+               if (irq != IRQ_MAC_NUBUS || nubus_disabled == 0)
+                       via2[gIER] = IER_SET_BIT(irq_idx);
        } else if (irq_src == 7) {
-               nubus_active |= irq_bit;
-               if (rbv_present) {
-                       /* enable the slot interrupt. SIER works like IER. */
+               switch (macintosh_config->via_type) {
+               case MAC_VIA_II:
+                       nubus_disabled &= ~(1 << irq_idx);
+                       /* Enable the CA1 interrupt when no slot is disabled. */
+                       if (!nubus_disabled)
+                               via2[gIER] = IER_SET_BIT(1);
+                       break;
+               case MAC_VIA_IIci:
+                       /* On RBV, enable the slot interrupt.
+                        * SIER works like IER.
+                        */
                        via2[rSIER] = IER_SET_BIT(irq_idx);
-               } else {
-                       /* Make sure the bit is an input, to enable the irq */
-                       /* But not on PowerBooks, that's ADB... */
+                       break;
+               case MAC_VIA_QUADRA:
+                       /* Make the port A line an input to enable the slot irq.
+                        * But not on PowerBooks, that's ADB.
+                        */
                        if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
-                          (macintosh_config->adb_type != MAC_ADB_PB2)) {
-                               switch(macintosh_config->ident)
-                               {
-                                       case MAC_MODEL_II:
-                                       case MAC_MODEL_IIX:
-                                       case MAC_MODEL_IICX:
-                                       case MAC_MODEL_SE30:
-                                               via2[vDirA] &= (~irq_bit | 0xc0);
-                                               break;
-                                       default:
-                                               via2[vDirA] &= ~irq_bit;
-                               }
-                       }
+                           (macintosh_config->adb_type != MAC_ADB_PB2))
+                               via2[vDirA] &= ~(1 << irq_idx);
+                       break;
                }
        }
 }
@@ -544,29 +587,31 @@ void via_irq_enable(int irq) {
 void via_irq_disable(int irq) {
        int irq_src     = IRQ_SRC(irq);
        int irq_idx     = IRQ_IDX(irq);
-       int irq_bit     = 1 << irq_idx;
 
 #ifdef DEBUG_IRQUSE
        printk(KERN_DEBUG "via_irq_disable(%d)\n", irq);
 #endif
 
        if (irq_src == 1) {
-               via1[vIER] = irq_bit;
+               via1[vIER] = IER_CLR_BIT(irq_idx);
        } else if (irq_src == 2) {
-               via2[gIER] = irq_bit;
+               via2[gIER] = IER_CLR_BIT(irq_idx);
        } else if (irq_src == 7) {
-               if (rbv_present) {
-                       /* disable the slot interrupt.  SIER works like IER. */
+               switch (macintosh_config->via_type) {
+               case MAC_VIA_II:
+                       nubus_disabled |= 1 << irq_idx;
+                       if (nubus_disabled)
+                               via2[gIER] = IER_CLR_BIT(1);
+                       break;
+               case MAC_VIA_IIci:
                        via2[rSIER] = IER_CLR_BIT(irq_idx);
-               } else {
-                       /* disable the nubus irq by changing dir to output */
-                       /* except on PMU */
+                       break;
+               case MAC_VIA_QUADRA:
                        if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
-                          (macintosh_config->adb_type != MAC_ADB_PB2)) {
-                               via2[vDirA] |= irq_bit;
-                       }
+                           (macintosh_config->adb_type != MAC_ADB_PB2))
+                               via2[vDirA] |= 1 << irq_idx;
+                       break;
                }
-               nubus_active &= ~irq_bit;
        }
 }
 
@@ -580,7 +625,9 @@ void via_irq_clear(int irq) {
        } else if (irq_src == 2) {
                via2[gIFR] = irq_bit | rbv_clear;
        } else if (irq_src == 7) {
-               /* FIXME: hmm.. */
+               /* FIXME: There is no way to clear an individual nubus slot
+                * IRQ flag, other than getting the device to do it.
+                */
        }
 }
 
@@ -600,6 +647,7 @@ int via_irq_pending(int irq)
        } else if (irq_src == 2) {
                return via2[gIFR] & irq_bit;
        } else if (irq_src == 7) {
+               /* Always 0 for MAC_VIA_QUADRA if the slot irq is disabled. */
                return ~via2[gBufA] & irq_bit;
        }
        return 0;
index 92f873c..476e18e 100644 (file)
 #include <asm/machdep.h>
 #include <asm/q40_master.h>
 
-extern irqreturn_t q40_process_int (int level, struct pt_regs *regs);
-extern void q40_init_IRQ (void);
+extern irqreturn_t q40_process_int(int level, struct pt_regs *regs);
+extern void q40_init_IRQ(void);
 static void q40_get_model(char *model);
 static int  q40_get_hardware_list(char *buffer);
 extern void q40_sched_init(irq_handler_t handler);
 
-extern unsigned long q40_gettimeoffset (void);
-extern int q40_hwclk (int, struct rtc_time *);
-extern unsigned int q40_get_ss (void);
-extern int q40_set_clock_mmss (unsigned long);
+extern unsigned long q40_gettimeoffset(void);
+extern int q40_hwclk(int, struct rtc_time *);
+extern unsigned int q40_get_ss(void);
+extern int q40_set_clock_mmss(unsigned long);
 static int q40_get_rtc_pll(struct rtc_pll_info *pll);
 static int q40_set_rtc_pll(struct rtc_pll_info *pll);
-extern void q40_reset (void);
+extern void q40_reset(void);
 void q40_halt(void);
 extern void q40_waitbut(void);
-void q40_set_vectors (void);
+void q40_set_vectors(void);
 
-extern void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/ );
+extern void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/);
 
-extern char m68k_debug_device[];
 static void q40_mem_console_write(struct console *co, const char *b,
-                                   unsigned int count);
+                                 unsigned int count);
 
 extern int ql_ticks;
 
 static struct console q40_console_driver = {
-       .name =         "debug",
-       .flags =        CON_PRINTBUFFER,
-       .index =        -1,
+       .name   = "debug",
+       .write  = q40_mem_console_write,
+       .flags  = CON_PRINTBUFFER,
+       .index  = -1,
 };
 
 
@@ -74,150 +74,162 @@ static int _cpleft;
 static void q40_mem_console_write(struct console *co, const char *s,
                                  unsigned int count)
 {
-  char *p=(char *)s;
-
-  if (count<_cpleft)
-    while (count-- >0){
-      *q40_mem_cptr=*p++;
-      q40_mem_cptr+=4;
-      _cpleft--;
-    }
+       const char *p = s;
+
+       if (count < _cpleft) {
+               while (count-- > 0) {
+                       *q40_mem_cptr = *p++;
+                       q40_mem_cptr += 4;
+                       _cpleft--;
+               }
+       }
+}
+
+static int __init q40_debug_setup(char *arg)
+{
+       /* useful for early debugging stages - writes kernel messages into SRAM */
+       if (MACH_IS_Q40 && !strncmp(arg, "mem", 3)) {
+               /*printk("using NVRAM debug, q40_mem_cptr=%p\n",q40_mem_cptr);*/
+               _cpleft = 2000 - ((long)q40_mem_cptr-0xff020000) / 4;
+               register_console(&q40_console_driver);
+       }
+       return 0;
 }
+
+early_param("debug", q40_debug_setup);
+
 #if 0
 void printq40(char *str)
 {
-  int l=strlen(str);
-  char *p=q40_mem_cptr;
-
-  while (l-- >0 && _cpleft-- >0)
-    {
-      *p=*str++;
-      p+=4;
-    }
-  q40_mem_cptr=p;
+       int l = strlen(str);
+       char *p = q40_mem_cptr;
+
+       while (l-- > 0 && _cpleft-- > 0) {
+               *p = *str++;
+               p += 4;
+       }
+       q40_mem_cptr = p;
 }
 #endif
 
-static int halted=0;
+static int halted;
 
 #ifdef CONFIG_HEARTBEAT
 static void q40_heartbeat(int on)
 {
-  if (halted) return;
+       if (halted)
+               return;
 
-  if (on)
-    Q40_LED_ON();
-  else
-    Q40_LED_OFF();
+       if (on)
+               Q40_LED_ON();
+       else
+               Q40_LED_OFF();
 }
 #endif
 
 void q40_reset(void)
 {
-        halted=1;
-        printk ("\n\n*******************************************\n"
+        halted = 1;
+        printk("\n\n*******************************************\n"
                "Called q40_reset : press the RESET button!! \n"
                "*******************************************\n");
        Q40_LED_ON();
-       while(1) ;
+       while (1)
+               ;
 }
 void q40_halt(void)
 {
-        halted=1;
-        printk ("\n\n*******************\n"
-                   "  Called q40_halt\n"
-                   "*******************\n");
+        halted = 1;
+        printk("\n\n*******************\n"
+                  "  Called q40_halt\n"
+                  "*******************\n");
        Q40_LED_ON();
-       while(1) ;
+       while (1)
+               ;
 }
 
 static void q40_get_model(char *model)
 {
-    sprintf(model, "Q40");
+       sprintf(model, "Q40");
 }
 
 /* No hardware options on Q40? */
 
 static int q40_get_hardware_list(char *buffer)
 {
-    *buffer = '\0';
-    return 0;
+       *buffer = '\0';
+       return 0;
 }
 
-static unsigned int serports[]={0x3f8,0x2f8,0x3e8,0x2e8,0};
+static unsigned int serports[] =
+{
+       0x3f8,0x2f8,0x3e8,0x2e8,0
+};
 void q40_disable_irqs(void)
 {
-  unsigned i,j;
+       unsigned i, j;
 
-  j=0;
-  while((i=serports[j++])) outb(0,i+UART_IER);
-  master_outb(0,EXT_ENABLE_REG);
-  master_outb(0,KEY_IRQ_ENABLE_REG);
+       j = 0;
+       while ((i = serports[j++]))
+               outb(0, i + UART_IER);
+       master_outb(0, EXT_ENABLE_REG);
+       master_outb(0, KEY_IRQ_ENABLE_REG);
 }
 
 void __init config_q40(void)
 {
-    mach_sched_init      = q40_sched_init;
+       mach_sched_init = q40_sched_init;
 
-    mach_init_IRQ        = q40_init_IRQ;
-    mach_gettimeoffset   = q40_gettimeoffset;
-    mach_hwclk           = q40_hwclk;
-    mach_get_ss          = q40_get_ss;
-    mach_get_rtc_pll     = q40_get_rtc_pll;
-    mach_set_rtc_pll     = q40_set_rtc_pll;
-    mach_set_clock_mmss         = q40_set_clock_mmss;
+       mach_init_IRQ = q40_init_IRQ;
+       mach_gettimeoffset = q40_gettimeoffset;
+       mach_hwclk = q40_hwclk;
+       mach_get_ss = q40_get_ss;
+       mach_get_rtc_pll = q40_get_rtc_pll;
+       mach_set_rtc_pll = q40_set_rtc_pll;
+       mach_set_clock_mmss = q40_set_clock_mmss;
 
-    mach_reset          = q40_reset;
-    mach_get_model       = q40_get_model;
-    mach_get_hardware_list = q40_get_hardware_list;
+       mach_reset = q40_reset;
+       mach_get_model = q40_get_model;
+       mach_get_hardware_list = q40_get_hardware_list;
 
 #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
-    mach_beep            = q40_mksound;
+       mach_beep = q40_mksound;
 #endif
 #ifdef CONFIG_HEARTBEAT
-    mach_heartbeat = q40_heartbeat;
+       mach_heartbeat = q40_heartbeat;
 #endif
-    mach_halt = q40_halt;
-
-    /* disable a few things that SMSQ might have left enabled */
-    q40_disable_irqs();
-
-    /* no DMA at all, but ide-scsi requires it.. make sure
-     * all physical RAM fits into the boundary - otherwise
-     * allocator may play costly and useless tricks */
-    mach_max_dma_address = 1024*1024*1024;
-
-    /* useful for early debugging stages - writes kernel messages into SRAM */
-    if (!strncmp( m68k_debug_device,"mem",3 ))
-      {
-       /*printk("using NVRAM debug, q40_mem_cptr=%p\n",q40_mem_cptr);*/
-       _cpleft=2000-((long)q40_mem_cptr-0xff020000)/4;
-       q40_console_driver.write = q40_mem_console_write;
-       register_console(&q40_console_driver);
-      }
+       mach_halt = q40_halt;
+
+       /* disable a few things that SMSQ might have left enabled */
+       q40_disable_irqs();
+
+       /* no DMA at all, but ide-scsi requires it.. make sure
+        * all physical RAM fits into the boundary - otherwise
+        * allocator may play costly and useless tricks */
+       mach_max_dma_address = 1024*1024*1024;
 }
 
 
 int q40_parse_bootinfo(const struct bi_record *rec)
 {
-  return 1;
+       return 1;
 }
 
 
-static inline unsigned char bcd2bin (unsigned char b)
+static inline unsigned char bcd2bin(unsigned char b)
 {
-       return ((b>>4)*10 + (b&15));
+       return (b >> 4) * 10 + (b & 15);
 }
 
-static inline unsigned char bin2bcd (unsigned char b)
+static inline unsigned char bin2bcd(unsigned char b)
 {
-       return (((b/10)*16) + (b%10));
+       return (b / 10) * 16 + (b % 10);
 }
 
 
-unsigned long q40_gettimeoffset (void)
+unsigned long q40_gettimeoffset(void)
 {
-    return 5000*(ql_ticks!=0);
+       return 5000 * (ql_ticks != 0);
 }
 
 
@@ -238,9 +250,9 @@ unsigned long q40_gettimeoffset (void)
 
 int q40_hwclk(int op, struct rtc_time *t)
 {
-        if (op)
-       {       /* Write.... */
-               Q40_RTC_CTRL |= Q40_RTC_WRITE;
+       if (op) {
+               /* Write.... */
+               Q40_RTC_CTRL |= Q40_RTC_WRITE;
 
                Q40_RTC_SECS = bin2bcd(t->tm_sec);
                Q40_RTC_MINS = bin2bcd(t->tm_min);
@@ -251,25 +263,23 @@ int q40_hwclk(int op, struct rtc_time *t)
                if (t->tm_wday >= 0)
                        Q40_RTC_DOW = bin2bcd(t->tm_wday+1);
 
-               Q40_RTC_CTRL &= ~(Q40_RTC_WRITE);
-       }
-       else
-       {       /* Read....  */
-         Q40_RTC_CTRL |= Q40_RTC_READ;
-
-         t->tm_year = bcd2bin (Q40_RTC_YEAR);
-         t->tm_mon  = bcd2bin (Q40_RTC_MNTH)-1;
-         t->tm_mday = bcd2bin (Q40_RTC_DATE);
-         t->tm_hour = bcd2bin (Q40_RTC_HOUR);
-         t->tm_min  = bcd2bin (Q40_RTC_MINS);
-         t->tm_sec  = bcd2bin (Q40_RTC_SECS);
-
-         Q40_RTC_CTRL &= ~(Q40_RTC_READ);
-
-         if (t->tm_year < 70)
-           t->tm_year += 100;
-         t->tm_wday = bcd2bin(Q40_RTC_DOW)-1;
-
+               Q40_RTC_CTRL &= ~(Q40_RTC_WRITE);
+       } else {
+               /* Read....  */
+               Q40_RTC_CTRL |= Q40_RTC_READ;
+
+               t->tm_year = bcd2bin (Q40_RTC_YEAR);
+               t->tm_mon  = bcd2bin (Q40_RTC_MNTH)-1;
+               t->tm_mday = bcd2bin (Q40_RTC_DATE);
+               t->tm_hour = bcd2bin (Q40_RTC_HOUR);
+               t->tm_min  = bcd2bin (Q40_RTC_MINS);
+               t->tm_sec  = bcd2bin (Q40_RTC_SECS);
+
+               Q40_RTC_CTRL &= ~(Q40_RTC_READ);
+
+               if (t->tm_year < 70)
+                       t->tm_year += 100;
+               t->tm_wday = bcd2bin(Q40_RTC_DOW)-1;
        }
 
        return 0;
@@ -285,29 +295,25 @@ unsigned int q40_get_ss(void)
  * clock is out by > 30 minutes.  Logic lifted from atari code.
  */
 
-int q40_set_clock_mmss (unsigned long nowtime)
+int q40_set_clock_mmss(unsigned long nowtime)
 {
        int retval = 0;
        short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
 
        int rtc_minutes;
 
+       rtc_minutes = bcd2bin(Q40_RTC_MINS);
 
-       rtc_minutes = bcd2bin (Q40_RTC_MINS);
-
-       if ((rtc_minutes < real_minutes
-               ? real_minutes - rtc_minutes
-                       : rtc_minutes - real_minutes) < 30)
-       {
-               Q40_RTC_CTRL |= Q40_RTC_WRITE;
+       if ((rtc_minutes < real_minutes ?
+            real_minutes - rtc_minutes :
+            rtc_minutes - real_minutes) < 30) {
+               Q40_RTC_CTRL |= Q40_RTC_WRITE;
                Q40_RTC_MINS = bin2bcd(real_minutes);
                Q40_RTC_SECS = bin2bcd(real_seconds);
                Q40_RTC_CTRL &= ~(Q40_RTC_WRITE);
-       }
-       else
+       } else
                retval = -1;
 
-
        return retval;
 }
 
@@ -318,21 +324,23 @@ int q40_set_clock_mmss (unsigned long nowtime)
 
 static int q40_get_rtc_pll(struct rtc_pll_info *pll)
 {
-       int tmp=Q40_RTC_CTRL;
+       int tmp = Q40_RTC_CTRL;
+
        pll->pll_value = tmp & Q40_RTC_PLL_MASK;
        if (tmp & Q40_RTC_PLL_SIGN)
                pll->pll_value = -pll->pll_value;
-       pll->pll_max=31;
-       pll->pll_min=-31;
-       pll->pll_posmult=512;
-       pll->pll_negmult=256;
-       pll->pll_clock=125829120;
+       pll->pll_max = 31;
+       pll->pll_min = -31;
+       pll->pll_posmult = 512;
+       pll->pll_negmult = 256;
+       pll->pll_clock = 125829120;
+
        return 0;
 }
 
 static int q40_set_rtc_pll(struct rtc_pll_info *pll)
 {
-       if (!pll->pll_ctrl){
+       if (!pll->pll_ctrl) {
                /* the docs are a bit unclear so I am doublesetting */
                /* RTC_WRITE here ... */
                int tmp = (pll->pll_value & 31) | (pll->pll_value<0 ? 32 : 0) |
index baf74e8..4232a2c 100644 (file)
@@ -103,7 +103,7 @@ void sun3_init_IRQ(void)
 
        m68k_setup_auto_interrupt(sun3_inthandle);
        m68k_setup_irq_controller(&sun3_irq_controller, IRQ_AUTO_1, 7);
-       m68k_setup_user_interrupt(VEC_USER, 192, NULL);
+       m68k_setup_user_interrupt(VEC_USER, 128, NULL);
 
        request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL);
        request_irq(IRQ_AUTO_7, sun3_int7, 0, "int7", NULL);
index 574cf06..48f8eb7 100644 (file)
@@ -34,100 +34,101 @@ e_vector *sun3x_prom_vbr;
 /* Handle returning to the prom */
 void sun3x_halt(void)
 {
-    unsigned long flags;
+       unsigned long flags;
 
-    /* Disable interrupts while we mess with things */
-    local_irq_save(flags);
+       /* Disable interrupts while we mess with things */
+       local_irq_save(flags);
 
-    /* Restore prom vbr */
-    __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
+       /* Restore prom vbr */
+       asm volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
 
-    /* Restore prom NMI clock */
-//    sun3x_disable_intreg(5);
-    sun3_enable_irq(7);
+       /* Restore prom NMI clock */
+//     sun3x_disable_intreg(5);
+       sun3_enable_irq(7);
 
-    /* Let 'er rip */
-    __asm__ volatile ("trap #14" : : );
+       /* Let 'er rip */
+       asm volatile ("trap #14");
 
-    /* Restore everything */
-    sun3_disable_irq(7);
-    sun3_enable_irq(5);
+       /* Restore everything */
+       sun3_disable_irq(7);
+       sun3_enable_irq(5);
 
-    __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
-    local_irq_restore(flags);
+       asm volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
+       local_irq_restore(flags);
 }
 
 void sun3x_reboot(void)
 {
-    /* This never returns, don't bother saving things */
-    local_irq_disable();
+       /* This never returns, don't bother saving things */
+       local_irq_disable();
 
-    /* Restore prom vbr */
-    __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
+       /* Restore prom vbr */
+       asm volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
 
-    /* Restore prom NMI clock */
-    sun3_disable_irq(5);
-    sun3_enable_irq(7);
+       /* Restore prom NMI clock */
+       sun3_disable_irq(5);
+       sun3_enable_irq(7);
 
-    /* Let 'er rip */
-    (*romvec->pv_reboot)("vmlinux");
+       /* Let 'er rip */
+       (*romvec->pv_reboot)("vmlinux");
 }
 
-extern char m68k_debug_device[];
-
 static void sun3x_prom_write(struct console *co, const char *s,
                              unsigned int count)
 {
-    while (count--) {
-        if (*s == '\n')
-            sun3x_putchar('\r');
-        sun3x_putchar(*s++);
-    }
+       while (count--) {
+               if (*s == '\n')
+                       sun3x_putchar('\r');
+               sun3x_putchar(*s++);
+       }
 }
 
 /* debug console - write-only */
 
 static struct console sun3x_debug = {
-       .name  =        "debug",
-       .write =        sun3x_prom_write,
-       .flags =        CON_PRINTBUFFER,
-       .index =        -1,
+       .name   = "debug",
+       .write  = sun3x_prom_write,
+       .flags  = CON_PRINTBUFFER,
+       .index  = -1,
 };
 
 void sun3x_prom_init(void)
 {
-    /* Read the vector table */
-
-    sun3x_putchar = *(void (**)(int)) (SUN3X_P_PUTCHAR);
-    sun3x_getchar = *(int (**)(void)) (SUN3X_P_GETCHAR);
-    sun3x_mayget = *(int (**)(void))  (SUN3X_P_MAYGET);
-    sun3x_mayput = *(int (**)(int))   (SUN3X_P_MAYPUT);
-    sun3x_prom_reboot = *(void (**)(void)) (SUN3X_P_REBOOT);
-    sun3x_prom_abort = *(e_vector *)  (SUN3X_P_ABORT);
-    romvec = (struct linux_romvec *)SUN3X_PROM_BASE;
-
-    idprom_init();
-
-    if(!((idprom->id_machtype & SM_ARCH_MASK) == SM_SUN3X)) {
-           printk("Warning: machine reports strange type %02x\n",
-                  idprom->id_machtype);
-           printk("Pretending it's a 3/80, but very afraid...\n");
-           idprom->id_machtype = SM_SUN3X | SM_3_80;
-    }
-
-    /* point trap #14 at abort.
-     * XXX this is futile since we restore the vbr first - oops
-     */
-    vectors[VEC_TRAP14] = sun3x_prom_abort;
-
-    /* If debug=prom was specified, start the debug console */
-
-    if (!strcmp(m68k_debug_device, "prom"))
-        register_console(&sun3x_debug);
-
+       /* Read the vector table */
+
+       sun3x_putchar = *(void (**)(int)) (SUN3X_P_PUTCHAR);
+       sun3x_getchar = *(int (**)(void)) (SUN3X_P_GETCHAR);
+       sun3x_mayget = *(int (**)(void))  (SUN3X_P_MAYGET);
+       sun3x_mayput = *(int (**)(int))   (SUN3X_P_MAYPUT);
+       sun3x_prom_reboot = *(void (**)(void)) (SUN3X_P_REBOOT);
+       sun3x_prom_abort = *(e_vector *)  (SUN3X_P_ABORT);
+       romvec = (struct linux_romvec *)SUN3X_PROM_BASE;
+
+       idprom_init();
+
+       if (!((idprom->id_machtype & SM_ARCH_MASK) == SM_SUN3X)) {
+               printk("Warning: machine reports strange type %02x\n",
+                       idprom->id_machtype);
+               printk("Pretending it's a 3/80, but very afraid...\n");
+               idprom->id_machtype = SM_SUN3X | SM_3_80;
+       }
+
+       /* point trap #14 at abort.
+        * XXX this is futile since we restore the vbr first - oops
+        */
+       vectors[VEC_TRAP14] = sun3x_prom_abort;
+}
 
+static int __init sun3x_debug_setup(char *arg)
+{
+       /* If debug=prom was specified, start the debug console */
+       if (MACH_IS_SUN3X && !strcmp(arg, "prom"))
+               register_console(&sun3x_debug);
+       return 0;
 }
 
+early_param("debug", sun3x_debug_setup);
+
 /* some prom functions to export */
 int prom_getintdefault(int node, char *property, int deflt)
 {
@@ -141,7 +142,6 @@ int prom_getbool (int node, char *prop)
 
 void prom_printf(char *fmt, ...)
 {
-
 }
 
 void prom_halt (void)
@@ -159,7 +159,7 @@ prom_get_idprom(char *idbuf, int num_bytes)
         int i;
 
        /* make a copy of the idprom structure */
-       for(i = 0; i < num_bytes; i++)
+       for (i = 0; i < num_bytes; i++)
                idbuf[i] = ((char *)SUN3X_IDPROM)[i];
 
         return idbuf[0];
index 14b19c4..0a25874 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/string.h>
-#include <linux/pci.h>
 #include <asm/io.h>
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
index de017c1..9565b21 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the Cobalt micro systems family specific parts of the kernel
 #
 
-obj-y   := irq.o reset.o setup.o
+obj-y   := irq.o reset.o setup.o buttons.o
 
 obj-$(CONFIG_PCI)              += pci.o
 obj-$(CONFIG_EARLY_PRINTK)     += console.o
diff --git a/arch/mips/cobalt/buttons.c b/arch/mips/cobalt/buttons.c
new file mode 100644 (file)
index 0000000..9e14398
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ *  Cobalt buttons platform device.
+ *
+ *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+static struct resource cobalt_buttons_resource __initdata = {
+       .start  = 0x1d000000,
+       .end    = 0x1d000003,
+       .flags  = IORESOURCE_MEM,
+};
+
+static __init int cobalt_add_buttons(void)
+{
+       struct platform_device *pd;
+       int error;
+
+       pd = platform_device_alloc("Cobalt buttons", -1);
+       if (!pd)
+               return -ENOMEM;
+
+       error = platform_device_add_resources(pd, &cobalt_buttons_resource, 1);
+       if (error)
+               goto err_free_device;
+
+       error = platform_device_add(pd);
+       if (error)
+               goto err_free_device;
+
+       return 0;
+
+ err_free_device:
+       platform_device_put(pd);
+       return error;
+}
+device_initcall(cobalt_add_buttons);
index d51d5cb..e3acb2d 100644 (file)
@@ -6,7 +6,6 @@
  * (C) Copyright 2007 MIPS Technologies, Inc.
  *     written by Ralf Baechle <ralf@linux-mips.org>
  */
-#include <linux/pci.h>
 #include <linux/module.h>
 #include <asm/io.h>
 
index 60d7d4b..7138092 100644 (file)
@@ -340,7 +340,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
        struct pci_dev *dev;
        const char *type;
 
-       dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
+       dev = alloc_pci_dev();
        if (!dev)
                return NULL;
        type = of_get_property(node, "device_type", NULL);
index 9eaefac..b2c1b67 100644 (file)
@@ -37,7 +37,7 @@
 #include <asm/iseries/hv_call_xm.h>
 #include <asm/iseries/iommu.h>
 
-extern struct subsystem devices_subsys; /* needed for vio_find_name() */
+extern struct kset devices_subsys; /* needed for vio_find_name() */
 
 static struct vio_dev vio_bus_device  = { /* fake "parent" device */
        .name = vio_bus_device.dev.bus_id,
@@ -427,7 +427,7 @@ static struct vio_dev *vio_find_name(const char *kobj_name)
 {
        struct kobject *found;
 
-       found = kset_find_obj(&devices_subsys.kset, kobj_name);
+       found = kset_find_obj(&devices_subsys, kobj_name);
        if (!found)
                return NULL;
 
index 8943a94..1fe35da 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/cpufreq.h>
 #include <linux/init.h>
 #include <linux/sysdev.h>
-#include <linux/i2c.h>
 #include <linux/hardirq.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
index 2624b71..73e6902 100644 (file)
 
 unsigned long rtas_poweron_auto; /* default and normal state is 0 */
 
-static ssize_t auto_poweron_show(struct subsystem *subsys, char *buf)
+static ssize_t auto_poweron_show(struct kset *kset, char *buf)
 {
         return sprintf(buf, "%lu\n", rtas_poweron_auto);
 }
 
 static ssize_t
-auto_poweron_store(struct subsystem *subsys, const char *buf, size_t n)
+auto_poweron_store(struct kset *kset, const char *buf, size_t n)
 {
        int ret;
        unsigned long ups_restart;
@@ -72,12 +72,12 @@ static int __init pm_init(void)
 {
         int error = subsystem_register(&power_subsys);
         if (!error)
-                error = sysfs_create_group(&power_subsys.kset.kobj,&attr_group);
+                error = sysfs_create_group(&power_subsys.kobj, &attr_group);
         return error;
 }
 core_initcall(pm_init);
 #else
-extern struct subsystem power_subsys;
+extern struct kset power_subsys;
 
 static int __init apo_pm_init(void)
 {
index 53aa041..3a393c7 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/timex.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/random.h>
index 48ce84f..4c0a7d7 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
index 9db825f..cab395d 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
index bfa3f52..e58288e 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
index 939abe3..5dadca3 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/pci.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
index a43f348..2180ac1 100644 (file)
@@ -107,7 +107,7 @@ static void appldata_get_net_sum_data(void *data)
        tx_dropped = 0;
        collisions = 0;
        read_lock(&dev_base_lock);
-       for (dev = dev_base; dev != NULL; dev = dev->next) {
+       for_each_netdev(dev) {
                stats = dev->get_stats(dev);
                rx_packets += stats->rx_packets;
                tx_packets += stats->tx_packets;
index 9163635..3660ca6 100644 (file)
@@ -119,7 +119,8 @@ static struct crypto_alg aes_alg = {
        .cra_name               =       "aes",
        .cra_driver_name        =       "aes-s390",
        .cra_priority           =       CRYPT_S390_PRIORITY,
-       .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
+       .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER |
+                                       CRYPTO_ALG_NEED_FALLBACK,
        .cra_blocksize          =       AES_BLOCK_SIZE,
        .cra_ctxsize            =       sizeof(struct s390_aes_ctx),
        .cra_module             =       THIS_MODULE,
@@ -206,7 +207,8 @@ static struct crypto_alg ecb_aes_alg = {
        .cra_name               =       "ecb(aes)",
        .cra_driver_name        =       "ecb-aes-s390",
        .cra_priority           =       CRYPT_S390_COMPOSITE_PRIORITY,
-       .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER,
+       .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER |
+                                       CRYPTO_ALG_NEED_FALLBACK,
        .cra_blocksize          =       AES_BLOCK_SIZE,
        .cra_ctxsize            =       sizeof(struct s390_aes_ctx),
        .cra_type               =       &crypto_blkcipher_type,
@@ -300,7 +302,8 @@ static struct crypto_alg cbc_aes_alg = {
        .cra_name               =       "cbc(aes)",
        .cra_driver_name        =       "cbc-aes-s390",
        .cra_priority           =       CRYPT_S390_COMPOSITE_PRIORITY,
-       .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER,
+       .cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER |
+                                       CRYPTO_ALG_NEED_FALLBACK,
        .cra_blocksize          =       AES_BLOCK_SIZE,
        .cra_ctxsize            =       sizeof(struct s390_aes_ctx),
        .cra_type               =       &crypto_blkcipher_type,
@@ -333,10 +336,14 @@ static int __init aes_init(void)
                return -EOPNOTSUPP;
 
        /* z9 109 and z9 BC/EC only support 128 bit key length */
-       if (keylen_flag == AES_KEYLEN_128)
+       if (keylen_flag == AES_KEYLEN_128) {
+               aes_alg.cra_u.cipher.cia_max_keysize = AES_MIN_KEY_SIZE;
+               ecb_aes_alg.cra_u.blkcipher.max_keysize = AES_MIN_KEY_SIZE;
+               cbc_aes_alg.cra_u.blkcipher.max_keysize = AES_MIN_KEY_SIZE;
                printk(KERN_INFO
                       "aes_s390: hardware acceleration only available for"
                       "128 bit keys\n");
+       }
 
        ret = crypto_register_alg(&aes_alg);
        if (ret)
index 06833ac..0ea048d 100644 (file)
@@ -164,7 +164,7 @@ EXPORT_SYMBOL_GPL(diag308);
 /* SYSFS */
 
 #define DEFINE_IPL_ATTR_RO(_prefix, _name, _format, _value)            \
-static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys,        \
+static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset,       \
                char *page)                                             \
 {                                                                      \
        return sprintf(page, _format, _value);                          \
@@ -173,13 +173,13 @@ static struct subsys_attribute sys_##_prefix##_##_name##_attr =           \
        __ATTR(_name, S_IRUGO, sys_##_prefix##_##_name##_show, NULL);
 
 #define DEFINE_IPL_ATTR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)  \
-static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys,        \
+static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset,       \
                char *page)                                             \
 {                                                                      \
        return sprintf(page, _fmt_out,                                  \
                        (unsigned long long) _value);                   \
 }                                                                      \
-static ssize_t sys_##_prefix##_##_name##_store(struct subsystem *subsys,\
+static ssize_t sys_##_prefix##_##_name##_store(struct kset *kset,      \
                const char *buf, size_t len)                            \
 {                                                                      \
        unsigned long long value;                                       \
@@ -194,12 +194,12 @@ static struct subsys_attribute sys_##_prefix##_##_name##_attr =           \
                        sys_##_prefix##_##_name##_store);
 
 #define DEFINE_IPL_ATTR_STR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)\
-static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys,        \
+static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset,       \
                char *page)                                             \
 {                                                                      \
        return sprintf(page, _fmt_out, _value);                         \
 }                                                                      \
-static ssize_t sys_##_prefix##_##_name##_store(struct subsystem *subsys,\
+static ssize_t sys_##_prefix##_##_name##_store(struct kset *kset,      \
                const char *buf, size_t len)                            \
 {                                                                      \
        if (sscanf(buf, _fmt_in, _value) != 1)                          \
@@ -272,14 +272,14 @@ void __init setup_ipl_info(void)
 struct ipl_info ipl_info;
 EXPORT_SYMBOL_GPL(ipl_info);
 
-static ssize_t ipl_type_show(struct subsystem *subsys, char *page)
+static ssize_t ipl_type_show(struct kset *kset, char *page)
 {
        return sprintf(page, "%s\n", ipl_type_str(ipl_info.type));
 }
 
 static struct subsys_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
 
-static ssize_t sys_ipl_device_show(struct subsystem *subsys, char *page)
+static ssize_t sys_ipl_device_show(struct kset *kset, char *page)
 {
        struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
 
@@ -371,7 +371,7 @@ static struct attribute_group ipl_fcp_attr_group = {
 
 /* CCW ipl device attributes */
 
-static ssize_t ipl_ccw_loadparm_show(struct subsystem *subsys, char *page)
+static ssize_t ipl_ccw_loadparm_show(struct kset *kset, char *page)
 {
        char loadparm[LOADPARM_LEN + 1] = {};
 
@@ -469,7 +469,7 @@ static void reipl_get_ascii_loadparm(char *loadparm)
        strstrip(loadparm);
 }
 
-static ssize_t reipl_ccw_loadparm_show(struct subsystem *subsys, char *page)
+static ssize_t reipl_ccw_loadparm_show(struct kset *kset, char *page)
 {
        char buf[LOADPARM_LEN + 1];
 
@@ -477,7 +477,7 @@ static ssize_t reipl_ccw_loadparm_show(struct subsystem *subsys, char *page)
        return sprintf(page, "%s\n", buf);
 }
 
-static ssize_t reipl_ccw_loadparm_store(struct subsystem *subsys,
+static ssize_t reipl_ccw_loadparm_store(struct kset *kset,
                                        const char *buf, size_t len)
 {
        int i, lp_len;
@@ -572,12 +572,12 @@ static int reipl_set_type(enum ipl_type type)
        return 0;
 }
 
-static ssize_t reipl_type_show(struct subsystem *subsys, char *page)
+static ssize_t reipl_type_show(struct kset *kset, char *page)
 {
        return sprintf(page, "%s\n", ipl_type_str(reipl_type));
 }
 
-static ssize_t reipl_type_store(struct subsystem *subsys, const char *buf,
+static ssize_t reipl_type_store(struct kset *kset, const char *buf,
                                size_t len)
 {
        int rc = -EINVAL;
@@ -665,12 +665,12 @@ static int dump_set_type(enum dump_type type)
        return 0;
 }
 
-static ssize_t dump_type_show(struct subsystem *subsys, char *page)
+static ssize_t dump_type_show(struct kset *kset, char *page)
 {
        return sprintf(page, "%s\n", dump_type_str(dump_type));
 }
 
-static ssize_t dump_type_store(struct subsystem *subsys, const char *buf,
+static ssize_t dump_type_store(struct kset *kset, const char *buf,
                               size_t len)
 {
        int rc = -EINVAL;
@@ -697,12 +697,12 @@ static decl_subsys(shutdown_actions, NULL, NULL);
 
 /* on panic */
 
-static ssize_t on_panic_show(struct subsystem *subsys, char *page)
+static ssize_t on_panic_show(struct kset *kset, char *page)
 {
        return sprintf(page, "%s\n", shutdown_action_str(on_panic_action));
 }
 
-static ssize_t on_panic_store(struct subsystem *subsys, const char *buf,
+static ssize_t on_panic_store(struct kset *kset, const char *buf,
                              size_t len)
 {
        if (strncmp(buf, SHUTDOWN_REIPL_STR, strlen(SHUTDOWN_REIPL_STR)) == 0)
index 993f353..23c61f6 100644 (file)
@@ -516,7 +516,7 @@ out:
        return 1;
 }
 
-static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
        struct kprobe *cur = kprobe_running();
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -603,7 +603,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
                        ret = NOTIFY_STOP;
                break;
        case DIE_TRAP:
-       case DIE_PAGE_FAULT:
                /* kprobe_running() needs smp_processor_id() */
                preempt_disable();
                if (kprobe_running() &&
index 3dfd098..6bfb088 100644 (file)
@@ -65,7 +65,7 @@ long psw_user_bits    = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
  * User copy operations.
  */
 struct uaccess_ops uaccess;
-EXPORT_SYMBOL_GPL(uaccess);
+EXPORT_SYMBOL(uaccess);
 
 /*
  * Machine setup..
@@ -74,6 +74,8 @@ unsigned int console_mode = 0;
 unsigned int console_devno = -1;
 unsigned int console_irq = -1;
 unsigned long machine_flags = 0;
+unsigned long elf_hwcap = 0;
+char elf_platform[ELF_PLATFORM_SIZE];
 
 struct mem_chunk __initdata memory_chunk[MEMORY_CHUNKS];
 volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
@@ -749,6 +751,98 @@ setup_memory(void)
 #endif
 }
 
+static __init unsigned int stfl(void)
+{
+       asm volatile(
+               "       .insn   s,0xb2b10000,0(0)\n" /* stfl */
+               "0:\n"
+               EX_TABLE(0b,0b));
+       return S390_lowcore.stfl_fac_list;
+}
+
+static __init int stfle(unsigned long long *list, int doublewords)
+{
+       typedef struct { unsigned long long _[doublewords]; } addrtype;
+       register unsigned long __nr asm("0") = doublewords - 1;
+
+       asm volatile(".insn s,0xb2b00000,%0" /* stfle */
+                    : "=m" (*(addrtype *) list), "+d" (__nr) : : "cc");
+       return __nr + 1;
+}
+
+/*
+ * Setup hardware capabilities.
+ */
+static void __init setup_hwcaps(void)
+{
+       static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 };
+       struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
+       unsigned long long facility_list_extended;
+       unsigned int facility_list;
+       int i;
+
+       facility_list = stfl();
+       /*
+        * The store facility list bits numbers as found in the principles
+        * of operation are numbered with bit 1UL<<31 as number 0 to
+        * bit 1UL<<0 as number 31.
+        *   Bit 0: instructions named N3, "backported" to esa-mode
+        *   Bit 2: z/Architecture mode is active
+        *   Bit 7: the store-facility-list-extended facility is installed
+        *   Bit 17: the message-security assist is installed
+        *   Bit 19: the long-displacement facility is installed
+        *   Bit 21: the extended-immediate facility is installed
+        * These get translated to:
+        *   HWCAP_S390_ESAN3 bit 0, HWCAP_S390_ZARCH bit 1,
+        *   HWCAP_S390_STFLE bit 2, HWCAP_S390_MSA bit 3,
+        *   HWCAP_S390_LDISP bit 4, and HWCAP_S390_EIMM bit 5.
+        */
+       for (i = 0; i < 6; i++)
+               if (facility_list & (1UL << (31 - stfl_bits[i])))
+                       elf_hwcap |= 1UL << i;
+
+       /*
+        * Check for additional facilities with store-facility-list-extended.
+        * stfle stores doublewords (8 byte) with bit 1ULL<<63 as bit 0
+        * and 1ULL<<0 as bit 63. Bits 0-31 contain the same information
+        * as stored by stfl, bits 32-xxx contain additional facilities.
+        * How many facility words are stored depends on the number of
+        * doublewords passed to the instruction. The additional facilites
+        * are:
+        *   Bit 43: decimal floating point facility is installed
+        * translated to:
+        *   HWCAP_S390_DFP bit 6.
+        */
+       if ((elf_hwcap & (1UL << 2)) &&
+           stfle(&facility_list_extended, 1) > 0) {
+               if (facility_list_extended & (1ULL << (64 - 43)))
+                       elf_hwcap |= 1UL << 6;
+       }
+
+       switch (cpuinfo->cpu_id.machine) {
+       case 0x9672:
+#if !defined(CONFIG_64BIT)
+       default:        /* Use "g5" as default for 31 bit kernels. */
+#endif
+               strcpy(elf_platform, "g5");
+               break;
+       case 0x2064:
+       case 0x2066:
+#if defined(CONFIG_64BIT)
+       default:        /* Use "z900" as default for 64 bit kernels. */
+#endif
+               strcpy(elf_platform, "z900");
+               break;
+       case 0x2084:
+       case 0x2086:
+               strcpy(elf_platform, "z990");
+               break;
+       case 0x2094:
+               strcpy(elf_platform, "z9-109");
+               break;
+       }
+}
+
 /*
  * Setup function called from init/main.c just after the banner
  * was printed.
@@ -805,6 +899,11 @@ setup_arch(char **cmdline_p)
        smp_setup_cpu_possible_map();
 
        /*
+        * Setup capabilities (ELF_HWCAP & ELF_PLATFORM).
+        */
+       setup_hwcaps();
+
+       /*
         * Create kernel page tables and switch to virtual addressing.
         */
         paging_init();
@@ -839,8 +938,12 @@ void print_cpu_info(struct cpuinfo_S390 *cpuinfo)
 
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
+       static const char *hwcap_str[7] = {
+               "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp"
+       };
         struct cpuinfo_S390 *cpuinfo;
        unsigned long n = (unsigned long) v - 1;
+       int i;
 
        s390_adjust_jiffies();
        preempt_disable();
@@ -850,7 +953,13 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                               "bogomips per cpu: %lu.%02lu\n",
                               num_online_cpus(), loops_per_jiffy/(500000/HZ),
                               (loops_per_jiffy/(5000/HZ))%100);
+               seq_puts(m, "features\t: ");
+               for (i = 0; i < 7; i++)
+                       if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
+                               seq_printf(m, "%s ", hwcap_str[i]);
+               seq_puts(m, "\n");
        }
+
        if (cpu_online(n)) {
 #ifdef CONFIG_SMP
                if (smp_processor_id() == n)
index 2b76a87..91f705a 100644 (file)
@@ -52,38 +52,24 @@ extern int sysctl_userprocess_debug;
 extern void die(const char *,struct pt_regs *,long);
 
 #ifdef CONFIG_KPROBES
-static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
-int register_page_fault_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
-}
-
-int unregister_page_fault_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
-}
-
-static int __kprobes __notify_page_fault(struct pt_regs *regs, long err)
-{
-       struct die_args args = { .str = "page fault",
-                                .trapnr = 14,
-                                .signr = SIGSEGV };
-       args.regs = regs;
-       args.err = err;
-       return atomic_notifier_call_chain(&notify_page_fault_chain,
-                                         DIE_PAGE_FAULT, &args);
-}
-
 static inline int notify_page_fault(struct pt_regs *regs, long err)
 {
-       if (unlikely(kprobe_running()))
-               return __notify_page_fault(regs, err);
-       return NOTIFY_DONE;
+       int ret = 0;
+
+       /* kprobe_running() needs smp_processor_id() */
+       if (!user_mode(regs)) {
+               preempt_disable();
+               if (kprobe_running() && kprobe_fault_handler(regs, 14))
+                       ret = 1;
+               preempt_enable();
+       }
+
+       return ret;
 }
 #else
 static inline int notify_page_fault(struct pt_regs *regs, long err)
 {
-       return NOTIFY_DONE;
+       return 0;
 }
 #endif
 
@@ -319,7 +305,7 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int write)
        int space;
        int si_code;
 
-       if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
+       if (notify_page_fault(regs, error_code))
                return;
 
        tsk = current;
index 2d06e9a..a5c645f 100644 (file)
@@ -9,7 +9,6 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-#include <linux/pci.h>
 #include <asm/io.h>
 #include <asm/cayman.h>
 
index 590a41b..be9e10b 100644 (file)
@@ -306,6 +306,7 @@ config SUN_IO
 
 config PCI
        bool "PCI support"
+       select ARCH_SUPPORTS_MSI
        help
          Find out whether you have a PCI motherboard. PCI is the name of a
          bus system, i.e. the way the CPU talks to the other stuff inside
index 023af41..9a54954 100644 (file)
@@ -1092,10 +1092,10 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
                return -EINVAL;
 
        err = p->setup_msi_irq(&virt_irq, pdev, desc);
-       if (err < 0)
+       if (err)
                return err;
 
-       return virt_irq;
+       return 0;
 }
 
 void arch_teardown_msi_irq(unsigned int virt_irq)
index 94295c2..1ccf4c9 100644 (file)
@@ -1169,8 +1169,6 @@ static int pci_sun4v_setup_msi_irq(unsigned int *virt_irq_p,
        if (!devino)
                goto out_err;
 
-       set_irq_msi(*virt_irq_p, entry);
-
        msiqid = ((devino - pbm->msiq_first_devino) +
                  pbm->msiq_first);
 
@@ -1204,6 +1202,8 @@ static int pci_sun4v_setup_msi_irq(unsigned int *virt_irq_p,
                msg.address_lo = pbm->msi32_start;
        }
        msg.data = msi_num;
+
+       set_irq_msi(*virt_irq_p, entry);
        write_msi_msg(*virt_irq_p, &msg);
 
        irq_install_pre_handler(*virt_irq_p,
index 330743c..18352a4 100644 (file)
@@ -686,7 +686,8 @@ static inline int solaris_i(unsigned int fd, unsigned int cmd, u32 arg)
                        int i = 0;
                        
                        read_lock_bh(&dev_base_lock);
-                       for (d = dev_base; d; d = d->next) i++;
+                       for_each_netdev(d)
+                               i++;
                        read_unlock_bh(&dev_base_lock);
 
                        if (put_user (i, (int __user *)A(arg)))
index 1cad418..145bb82 100644 (file)
@@ -701,6 +701,7 @@ menu "Bus options (PCI etc.)"
 
 config PCI
        bool "PCI support"
+       select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC)
 
 # x86-64 doesn't support PCI BIOS access from long mode so always go direct.
 config PCI_DIRECT
index 40acb67..c0749d2 100644 (file)
@@ -16,6 +16,9 @@ config X86_POWERNOW_K8
        help
          This adds the CPUFreq driver for mobile AMD Opteron/Athlon64 processors.
 
+         To compile this driver as a module, choose M here: the
+         module will be called powernow-k8.
+
          For details, take a look at <file:Documentation/cpu-freq/>. 
 
          If in doubt, say N.
@@ -38,6 +41,9 @@ config X86_SPEEDSTEP_CENTRINO
          mobile CPUs.  This means Intel Pentium M (Centrino) CPUs
          or 64bit enabled Intel Xeons.
 
+         To compile this driver as a module, choose M here: the
+         module will be called speedstep-centrino.
+
          For details, take a look at <file:Documentation/cpu-freq/>.
 
          If in doubt, say N.
@@ -55,6 +61,9 @@ config X86_ACPI_CPUFREQ
          Processor Performance States.
          This driver also supports Intel Enhanced Speedstep.
 
+         To compile this driver as a module, choose M here: the
+         module will be called acpi-cpufreq.
+
          For details, take a look at <file:Documentation/cpu-freq/>.
 
          If in doubt, say N.
@@ -62,7 +71,7 @@ config X86_ACPI_CPUFREQ
 comment "shared options"
 
 config X86_ACPI_CPUFREQ_PROC_INTF
-        bool "/proc/acpi/processor/../performance interface (deprecated)"
+       bool "/proc/acpi/processor/../performance interface (deprecated)"
        depends on PROC_FS
        depends on X86_ACPI_CPUFREQ || X86_SPEEDSTEP_CENTRINO_ACPI || X86_POWERNOW_K8_ACPI
        help
@@ -86,16 +95,18 @@ config X86_P4_CLOCKMOD
          slowdowns and noticeable latencies.  Normally Speedstep should be used
          instead.
 
+         To compile this driver as a module, choose M here: the
+         module will be called p4-clockmod.
+
          For details, take a look at <file:Documentation/cpu-freq/>.
 
          Unless you are absolutely sure say N.
 
 
 config X86_SPEEDSTEP_LIB
-        tristate
-        default X86_P4_CLOCKMOD
+       tristate
+       default X86_P4_CLOCKMOD
 
 endif
 
 endmenu
-
index dd14ffa..2a2df14 100644 (file)
@@ -1954,18 +1954,18 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
        if (irq < 0)
                return irq;
 
-       set_irq_msi(irq, desc);
        ret = msi_compose_msg(dev, irq, &msg);
        if (ret < 0) {
                destroy_irq(irq);
                return ret;
        }
 
+       set_irq_msi(irq, desc);
        write_msi_msg(irq, &msg);
 
        set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
 
-       return irq;
+       return 0;
 }
 
 void arch_teardown_msi_irq(unsigned int irq)
index 0b4cb93..cd7e6a0 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/interrupt.h>
 #include <asm/irq.h>
 #include <linux/in6.h>
-#include <linux/pci.h>
 #include <linux/ide.h>
 
 #include <asm/uaccess.h>
index c8a42b6..f60c8cf 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/reboot.h>
-#include <linux/pci.h>
 #include <linux/kdev_t.h>
 #include <linux/types.h>
 #include <linux/major.h>
index 441432a..b566444 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/buffer_head.h>
 #include <linux/mutex.h>
 
-struct subsystem block_subsys;
+struct kset block_subsys;
 static DEFINE_MUTEX(block_subsys_lock);
 
 /*
@@ -221,7 +221,7 @@ static void *part_start(struct seq_file *part, loff_t *pos)
        loff_t l = *pos;
 
        mutex_lock(&block_subsys_lock);
-       list_for_each(p, &block_subsys.kset.list)
+       list_for_each(p, &block_subsys.list)
                if (!l--)
                        return list_entry(p, struct gendisk, kobj.entry);
        return NULL;
@@ -231,7 +231,7 @@ static void *part_next(struct seq_file *part, void *v, loff_t *pos)
 {
        struct list_head *p = ((struct gendisk *)v)->kobj.entry.next;
        ++*pos;
-       return p==&block_subsys.kset.list ? NULL : 
+       return p==&block_subsys.list ? NULL :
                list_entry(p, struct gendisk, kobj.entry);
 }
 
@@ -246,7 +246,7 @@ static int show_partition(struct seq_file *part, void *v)
        int n;
        char buf[BDEVNAME_SIZE];
 
-       if (&sgp->kobj.entry == block_subsys.kset.list.next)
+       if (&sgp->kobj.entry == block_subsys.list.next)
                seq_puts(part, "major minor  #blocks  name\n\n");
 
        /* Don't show non-partitionable removeable devices or empty devices */
@@ -565,7 +565,7 @@ static void *diskstats_start(struct seq_file *part, loff_t *pos)
        struct list_head *p;
 
        mutex_lock(&block_subsys_lock);
-       list_for_each(p, &block_subsys.kset.list)
+       list_for_each(p, &block_subsys.list)
                if (!k--)
                        return list_entry(p, struct gendisk, kobj.entry);
        return NULL;
@@ -575,7 +575,7 @@ static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos)
 {
        struct list_head *p = ((struct gendisk *)v)->kobj.entry.next;
        ++*pos;
-       return p==&block_subsys.kset.list ? NULL :
+       return p==&block_subsys.list ? NULL :
                list_entry(p, struct gendisk, kobj.entry);
 }
 
index 123003a..5873861 100644 (file)
@@ -1925,6 +1925,8 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
        blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS);
        blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
 
+       q->sg_reserved_size = INT_MAX;
+
        /*
         * all done
         */
index 65c6a3c..e83f1db 100644 (file)
@@ -78,7 +78,9 @@ static int sg_set_timeout(request_queue_t *q, int __user *p)
 
 static int sg_get_reserved_size(request_queue_t *q, int __user *p)
 {
-       return put_user(q->sg_reserved_size, p);
+       unsigned val = min(q->sg_reserved_size, q->max_sectors << 9);
+
+       return put_user(val, p);
 }
 
 static int sg_set_reserved_size(request_queue_t *q, int __user *p)
index 086fcec..620e14c 100644 (file)
@@ -16,6 +16,10 @@ config CRYPTO_ALGAPI
        help
          This option provides the API for cryptographic algorithms.
 
+config CRYPTO_ABLKCIPHER
+       tristate
+       select CRYPTO_BLKCIPHER
+
 config CRYPTO_BLKCIPHER
        tristate
        select CRYPTO_ALGAPI
@@ -171,6 +175,15 @@ config CRYPTO_LRW
          The first 128, 192 or 256 bits in the key are used for AES and the
          rest is used to tie each cipher block to its logical position.
 
+config CRYPTO_CRYPTD
+       tristate "Software async crypto daemon"
+       select CRYPTO_ABLKCIPHER
+       select CRYPTO_MANAGER
+       help
+         This is a generic software asynchronous crypto daemon that
+         converts an arbitrary synchronous software crypto algorithm
+         into an asynchronous algorithm that executes in a kernel thread.
+
 config CRYPTO_DES
        tristate "DES and Triple DES EDE cipher algorithms"
        select CRYPTO_ALGAPI
index 12f93f5..cce46a1 100644 (file)
@@ -8,6 +8,7 @@ crypto_algapi-$(CONFIG_PROC_FS) += proc.o
 crypto_algapi-objs := algapi.o $(crypto_algapi-y)
 obj-$(CONFIG_CRYPTO_ALGAPI) += crypto_algapi.o
 
+obj-$(CONFIG_CRYPTO_ABLKCIPHER) += ablkcipher.o
 obj-$(CONFIG_CRYPTO_BLKCIPHER) += blkcipher.o
 
 crypto_hash-objs := hash.o
@@ -29,6 +30,7 @@ obj-$(CONFIG_CRYPTO_ECB) += ecb.o
 obj-$(CONFIG_CRYPTO_CBC) += cbc.o
 obj-$(CONFIG_CRYPTO_PCBC) += pcbc.o
 obj-$(CONFIG_CRYPTO_LRW) += lrw.o
+obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o
 obj-$(CONFIG_CRYPTO_DES) += des.o
 obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o
 obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
new file mode 100644 (file)
index 0000000..9348ddd
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Asynchronous block chaining cipher operations.
+ * 
+ * This is the asynchronous version of blkcipher.c indicating completion
+ * via a callback.
+ *
+ * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ */
+
+#include <crypto/algapi.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+
+static int setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+                 unsigned int keylen)
+{
+       struct ablkcipher_alg *cipher = crypto_ablkcipher_alg(tfm);
+
+       if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) {
+               crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+               return -EINVAL;
+       }
+
+       return cipher->setkey(tfm, key, keylen);
+}
+
+static unsigned int crypto_ablkcipher_ctxsize(struct crypto_alg *alg, u32 type,
+                                             u32 mask)
+{
+       return alg->cra_ctxsize;
+}
+
+static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type,
+                                     u32 mask)
+{
+       struct ablkcipher_alg *alg = &tfm->__crt_alg->cra_ablkcipher;
+       struct ablkcipher_tfm *crt = &tfm->crt_ablkcipher;
+
+       if (alg->ivsize > PAGE_SIZE / 8)
+               return -EINVAL;
+
+       crt->setkey = setkey;
+       crt->encrypt = alg->encrypt;
+       crt->decrypt = alg->decrypt;
+       crt->ivsize = alg->ivsize;
+
+       return 0;
+}
+
+static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
+       __attribute__ ((unused));
+static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
+{
+       struct ablkcipher_alg *ablkcipher = &alg->cra_ablkcipher;
+
+       seq_printf(m, "type         : ablkcipher\n");
+       seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
+       seq_printf(m, "min keysize  : %u\n", ablkcipher->min_keysize);
+       seq_printf(m, "max keysize  : %u\n", ablkcipher->max_keysize);
+       seq_printf(m, "ivsize       : %u\n", ablkcipher->ivsize);
+       seq_printf(m, "qlen         : %u\n", ablkcipher->queue->qlen);
+       seq_printf(m, "max qlen     : %u\n", ablkcipher->queue->max_qlen);
+}
+
+const struct crypto_type crypto_ablkcipher_type = {
+       .ctxsize = crypto_ablkcipher_ctxsize,
+       .init = crypto_init_ablkcipher_ops,
+#ifdef CONFIG_PROC_FS
+       .show = crypto_ablkcipher_show,
+#endif
+};
+EXPORT_SYMBOL_GPL(crypto_ablkcipher_type);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Asynchronous block chaining cipher type");
index f7d2185..f137a43 100644 (file)
@@ -84,36 +84,47 @@ static void crypto_destroy_instance(struct crypto_alg *alg)
        crypto_tmpl_put(tmpl);
 }
 
-static void crypto_remove_spawns(struct list_head *spawns,
-                                struct list_head *list)
+static void crypto_remove_spawn(struct crypto_spawn *spawn,
+                               struct list_head *list,
+                               struct list_head *secondary_spawns)
 {
-       struct crypto_spawn *spawn, *n;
+       struct crypto_instance *inst = spawn->inst;
+       struct crypto_template *tmpl = inst->tmpl;
 
-       list_for_each_entry_safe(spawn, n, spawns, list) {
-               struct crypto_instance *inst = spawn->inst;
-               struct crypto_template *tmpl = inst->tmpl;
+       list_del_init(&spawn->list);
+       spawn->alg = NULL;
 
-               list_del_init(&spawn->list);
-               spawn->alg = NULL;
+       if (crypto_is_dead(&inst->alg))
+               return;
 
-               if (crypto_is_dead(&inst->alg))
-                       continue;
+       inst->alg.cra_flags |= CRYPTO_ALG_DEAD;
+       if (!tmpl || !crypto_tmpl_get(tmpl))
+               return;
 
-               inst->alg.cra_flags |= CRYPTO_ALG_DEAD;
-               if (!tmpl || !crypto_tmpl_get(tmpl))
+       crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, &inst->alg);
+       list_move(&inst->alg.cra_list, list);
+       hlist_del(&inst->list);
+       inst->alg.cra_destroy = crypto_destroy_instance;
+
+       list_splice(&inst->alg.cra_users, secondary_spawns);
+}
+
+static void crypto_remove_spawns(struct list_head *spawns,
+                                struct list_head *list, u32 new_type)
+{
+       struct crypto_spawn *spawn, *n;
+       LIST_HEAD(secondary_spawns);
+
+       list_for_each_entry_safe(spawn, n, spawns, list) {
+               if ((spawn->alg->cra_flags ^ new_type) & spawn->mask)
                        continue;
 
-               crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, &inst->alg);
-               list_move(&inst->alg.cra_list, list);
-               hlist_del(&inst->list);
-               inst->alg.cra_destroy = crypto_destroy_instance;
+               crypto_remove_spawn(spawn, list, &secondary_spawns);
+       }
 
-               if (!list_empty(&inst->alg.cra_users)) {
-                       if (&n->list == spawns)
-                               n = list_entry(inst->alg.cra_users.next,
-                                              typeof(*n), list);
-                       __list_splice(&inst->alg.cra_users, spawns->prev);
-               }
+       while (!list_empty(&secondary_spawns)) {
+               list_for_each_entry_safe(spawn, n, &secondary_spawns, list)
+                       crypto_remove_spawn(spawn, list, &secondary_spawns);
        }
 }
 
@@ -164,7 +175,7 @@ static int __crypto_register_alg(struct crypto_alg *alg,
                    q->cra_priority > alg->cra_priority)
                        continue;
 
-               crypto_remove_spawns(&q->cra_users, list);
+               crypto_remove_spawns(&q->cra_users, list, alg->cra_flags);
        }
        
        list_add(&alg->cra_list, &crypto_alg_list);
@@ -214,7 +225,7 @@ static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list)
 
        crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, alg);
        list_del_init(&alg->cra_list);
-       crypto_remove_spawns(&alg->cra_users, list);
+       crypto_remove_spawns(&alg->cra_users, list, alg->cra_flags);
 
        return 0;
 }
@@ -351,11 +362,12 @@ err:
 EXPORT_SYMBOL_GPL(crypto_register_instance);
 
 int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
-                     struct crypto_instance *inst)
+                     struct crypto_instance *inst, u32 mask)
 {
        int err = -EAGAIN;
 
        spawn->inst = inst;
+       spawn->mask = mask;
 
        down_write(&crypto_alg_sem);
        if (!crypto_is_moribund(alg)) {
@@ -425,15 +437,45 @@ int crypto_unregister_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL_GPL(crypto_unregister_notifier);
 
-struct crypto_alg *crypto_get_attr_alg(void *param, unsigned int len,
-                                      u32 type, u32 mask)
+struct crypto_attr_type *crypto_get_attr_type(struct rtattr **tb)
+{
+       struct rtattr *rta = tb[CRYPTOA_TYPE - 1];
+       struct crypto_attr_type *algt;
+
+       if (!rta)
+               return ERR_PTR(-ENOENT);
+       if (RTA_PAYLOAD(rta) < sizeof(*algt))
+               return ERR_PTR(-EINVAL);
+
+       algt = RTA_DATA(rta);
+
+       return algt;
+}
+EXPORT_SYMBOL_GPL(crypto_get_attr_type);
+
+int crypto_check_attr_type(struct rtattr **tb, u32 type)
 {
-       struct rtattr *rta = param;
+       struct crypto_attr_type *algt;
+
+       algt = crypto_get_attr_type(tb);
+       if (IS_ERR(algt))
+               return PTR_ERR(algt);
+
+       if ((algt->type ^ type) & algt->mask)
+               return -EINVAL;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(crypto_check_attr_type);
+
+struct crypto_alg *crypto_get_attr_alg(struct rtattr **tb, u32 type, u32 mask)
+{
+       struct rtattr *rta = tb[CRYPTOA_ALG - 1];
        struct crypto_attr_alg *alga;
 
-       if (!RTA_OK(rta, len))
-               return ERR_PTR(-EBADR);
-       if (rta->rta_type != CRYPTOA_ALG || RTA_PAYLOAD(rta) < sizeof(*alga))
+       if (!rta)
+               return ERR_PTR(-ENOENT);
+       if (RTA_PAYLOAD(rta) < sizeof(*alga))
                return ERR_PTR(-EINVAL);
 
        alga = RTA_DATA(rta);
@@ -464,7 +506,8 @@ struct crypto_instance *crypto_alloc_instance(const char *name,
                goto err_free_inst;
 
        spawn = crypto_instance_ctx(inst);
-       err = crypto_init_spawn(spawn, alg, inst);
+       err = crypto_init_spawn(spawn, alg, inst,
+                               CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
 
        if (err)
                goto err_free_inst;
@@ -477,6 +520,68 @@ err_free_inst:
 }
 EXPORT_SYMBOL_GPL(crypto_alloc_instance);
 
+void crypto_init_queue(struct crypto_queue *queue, unsigned int max_qlen)
+{
+       INIT_LIST_HEAD(&queue->list);
+       queue->backlog = &queue->list;
+       queue->qlen = 0;
+       queue->max_qlen = max_qlen;
+}
+EXPORT_SYMBOL_GPL(crypto_init_queue);
+
+int crypto_enqueue_request(struct crypto_queue *queue,
+                          struct crypto_async_request *request)
+{
+       int err = -EINPROGRESS;
+
+       if (unlikely(queue->qlen >= queue->max_qlen)) {
+               err = -EBUSY;
+               if (!(request->flags & CRYPTO_TFM_REQ_MAY_BACKLOG))
+                       goto out;
+               if (queue->backlog == &queue->list)
+                       queue->backlog = &request->list;
+       }
+
+       queue->qlen++;
+       list_add_tail(&request->list, &queue->list);
+
+out:
+       return err;
+}
+EXPORT_SYMBOL_GPL(crypto_enqueue_request);
+
+struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue)
+{
+       struct list_head *request;
+
+       if (unlikely(!queue->qlen))
+               return NULL;
+
+       queue->qlen--;
+
+       if (queue->backlog != &queue->list)
+               queue->backlog = queue->backlog->next;
+
+       request = queue->list.next;
+       list_del(request);
+
+       return list_entry(request, struct crypto_async_request, list);
+}
+EXPORT_SYMBOL_GPL(crypto_dequeue_request);
+
+int crypto_tfm_in_queue(struct crypto_queue *queue, struct crypto_tfm *tfm)
+{
+       struct crypto_async_request *req;
+
+       list_for_each_entry(req, &queue->list, list) {
+               if (req->tfm == tfm)
+                       return 1;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(crypto_tfm_in_queue);
+
 static int __init crypto_algapi_init(void)
 {
        crypto_init_proc();
index b5befe8..8edf40c 100644 (file)
@@ -349,13 +349,48 @@ static int setkey(struct crypto_tfm *tfm, const u8 *key,
        return cipher->setkey(tfm, key, keylen);
 }
 
+static int async_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+                       unsigned int keylen)
+{
+       return setkey(crypto_ablkcipher_tfm(tfm), key, keylen);
+}
+
+static int async_encrypt(struct ablkcipher_request *req)
+{
+       struct crypto_tfm *tfm = req->base.tfm;
+       struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
+       struct blkcipher_desc desc = {
+               .tfm = __crypto_blkcipher_cast(tfm),
+               .info = req->info,
+               .flags = req->base.flags,
+       };
+
+
+       return alg->encrypt(&desc, req->dst, req->src, req->nbytes);
+}
+
+static int async_decrypt(struct ablkcipher_request *req)
+{
+       struct crypto_tfm *tfm = req->base.tfm;
+       struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
+       struct blkcipher_desc desc = {
+               .tfm = __crypto_blkcipher_cast(tfm),
+               .info = req->info,
+               .flags = req->base.flags,
+       };
+
+       return alg->decrypt(&desc, req->dst, req->src, req->nbytes);
+}
+
 static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg, u32 type,
                                             u32 mask)
 {
        struct blkcipher_alg *cipher = &alg->cra_blkcipher;
        unsigned int len = alg->cra_ctxsize;
 
-       if (cipher->ivsize) {
+       type ^= CRYPTO_ALG_ASYNC;
+       mask &= CRYPTO_ALG_ASYNC;
+       if ((type & mask) && cipher->ivsize) {
                len = ALIGN(len, (unsigned long)alg->cra_alignmask + 1);
                len += cipher->ivsize;
        }
@@ -363,16 +398,26 @@ static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg, u32 type,
        return len;
 }
 
-static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
+static int crypto_init_blkcipher_ops_async(struct crypto_tfm *tfm)
+{
+       struct ablkcipher_tfm *crt = &tfm->crt_ablkcipher;
+       struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
+
+       crt->setkey = async_setkey;
+       crt->encrypt = async_encrypt;
+       crt->decrypt = async_decrypt;
+       crt->ivsize = alg->ivsize;
+
+       return 0;
+}
+
+static int crypto_init_blkcipher_ops_sync(struct crypto_tfm *tfm)
 {
        struct blkcipher_tfm *crt = &tfm->crt_blkcipher;
        struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
        unsigned long align = crypto_tfm_alg_alignmask(tfm) + 1;
        unsigned long addr;
 
-       if (alg->ivsize > PAGE_SIZE / 8)
-               return -EINVAL;
-
        crt->setkey = setkey;
        crt->encrypt = alg->encrypt;
        crt->decrypt = alg->decrypt;
@@ -385,8 +430,23 @@ static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
        return 0;
 }
 
+static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
+{
+       struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
+
+       if (alg->ivsize > PAGE_SIZE / 8)
+               return -EINVAL;
+
+       type ^= CRYPTO_ALG_ASYNC;
+       mask &= CRYPTO_ALG_ASYNC;
+       if (type & mask)
+               return crypto_init_blkcipher_ops_sync(tfm);
+       else
+               return crypto_init_blkcipher_ops_async(tfm);
+}
+
 static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
-       __attribute_used__;
+       __attribute__ ((unused));
 static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
 {
        seq_printf(m, "type         : blkcipher\n");
index 136fea7..1f2649e 100644 (file)
@@ -275,13 +275,18 @@ static void crypto_cbc_exit_tfm(struct crypto_tfm *tfm)
        crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *crypto_cbc_alloc(void *param, unsigned int len)
+static struct crypto_instance *crypto_cbc_alloc(struct rtattr **tb)
 {
        struct crypto_instance *inst;
        struct crypto_alg *alg;
+       int err;
+
+       err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+       if (err)
+               return ERR_PTR(err);
 
-       alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
-                                 CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+       alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+                                 CRYPTO_ALG_TYPE_MASK);
        if (IS_ERR(alg))
                return ERR_PTR(PTR_ERR(alg));
 
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
new file mode 100644 (file)
index 0000000..3ff4e1f
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * Software async crypto daemon.
+ *
+ * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#include <crypto/algapi.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/scatterlist.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#define CRYPTD_MAX_QLEN 100
+
+struct cryptd_state {
+       spinlock_t lock;
+       struct mutex mutex;
+       struct crypto_queue queue;
+       struct task_struct *task;
+};
+
+struct cryptd_instance_ctx {
+       struct crypto_spawn spawn;
+       struct cryptd_state *state;
+};
+
+struct cryptd_blkcipher_ctx {
+       struct crypto_blkcipher *child;
+};
+
+struct cryptd_blkcipher_request_ctx {
+       crypto_completion_t complete;
+};
+
+
+static inline struct cryptd_state *cryptd_get_state(struct crypto_tfm *tfm)
+{
+       struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
+       struct cryptd_instance_ctx *ictx = crypto_instance_ctx(inst);
+       return ictx->state;
+}
+
+static int cryptd_blkcipher_setkey(struct crypto_ablkcipher *parent,
+                                  const u8 *key, unsigned int keylen)
+{
+       struct cryptd_blkcipher_ctx *ctx = crypto_ablkcipher_ctx(parent);
+       struct crypto_blkcipher *child = ctx->child;
+       int err;
+
+       crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+       crypto_blkcipher_set_flags(child, crypto_ablkcipher_get_flags(parent) &
+                                         CRYPTO_TFM_REQ_MASK);
+       err = crypto_blkcipher_setkey(child, key, keylen);
+       crypto_ablkcipher_set_flags(parent, crypto_blkcipher_get_flags(child) &
+                                           CRYPTO_TFM_RES_MASK);
+       return err;
+}
+
+static void cryptd_blkcipher_crypt(struct ablkcipher_request *req,
+                                  struct crypto_blkcipher *child,
+                                  int err,
+                                  int (*crypt)(struct blkcipher_desc *desc,
+                                               struct scatterlist *dst,
+                                               struct scatterlist *src,
+                                               unsigned int len))
+{
+       struct cryptd_blkcipher_request_ctx *rctx;
+       struct blkcipher_desc desc;
+
+       rctx = ablkcipher_request_ctx(req);
+
+       if (unlikely(err == -EINPROGRESS)) {
+               rctx->complete(&req->base, err);
+               return;
+       }
+
+       desc.tfm = child;
+       desc.info = req->info;
+       desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+       err = crypt(&desc, req->dst, req->src, req->nbytes);
+
+       req->base.complete = rctx->complete;
+
+       local_bh_disable();
+       req->base.complete(&req->base, err);
+       local_bh_enable();
+}
+
+static void cryptd_blkcipher_encrypt(struct crypto_async_request *req, int err)
+{
+       struct cryptd_blkcipher_ctx *ctx = crypto_tfm_ctx(req->tfm);
+       struct crypto_blkcipher *child = ctx->child;
+
+       cryptd_blkcipher_crypt(ablkcipher_request_cast(req), child, err,
+                              crypto_blkcipher_crt(child)->encrypt);
+}
+
+static void cryptd_blkcipher_decrypt(struct crypto_async_request *req, int err)
+{
+       struct cryptd_blkcipher_ctx *ctx = crypto_tfm_ctx(req->tfm);
+       struct crypto_blkcipher *child = ctx->child;
+
+       cryptd_blkcipher_crypt(ablkcipher_request_cast(req), child, err,
+                              crypto_blkcipher_crt(child)->decrypt);
+}
+
+static int cryptd_blkcipher_enqueue(struct ablkcipher_request *req,
+                                   crypto_completion_t complete)
+{
+       struct cryptd_blkcipher_request_ctx *rctx = ablkcipher_request_ctx(req);
+       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+       struct cryptd_state *state =
+               cryptd_get_state(crypto_ablkcipher_tfm(tfm));
+       int err;
+
+       rctx->complete = req->base.complete;
+       req->base.complete = complete;
+
+       spin_lock_bh(&state->lock);
+       err = ablkcipher_enqueue_request(crypto_ablkcipher_alg(tfm), req);
+       spin_unlock_bh(&state->lock);
+
+       wake_up_process(state->task);
+       return err;
+}
+
+static int cryptd_blkcipher_encrypt_enqueue(struct ablkcipher_request *req)
+{
+       return cryptd_blkcipher_enqueue(req, cryptd_blkcipher_encrypt);
+}
+
+static int cryptd_blkcipher_decrypt_enqueue(struct ablkcipher_request *req)
+{
+       return cryptd_blkcipher_enqueue(req, cryptd_blkcipher_decrypt);
+}
+
+static int cryptd_blkcipher_init_tfm(struct crypto_tfm *tfm)
+{
+       struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
+       struct cryptd_instance_ctx *ictx = crypto_instance_ctx(inst);
+       struct crypto_spawn *spawn = &ictx->spawn;
+       struct cryptd_blkcipher_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct crypto_blkcipher *cipher;
+
+       cipher = crypto_spawn_blkcipher(spawn);
+       if (IS_ERR(cipher))
+               return PTR_ERR(cipher);
+
+       ctx->child = cipher;
+       tfm->crt_ablkcipher.reqsize =
+               sizeof(struct cryptd_blkcipher_request_ctx);
+       return 0;
+}
+
+static void cryptd_blkcipher_exit_tfm(struct crypto_tfm *tfm)
+{
+       struct cryptd_blkcipher_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct cryptd_state *state = cryptd_get_state(tfm);
+       int active;
+
+       mutex_lock(&state->mutex);
+       active = ablkcipher_tfm_in_queue(__crypto_ablkcipher_cast(tfm));
+       mutex_unlock(&state->mutex);
+
+       BUG_ON(active);
+
+       crypto_free_blkcipher(ctx->child);
+}
+
+static struct crypto_instance *cryptd_alloc_instance(struct crypto_alg *alg,
+                                                    struct cryptd_state *state)
+{
+       struct crypto_instance *inst;
+       struct cryptd_instance_ctx *ctx;
+       int err;
+
+       inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
+       if (IS_ERR(inst))
+               goto out;
+
+       err = -ENAMETOOLONG;
+       if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+                    "cryptd(%s)", alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
+               goto out_free_inst;
+
+       ctx = crypto_instance_ctx(inst);
+       err = crypto_init_spawn(&ctx->spawn, alg, inst,
+                               CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+       if (err)
+               goto out_free_inst;
+
+       ctx->state = state;
+
+       memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
+
+       inst->alg.cra_priority = alg->cra_priority + 50;
+       inst->alg.cra_blocksize = alg->cra_blocksize;
+       inst->alg.cra_alignmask = alg->cra_alignmask;
+
+out:
+       return inst;
+
+out_free_inst:
+       kfree(inst);
+       inst = ERR_PTR(err);
+       goto out;
+}
+
+static struct crypto_instance *cryptd_alloc_blkcipher(
+       struct rtattr **tb, struct cryptd_state *state)
+{
+       struct crypto_instance *inst;
+       struct crypto_alg *alg;
+
+       alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_BLKCIPHER,
+                                 CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+       if (IS_ERR(alg))
+               return ERR_PTR(PTR_ERR(alg));
+
+       inst = cryptd_alloc_instance(alg, state);
+       if (IS_ERR(inst))
+               goto out_put_alg;
+
+       inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | CRYPTO_ALG_ASYNC;
+       inst->alg.cra_type = &crypto_ablkcipher_type;
+
+       inst->alg.cra_ablkcipher.ivsize = alg->cra_blkcipher.ivsize;
+       inst->alg.cra_ablkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
+       inst->alg.cra_ablkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
+
+       inst->alg.cra_ctxsize = sizeof(struct cryptd_blkcipher_ctx);
+
+       inst->alg.cra_init = cryptd_blkcipher_init_tfm;
+       inst->alg.cra_exit = cryptd_blkcipher_exit_tfm;
+
+       inst->alg.cra_ablkcipher.setkey = cryptd_blkcipher_setkey;
+       inst->alg.cra_ablkcipher.encrypt = cryptd_blkcipher_encrypt_enqueue;
+       inst->alg.cra_ablkcipher.decrypt = cryptd_blkcipher_decrypt_enqueue;
+
+       inst->alg.cra_ablkcipher.queue = &state->queue;
+
+out_put_alg:
+       crypto_mod_put(alg);
+       return inst;
+}
+
+static struct cryptd_state state;
+
+static struct crypto_instance *cryptd_alloc(struct rtattr **tb)
+{
+       struct crypto_attr_type *algt;
+
+       algt = crypto_get_attr_type(tb);
+       if (IS_ERR(algt))
+               return ERR_PTR(PTR_ERR(algt));
+
+       switch (algt->type & algt->mask & CRYPTO_ALG_TYPE_MASK) {
+       case CRYPTO_ALG_TYPE_BLKCIPHER:
+               return cryptd_alloc_blkcipher(tb, &state);
+       }
+
+       return ERR_PTR(-EINVAL);
+}
+
+static void cryptd_free(struct crypto_instance *inst)
+{
+       struct cryptd_instance_ctx *ctx = crypto_instance_ctx(inst);
+
+       crypto_drop_spawn(&ctx->spawn);
+       kfree(inst);
+}
+
+static struct crypto_template cryptd_tmpl = {
+       .name = "cryptd",
+       .alloc = cryptd_alloc,
+       .free = cryptd_free,
+       .module = THIS_MODULE,
+};
+
+static inline int cryptd_create_thread(struct cryptd_state *state,
+                                      int (*fn)(void *data), const char *name)
+{
+       spin_lock_init(&state->lock);
+       mutex_init(&state->mutex);
+       crypto_init_queue(&state->queue, CRYPTD_MAX_QLEN);
+
+       state->task = kthread_create(fn, state, name);
+       if (IS_ERR(state->task))
+               return PTR_ERR(state->task);
+
+       return 0;
+}
+
+static inline void cryptd_stop_thread(struct cryptd_state *state)
+{
+       BUG_ON(state->queue.qlen);
+       kthread_stop(state->task);
+}
+
+static int cryptd_thread(void *data)
+{
+       struct cryptd_state *state = data;
+       int stop;
+
+       do {
+               struct crypto_async_request *req, *backlog;
+
+               mutex_lock(&state->mutex);
+               __set_current_state(TASK_INTERRUPTIBLE);
+
+               spin_lock_bh(&state->lock);
+               backlog = crypto_get_backlog(&state->queue);
+               req = crypto_dequeue_request(&state->queue);
+               spin_unlock_bh(&state->lock);
+
+               stop = kthread_should_stop();
+
+               if (stop || req) {
+                       __set_current_state(TASK_RUNNING);
+                       if (req) {
+                               if (backlog)
+                                       backlog->complete(backlog,
+                                                         -EINPROGRESS);
+                               req->complete(req, 0);
+                       }
+               }
+
+               mutex_unlock(&state->mutex);
+
+               schedule();
+       } while (!stop);
+
+       return 0;
+}
+
+static int __init cryptd_init(void)
+{
+       int err;
+
+       err = cryptd_create_thread(&state, cryptd_thread, "cryptd");
+       if (err)
+               return err;
+
+       err = crypto_register_template(&cryptd_tmpl);
+       if (err)
+               kthread_stop(state.task);
+
+       return err;
+}
+
+static void __exit cryptd_exit(void)
+{
+       cryptd_stop_thread(&state);
+       crypto_unregister_template(&cryptd_tmpl);
+}
+
+module_init(cryptd_init);
+module_exit(cryptd_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Software async crypto daemon");
index 2ebffb8..6958ea8 100644 (file)
 #include <linux/ctype.h>
 #include <linux/err.h>
 #include <linux/init.h>
+#include <linux/kthread.h>
 #include <linux/module.h>
 #include <linux/notifier.h>
 #include <linux/rtnetlink.h>
 #include <linux/sched.h>
 #include <linux/string.h>
-#include <linux/workqueue.h>
 
 #include "internal.h"
 
 struct cryptomgr_param {
-       struct work_struct work;
+       struct task_struct *thread;
+
+       struct rtattr *tb[CRYPTOA_MAX];
+
+       struct {
+               struct rtattr attr;
+               struct crypto_attr_type data;
+       } type;
 
        struct {
                struct rtattr attr;
@@ -32,18 +39,15 @@ struct cryptomgr_param {
        } alg;
 
        struct {
-               u32 type;
-               u32 mask;
                char name[CRYPTO_MAX_ALG_NAME];
        } larval;
 
        char template[CRYPTO_MAX_ALG_NAME];
 };
 
-static void cryptomgr_probe(struct work_struct *work)
+static int cryptomgr_probe(void *data)
 {
-       struct cryptomgr_param *param =
-               container_of(work, struct cryptomgr_param, work);
+       struct cryptomgr_param *param = data;
        struct crypto_template *tmpl;
        struct crypto_instance *inst;
        int err;
@@ -53,7 +57,7 @@ static void cryptomgr_probe(struct work_struct *work)
                goto err;
 
        do {
-               inst = tmpl->alloc(&param->alg, sizeof(param->alg));
+               inst = tmpl->alloc(param->tb);
                if (IS_ERR(inst))
                        err = PTR_ERR(inst);
                else if ((err = crypto_register_instance(tmpl, inst)))
@@ -67,11 +71,11 @@ static void cryptomgr_probe(struct work_struct *work)
 
 out:
        kfree(param);
-       return;
+       module_put_and_exit(0);
 
 err:
-       crypto_larval_error(param->larval.name, param->larval.type,
-                           param->larval.mask);
+       crypto_larval_error(param->larval.name, param->type.data.type,
+                           param->type.data.mask);
        goto out;
 }
 
@@ -82,10 +86,13 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval)
        const char *p;
        unsigned int len;
 
-       param = kmalloc(sizeof(*param), GFP_KERNEL);
-       if (!param)
+       if (!try_module_get(THIS_MODULE))
                goto err;
 
+       param = kzalloc(sizeof(*param), GFP_KERNEL);
+       if (!param)
+               goto err_put_module;
+
        for (p = name; isalnum(*p) || *p == '-' || *p == '_'; p++)
                ;
 
@@ -94,32 +101,45 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval)
                goto err_free_param;
 
        memcpy(param->template, name, len);
-       param->template[len] = 0;
 
        name = p + 1;
-       for (p = name; isalnum(*p) || *p == '-' || *p == '_'; p++)
-               ;
+       len = 0;
+       for (p = name; *p; p++) {
+               for (; isalnum(*p) || *p == '-' || *p == '_' || *p == '('; p++)
+                       ;
 
-       len = p - name;
-       if (!len || *p != ')' || p[1])
+               if (*p != ')')
+                       goto err_free_param;
+
+               len = p - name;
+       }
+
+       if (!len || name[len + 1])
                goto err_free_param;
 
+       param->type.attr.rta_len = sizeof(param->type);
+       param->type.attr.rta_type = CRYPTOA_TYPE;
+       param->type.data.type = larval->alg.cra_flags;
+       param->type.data.mask = larval->mask;
+       param->tb[CRYPTOA_TYPE - 1] = &param->type.attr;
+
        param->alg.attr.rta_len = sizeof(param->alg);
        param->alg.attr.rta_type = CRYPTOA_ALG;
        memcpy(param->alg.data.name, name, len);
-       param->alg.data.name[len] = 0;
+       param->tb[CRYPTOA_ALG - 1] = &param->alg.attr;
 
        memcpy(param->larval.name, larval->alg.cra_name, CRYPTO_MAX_ALG_NAME);
-       param->larval.type = larval->alg.cra_flags;
-       param->larval.mask = larval->mask;
 
-       INIT_WORK(&param->work, cryptomgr_probe);
-       schedule_work(&param->work);
+       param->thread = kthread_run(cryptomgr_probe, param, "cryptomgr");
+       if (IS_ERR(param->thread))
+               goto err_free_param;
 
        return NOTIFY_STOP;
 
 err_free_param:
        kfree(param);
+err_put_module:
+       module_put(THIS_MODULE);
 err:
        return NOTIFY_OK;
 }
index 839a0ae..6310387 100644 (file)
@@ -115,13 +115,18 @@ static void crypto_ecb_exit_tfm(struct crypto_tfm *tfm)
        crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *crypto_ecb_alloc(void *param, unsigned int len)
+static struct crypto_instance *crypto_ecb_alloc(struct rtattr **tb)
 {
        struct crypto_instance *inst;
        struct crypto_alg *alg;
+       int err;
+
+       err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+       if (err)
+               return ERR_PTR(err);
 
-       alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
-                                 CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+       alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+                                 CRYPTO_ALG_TYPE_MASK);
        if (IS_ERR(alg))
                return ERR_PTR(PTR_ERR(alg));
 
index 12c4514..4ccd22d 100644 (file)
@@ -41,7 +41,7 @@ static int crypto_init_hash_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
 }
 
 static void crypto_hash_show(struct seq_file *m, struct crypto_alg *alg)
-       __attribute_used__;
+       __attribute__ ((unused));
 static void crypto_hash_show(struct seq_file *m, struct crypto_alg *alg)
 {
        seq_printf(m, "type         : hash\n");
index 44187c5..8802fb6 100644 (file)
@@ -197,13 +197,18 @@ static void hmac_free(struct crypto_instance *inst)
        kfree(inst);
 }
 
-static struct crypto_instance *hmac_alloc(void *param, unsigned int len)
+static struct crypto_instance *hmac_alloc(struct rtattr **tb)
 {
        struct crypto_instance *inst;
        struct crypto_alg *alg;
+       int err;
+
+       err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_HASH);
+       if (err)
+               return ERR_PTR(err);
 
-       alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_HASH,
-                                 CRYPTO_ALG_TYPE_HASH_MASK | CRYPTO_ALG_ASYNC);
+       alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_HASH,
+                                 CRYPTO_ALG_TYPE_HASH_MASK);
        if (IS_ERR(alg))
                return ERR_PTR(PTR_ERR(alg));
 
index b410508..621095d 100644 (file)
@@ -228,13 +228,18 @@ static void exit_tfm(struct crypto_tfm *tfm)
        crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *alloc(void *param, unsigned int len)
+static struct crypto_instance *alloc(struct rtattr **tb)
 {
        struct crypto_instance *inst;
        struct crypto_alg *alg;
+       int err;
+
+       err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+       if (err)
+               return ERR_PTR(err);
 
-       alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
-                                 CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+       alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+                                 CRYPTO_ALG_TYPE_MASK);
        if (IS_ERR(alg))
                return ERR_PTR(PTR_ERR(alg));
 
index 5174d7f..c3ed8a1 100644 (file)
@@ -279,13 +279,18 @@ static void crypto_pcbc_exit_tfm(struct crypto_tfm *tfm)
        crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *crypto_pcbc_alloc(void *param, unsigned int len)
+static struct crypto_instance *crypto_pcbc_alloc(struct rtattr **tb)
 {
        struct crypto_instance *inst;
        struct crypto_alg *alg;
+       int err;
+
+       err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+       if (err)
+               return ERR_PTR(err);
 
-       alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
-                                 CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+       alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+                                 CRYPTO_ALG_TYPE_MASK);
        if (IS_ERR(alg))
                return ERR_PTR(PTR_ERR(alg));
 
index 8eaa5aa..f0aed01 100644 (file)
 #define ENCRYPT 1
 #define DECRYPT 0
 
+struct tcrypt_result {
+       struct completion completion;
+       int err;
+};
+
 static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 };
 
 /*
@@ -84,6 +89,17 @@ static void hexdump(unsigned char *buf, unsigned int len)
        printk("\n");
 }
 
+static void tcrypt_complete(struct crypto_async_request *req, int err)
+{
+       struct tcrypt_result *res = req->data;
+
+       if (err == -EINPROGRESS)
+               return;
+
+       res->err = err;
+       complete(&res->completion);
+}
+
 static void test_hash(char *algo, struct hash_testvec *template,
                      unsigned int tcount)
 {
@@ -203,15 +219,14 @@ static void test_cipher(char *algo, int enc,
 {
        unsigned int ret, i, j, k, temp;
        unsigned int tsize;
-       unsigned int iv_len;
-       unsigned int len;
        char *q;
-       struct crypto_blkcipher *tfm;
+       struct crypto_ablkcipher *tfm;
        char *key;
        struct cipher_testvec *cipher_tv;
-       struct blkcipher_desc desc;
+       struct ablkcipher_request *req;
        struct scatterlist sg[8];
        const char *e;
+       struct tcrypt_result result;
 
        if (enc == ENCRYPT)
                e = "encryption";
@@ -232,15 +247,24 @@ static void test_cipher(char *algo, int enc,
        memcpy(tvmem, template, tsize);
        cipher_tv = (void *)tvmem;
 
-       tfm = crypto_alloc_blkcipher(algo, 0, CRYPTO_ALG_ASYNC);
+       init_completion(&result.completion);
+
+       tfm = crypto_alloc_ablkcipher(algo, 0, 0);
 
        if (IS_ERR(tfm)) {
                printk("failed to load transform for %s: %ld\n", algo,
                       PTR_ERR(tfm));
                return;
        }
-       desc.tfm = tfm;
-       desc.flags = 0;
+
+       req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
+       if (!req) {
+               printk("failed to allocate request for %s\n", algo);
+               goto out;
+       }
+
+       ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+                                       tcrypt_complete, &result);
 
        j = 0;
        for (i = 0; i < tcount; i++) {
@@ -249,17 +273,17 @@ static void test_cipher(char *algo, int enc,
                        printk("test %u (%d bit key):\n",
                        j, cipher_tv[i].klen * 8);
 
-                       crypto_blkcipher_clear_flags(tfm, ~0);
+                       crypto_ablkcipher_clear_flags(tfm, ~0);
                        if (cipher_tv[i].wk)
-                               crypto_blkcipher_set_flags(
+                               crypto_ablkcipher_set_flags(
                                        tfm, CRYPTO_TFM_REQ_WEAK_KEY);
                        key = cipher_tv[i].key;
 
-                       ret = crypto_blkcipher_setkey(tfm, key,
-                                                     cipher_tv[i].klen);
+                       ret = crypto_ablkcipher_setkey(tfm, key,
+                                                      cipher_tv[i].klen);
                        if (ret) {
                                printk("setkey() failed flags=%x\n",
-                                      crypto_blkcipher_get_flags(tfm));
+                                      crypto_ablkcipher_get_flags(tfm));
 
                                if (!cipher_tv[i].fail)
                                        goto out;
@@ -268,19 +292,28 @@ static void test_cipher(char *algo, int enc,
                        sg_set_buf(&sg[0], cipher_tv[i].input,
                                   cipher_tv[i].ilen);
 
-                       iv_len = crypto_blkcipher_ivsize(tfm);
-                       if (iv_len)
-                               crypto_blkcipher_set_iv(tfm, cipher_tv[i].iv,
-                                                       iv_len);
+                       ablkcipher_request_set_crypt(req, sg, sg,
+                                                    cipher_tv[i].ilen,
+                                                    cipher_tv[i].iv);
 
-                       len = cipher_tv[i].ilen;
                        ret = enc ?
-                               crypto_blkcipher_encrypt(&desc, sg, sg, len) :
-                               crypto_blkcipher_decrypt(&desc, sg, sg, len);
+                               crypto_ablkcipher_encrypt(req) :
+                               crypto_ablkcipher_decrypt(req);
 
-                       if (ret) {
-                               printk("%s () failed flags=%x\n", e,
-                                      desc.flags);
+                       switch (ret) {
+                       case 0:
+                               break;
+                       case -EINPROGRESS:
+                       case -EBUSY:
+                               ret = wait_for_completion_interruptible(
+                                       &result.completion);
+                               if (!ret && !((ret = result.err))) {
+                                       INIT_COMPLETION(result.completion);
+                                       break;
+                               }
+                               /* fall through */
+                       default:
+                               printk("%s () failed err=%d\n", e, -ret);
                                goto out;
                        }
 
@@ -303,17 +336,17 @@ static void test_cipher(char *algo, int enc,
                        printk("test %u (%d bit key):\n",
                        j, cipher_tv[i].klen * 8);
 
-                       crypto_blkcipher_clear_flags(tfm, ~0);
+                       crypto_ablkcipher_clear_flags(tfm, ~0);
                        if (cipher_tv[i].wk)
-                               crypto_blkcipher_set_flags(
+                               crypto_ablkcipher_set_flags(
                                        tfm, CRYPTO_TFM_REQ_WEAK_KEY);
                        key = cipher_tv[i].key;
 
-                       ret = crypto_blkcipher_setkey(tfm, key,
-                                                     cipher_tv[i].klen);
+                       ret = crypto_ablkcipher_setkey(tfm, key,
+                                                      cipher_tv[i].klen);
                        if (ret) {
                                printk("setkey() failed flags=%x\n",
-                                      crypto_blkcipher_get_flags(tfm));
+                                      crypto_ablkcipher_get_flags(tfm));
 
                                if (!cipher_tv[i].fail)
                                        goto out;
@@ -329,19 +362,28 @@ static void test_cipher(char *algo, int enc,
                                           cipher_tv[i].tap[k]);
                        }
 
-                       iv_len = crypto_blkcipher_ivsize(tfm);
-                       if (iv_len)
-                               crypto_blkcipher_set_iv(tfm, cipher_tv[i].iv,
-                                                       iv_len);
+                       ablkcipher_request_set_crypt(req, sg, sg,
+                                                    cipher_tv[i].ilen,
+                                                    cipher_tv[i].iv);
 
-                       len = cipher_tv[i].ilen;
                        ret = enc ?
-                               crypto_blkcipher_encrypt(&desc, sg, sg, len) :
-                               crypto_blkcipher_decrypt(&desc, sg, sg, len);
+                               crypto_ablkcipher_encrypt(req) :
+                               crypto_ablkcipher_decrypt(req);
 
-                       if (ret) {
-                               printk("%s () failed flags=%x\n", e,
-                                      desc.flags);
+                       switch (ret) {
+                       case 0:
+                               break;
+                       case -EINPROGRESS:
+                       case -EBUSY:
+                               ret = wait_for_completion_interruptible(
+                                       &result.completion);
+                               if (!ret && !((ret = result.err))) {
+                                       INIT_COMPLETION(result.completion);
+                                       break;
+                               }
+                               /* fall through */
+                       default:
+                               printk("%s () failed err=%d\n", e, -ret);
                                goto out;
                        }
 
@@ -360,7 +402,8 @@ static void test_cipher(char *algo, int enc,
        }
 
 out:
-       crypto_free_blkcipher(tfm);
+       crypto_free_ablkcipher(tfm);
+       ablkcipher_request_free(req);
 }
 
 static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc, char *p,
@@ -832,7 +875,7 @@ static void test_available(void)
 
        while (*name) {
                printk("alg %s ", *name);
-               printk(crypto_has_alg(*name, 0, CRYPTO_ALG_ASYNC) ?
+               printk(crypto_has_alg(*name, 0, 0) ?
                       "found\n" : "not found\n");
                name++;
        }
index 53e8ccb..9f502b8 100644 (file)
@@ -288,12 +288,18 @@ static void xcbc_exit_tfm(struct crypto_tfm *tfm)
        crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *xcbc_alloc(void *param, unsigned int len)
+static struct crypto_instance *xcbc_alloc(struct rtattr **tb)
 {
        struct crypto_instance *inst;
        struct crypto_alg *alg;
-       alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
-                                 CRYPTO_ALG_TYPE_HASH_MASK | CRYPTO_ALG_ASYNC);
+       int err;
+
+       err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_HASH);
+       if (err)
+               return ERR_PTR(err);
+
+       alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
+                                 CRYPTO_ALG_TYPE_MASK);
        if (IS_ERR(alg))
                return ERR_PTR(PTR_ERR(alg));
 
index 920c975..26ca903 100644 (file)
@@ -58,7 +58,7 @@ obj-$(CONFIG_GAMEPORT)                += input/gameport/
 obj-$(CONFIG_INPUT)            += input/
 obj-$(CONFIG_I2O)              += message/
 obj-$(CONFIG_RTC_LIB)          += rtc/
-obj-$(CONFIG_I2C)              += i2c/
+obj-y                          += i2c/
 obj-$(CONFIG_W1)               += w1/
 obj-$(CONFIG_HWMON)            += hwmon/
 obj-$(CONFIG_PHONE)            += telephony/
index 2f2e796..c4efc0c 100644 (file)
@@ -433,49 +433,6 @@ static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file)
                           PDE(inode)->data);
 }
 
-static ssize_t
-acpi_processor_write_performance(struct file *file,
-                                const char __user * buffer,
-                                size_t count, loff_t * data)
-{
-       int result = 0;
-       struct seq_file *m = file->private_data;
-       struct acpi_processor *pr = m->private;
-       struct acpi_processor_performance *perf;
-       char state_string[12] = { '\0' };
-       unsigned int new_state = 0;
-       struct cpufreq_policy policy;
-
-
-       if (!pr || (count > sizeof(state_string) - 1))
-               return -EINVAL;
-
-       perf = pr->performance;
-       if (!perf)
-               return -EINVAL;
-
-       if (copy_from_user(state_string, buffer, count))
-               return -EFAULT;
-
-       state_string[count] = '\0';
-       new_state = simple_strtoul(state_string, NULL, 0);
-
-       if (new_state >= perf->state_count)
-               return -EINVAL;
-
-       cpufreq_get_policy(&policy, pr->id);
-
-       policy.cpu = pr->id;
-       policy.min = perf->states[new_state].core_frequency * 1000;
-       policy.max = perf->states[new_state].core_frequency * 1000;
-
-       result = cpufreq_set_policy(&policy);
-       if (result)
-               return result;
-
-       return count;
-}
-
 static void acpi_cpufreq_add_file(struct acpi_processor *pr)
 {
        struct proc_dir_entry *entry = NULL;
@@ -487,10 +444,9 @@ static void acpi_cpufreq_add_file(struct acpi_processor *pr)
 
        /* add file 'performance' [R/W] */
        entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
-                                 S_IFREG | S_IRUGO | S_IWUSR,
+                                 S_IFREG | S_IRUGO,
                                  acpi_device_dir(device));
        if (entry){
-               acpi_processor_perf_fops.write = acpi_processor_write_performance;
                entry->proc_fops = &acpi_processor_perf_fops;
                entry->data = acpi_driver_data(device);
                entry->owner = THIS_MODULE;
index 8d60c4e..2ebd07f 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
-#include <linux/pci.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/string.h>
index d597f26..5512d84 100644 (file)
@@ -45,3 +45,5 @@ struct class_device_attribute *to_class_dev_attr(struct attribute *_attr)
 extern char *make_class_name(const char *name, struct kobject *kobj);
 
 extern void devres_release_all(struct device *dev);
+
+extern struct kset devices_subsys;
index 1d76e23..dca7348 100644 (file)
@@ -17,7 +17,7 @@
 #include "power/power.h"
 
 #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr)
-#define to_bus(obj) container_of(obj, struct bus_type, subsys.kset.kobj)
+#define to_bus(obj) container_of(obj, struct bus_type, subsys.kobj)
 
 /*
  * sysfs bindings for drivers
@@ -123,7 +123,7 @@ int bus_create_file(struct bus_type * bus, struct bus_attribute * attr)
 {
        int error;
        if (get_bus(bus)) {
-               error = sysfs_create_file(&bus->subsys.kset.kobj, &attr->attr);
+               error = sysfs_create_file(&bus->subsys.kobj, &attr->attr);
                put_bus(bus);
        } else
                error = -EINVAL;
@@ -133,7 +133,7 @@ int bus_create_file(struct bus_type * bus, struct bus_attribute * attr)
 void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
 {
        if (get_bus(bus)) {
-               sysfs_remove_file(&bus->subsys.kset.kobj, &attr->attr);
+               sysfs_remove_file(&bus->subsys.kobj, &attr->attr);
                put_bus(bus);
        }
 }
@@ -397,7 +397,7 @@ static void device_remove_attrs(struct bus_type * bus, struct device * dev)
 static int make_deprecated_bus_links(struct device *dev)
 {
        return sysfs_create_link(&dev->kobj,
-                                &dev->bus->subsys.kset.kobj, "bus");
+                                &dev->bus->subsys.kobj, "bus");
 }
 
 static void remove_deprecated_bus_links(struct device *dev)
@@ -431,7 +431,7 @@ int bus_add_device(struct device * dev)
                if (error)
                        goto out_id;
                error = sysfs_create_link(&dev->kobj,
-                               &dev->bus->subsys.kset.kobj, "subsystem");
+                               &dev->bus->subsys.kobj, "subsystem");
                if (error)
                        goto out_subsys;
                error = make_deprecated_bus_links(dev);
@@ -810,7 +810,7 @@ int bus_register(struct bus_type * bus)
 
        BLOCKING_INIT_NOTIFIER_HEAD(&bus->bus_notifier);
 
-       retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name);
+       retval = kobject_set_name(&bus->subsys.kobj, "%s", bus->name);
        if (retval)
                goto out;
 
@@ -820,13 +820,13 @@ int bus_register(struct bus_type * bus)
                goto out;
 
        kobject_set_name(&bus->devices.kobj, "devices");
-       bus->devices.subsys = &bus->subsys;
+       bus->devices.kobj.parent = &bus->subsys.kobj;
        retval = kset_register(&bus->devices);
        if (retval)
                goto bus_devices_fail;
 
        kobject_set_name(&bus->drivers.kobj, "drivers");
-       bus->drivers.subsys = &bus->subsys;
+       bus->drivers.kobj.parent = &bus->subsys.kobj;
        bus->drivers.ktype = &ktype_driver;
        retval = kset_register(&bus->drivers);
        if (retval)
index 80bbb20..20c4ea6 100644 (file)
 #include <linux/slab.h>
 #include "base.h"
 
-extern struct subsystem devices_subsys;
-
 #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
-#define to_class(obj) container_of(obj, struct class, subsys.kset.kobj)
+#define to_class(obj) container_of(obj, struct class, subsys.kobj)
 
 static ssize_t
 class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
@@ -80,7 +78,7 @@ int class_create_file(struct class * cls, const struct class_attribute * attr)
 {
        int error;
        if (cls) {
-               error = sysfs_create_file(&cls->subsys.kset.kobj, &attr->attr);
+               error = sysfs_create_file(&cls->subsys.kobj, &attr->attr);
        } else
                error = -EINVAL;
        return error;
@@ -89,7 +87,7 @@ int class_create_file(struct class * cls, const struct class_attribute * attr)
 void class_remove_file(struct class * cls, const struct class_attribute * attr)
 {
        if (cls)
-               sysfs_remove_file(&cls->subsys.kset.kobj, &attr->attr);
+               sysfs_remove_file(&cls->subsys.kobj, &attr->attr);
 }
 
 static struct class *class_get(struct class *cls)
@@ -147,7 +145,7 @@ int class_register(struct class * cls)
        INIT_LIST_HEAD(&cls->interfaces);
        kset_init(&cls->class_dirs);
        init_MUTEX(&cls->sem);
-       error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name);
+       error = kobject_set_name(&cls->subsys.kobj, "%s", cls->name);
        if (error)
                return error;
 
@@ -611,7 +609,7 @@ int class_device_add(struct class_device *class_dev)
        if (parent_class_dev)
                class_dev->kobj.parent = &parent_class_dev->kobj;
        else
-               class_dev->kobj.parent = &parent_class->subsys.kset.kobj;
+               class_dev->kobj.parent = &parent_class->subsys.kobj;
 
        error = kobject_add(&class_dev->kobj);
        if (error)
@@ -619,7 +617,7 @@ int class_device_add(struct class_device *class_dev)
 
        /* add the needed attributes to this device */
        error = sysfs_create_link(&class_dev->kobj,
-                                 &parent_class->subsys.kset.kobj, "subsystem");
+                                 &parent_class->subsys.kobj, "subsystem");
        if (error)
                goto out3;
        class_dev->uevent_attr.attr.name = "uevent";
@@ -917,8 +915,8 @@ int __init classes_init(void)
        /* ick, this is ugly, the things we go through to keep from showing up
         * in sysfs... */
        subsystem_init(&class_obj_subsys);
-       if (!class_obj_subsys.kset.subsys)
-                       class_obj_subsys.kset.subsys = &class_obj_subsys;
+       if (!class_obj_subsys.kobj.parent)
+               class_obj_subsys.kobj.parent = &class_obj_subsys.kobj;
        return 0;
 }
 
index 8aa090d..b78fc1e 100644 (file)
@@ -252,7 +252,7 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr,
        struct kobject *top_kobj;
        struct kset *kset;
        char *envp[32];
-       char data[PAGE_SIZE];
+       char *data = NULL;
        char *pos;
        int i;
        size_t count = 0;
@@ -276,6 +276,10 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr,
                if (!kset->uevent_ops->filter(kset, &dev->kobj))
                        goto out;
 
+       data = (char *)get_zeroed_page(GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
        /* let the kset specific function add its keys */
        pos = data;
        retval = kset->uevent_ops->uevent(kset, &dev->kobj,
@@ -290,6 +294,7 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr,
                count += sprintf(pos, "%s\n", envp[i]);
        }
 out:
+       free_page((unsigned long)data);
        return count;
 }
 
@@ -560,7 +565,7 @@ static struct kobject * get_device_parent(struct device *dev,
        /* Set the parent to the class, not the parent device */
        /* this keeps sysfs from having a symlink to make old udevs happy */
        if (dev->class)
-               return &dev->class->subsys.kset.kobj;
+               return &dev->class->subsys.kobj;
        else if (parent)
                return &parent->kobj;
 
@@ -572,7 +577,7 @@ static struct kobject *virtual_device_parent(struct device *dev)
        static struct kobject *virtual_dir = NULL;
 
        if (!virtual_dir)
-               virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual");
+               virtual_dir = kobject_add_dir(&devices_subsys.kobj, "virtual");
 
        return virtual_dir;
 }
@@ -706,12 +711,12 @@ int device_add(struct device *dev)
        }
 
        if (dev->class) {
-               sysfs_create_link(&dev->kobj, &dev->class->subsys.kset.kobj,
+               sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj,
                                  "subsystem");
                /* If this is not a "fake" compatible device, then create the
                 * symlink from the class to the device. */
-               if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
-                       sysfs_create_link(&dev->class->subsys.kset.kobj,
+               if (dev->kobj.parent != &dev->class->subsys.kobj)
+                       sysfs_create_link(&dev->class->subsys.kobj,
                                          &dev->kobj, dev->bus_id);
                if (parent) {
                        sysfs_create_link(&dev->kobj, &dev->parent->kobj,
@@ -769,8 +774,8 @@ int device_add(struct device *dev)
                sysfs_remove_link(&dev->kobj, "subsystem");
                /* If this is not a "fake" compatible device, remove the
                 * symlink from the class to the device. */
-               if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
-                       sysfs_remove_link(&dev->class->subsys.kset.kobj,
+               if (dev->kobj.parent != &dev->class->subsys.kobj)
+                       sysfs_remove_link(&dev->class->subsys.kobj,
                                          dev->bus_id);
                if (parent) {
 #ifdef CONFIG_SYSFS_DEPRECATED
@@ -870,8 +875,8 @@ void device_del(struct device * dev)
                sysfs_remove_link(&dev->kobj, "subsystem");
                /* If this is not a "fake" compatible device, remove the
                 * symlink from the class to the device. */
-               if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
-                       sysfs_remove_link(&dev->class->subsys.kset.kobj,
+               if (dev->kobj.parent != &dev->class->subsys.kobj)
+                       sysfs_remove_link(&dev->class->subsys.kobj,
                                          dev->bus_id);
                if (parent) {
 #ifdef CONFIG_SYSFS_DEPRECATED
@@ -1187,9 +1192,9 @@ int device_rename(struct device *dev, char *new_name)
 #endif
 
        if (dev->class) {
-               sysfs_remove_link(&dev->class->subsys.kset.kobj,
+               sysfs_remove_link(&dev->class->subsys.kobj,
                                  old_symlink_name);
-               sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj,
+               sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
                                  dev->bus_id);
        }
        put_device(dev);
index 18dba8e..92428e5 100644 (file)
@@ -226,12 +226,10 @@ static int device_probe_drivers(void *data)
  *
  *     Walk the list of drivers that the bus has and call
  *     driver_probe_device() for each pair. If a compatible
- *     pair is found, break out and return. If the bus specifies
- *     multithreaded probing, walking the list of drivers is done
- *     on a probing thread.
+ *     pair is found, break out and return.
  *
  *     Returns 1 if the device was bound to a driver;
- *     0 if no matching device was found or multithreaded probing is done;
+ *     0 if no matching device was found;
  *     -ENODEV if the device is not registered.
  *
  *     When called for a USB interface, @dev->parent->sem must be held.
@@ -239,7 +237,6 @@ static int device_probe_drivers(void *data)
 int device_attach(struct device * dev)
 {
        int ret = 0;
-       struct task_struct *probe_task = ERR_PTR(-ENOMEM);
 
        down(&dev->sem);
        if (dev->driver) {
@@ -251,12 +248,7 @@ int device_attach(struct device * dev)
                        ret = 0;
                }
        } else {
-               if (dev->bus->multithread_probe)
-                       probe_task = kthread_run(device_probe_drivers, dev,
-                                                "probe-%s", dev->bus_id);
-               if(IS_ERR(probe_task))
-                       ret = bus_for_each_drv(dev->bus, NULL, dev,
-                                              __device_attach);
+               ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
        }
        up(&dev->sem);
        return ret;
@@ -383,33 +375,6 @@ void driver_detach(struct device_driver * drv)
        }
 }
 
-#ifdef CONFIG_PCI_MULTITHREAD_PROBE
-static int __init wait_for_probes(void)
-{
-       DEFINE_WAIT(wait);
-
-       printk(KERN_INFO "%s: waiting for %d threads\n", __FUNCTION__,
-                       atomic_read(&probe_count));
-       if (!atomic_read(&probe_count))
-               return 0;
-       while (atomic_read(&probe_count)) {
-               prepare_to_wait(&probe_waitqueue, &wait, TASK_UNINTERRUPTIBLE);
-               if (atomic_read(&probe_count))
-                       schedule();
-       }
-       finish_wait(&probe_waitqueue, &wait);
-       return 0;
-}
-
-core_initcall_sync(wait_for_probes);
-postcore_initcall_sync(wait_for_probes);
-arch_initcall_sync(wait_for_probes);
-subsys_initcall_sync(wait_for_probes);
-fs_initcall_sync(wait_for_probes);
-device_initcall_sync(wait_for_probes);
-late_initcall_sync(wait_for_probes);
-#endif
-
 EXPORT_SYMBOL_GPL(device_bind_driver);
 EXPORT_SYMBOL_GPL(device_release_driver);
 EXPORT_SYMBOL_GPL(device_attach);
index cb1b98a..90c8629 100644 (file)
 
 static decl_subsys(firmware, NULL, NULL);
 
-int firmware_register(struct subsystem * s)
+int firmware_register(struct kset *s)
 {
-       kset_set_kset_s(s, firmware_subsys);
+       kobj_set_kset_s(s, firmware_subsys);
        return subsystem_register(s);
 }
 
-void firmware_unregister(struct subsystem * s)
+void firmware_unregister(struct kset *s)
 {
        subsystem_unregister(s);
 }
index 30480f6..17b5ece 100644 (file)
@@ -292,20 +292,22 @@ EXPORT_SYMBOL_GPL(platform_device_add);
  *     @pdev:  platform device we're removing
  *
  *     Note that this function will also release all memory- and port-based
- *     resources owned by the device (@dev->resource).
+ *     resources owned by the device (@dev->resource).  This function
+ *     must _only_ be externally called in error cases.  All other usage
+ *     is a bug.
  */
 void platform_device_del(struct platform_device *pdev)
 {
        int i;
 
        if (pdev) {
+               device_del(&pdev->dev);
+
                for (i = 0; i < pdev->num_resources; i++) {
                        struct resource *r = &pdev->resource[i];
                        if (r->flags & (IORESOURCE_MEM|IORESOURCE_IO))
                                release_resource(r);
                }
-
-               device_del(&pdev->dev);
        }
 }
 EXPORT_SYMBOL_GPL(platform_device_del);
index 58b6f77..a47ee1b 100644 (file)
@@ -16,8 +16,6 @@
 
 #define to_dev(node) container_of(node, struct device, kobj.entry)
 
-extern struct subsystem devices_subsys;
-
 
 /**
  * We handle system devices differently - we suspend and shut them
@@ -36,7 +34,7 @@ void device_shutdown(void)
 {
        struct device * dev, *devn;
 
-       list_for_each_entry_safe_reverse(dev, devn, &devices_subsys.kset.list,
+       list_for_each_entry_safe_reverse(dev, devn, &devices_subsys.list,
                                kobj.entry) {
                if (dev->bus && dev->bus->shutdown) {
                        dev_dbg(dev, "shutdown\n");
index 04e5db4..29f1291 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "base.h"
 
-extern struct subsystem devices_subsys;
+extern struct kset devices_subsys;
 
 #define to_sysdev(k) container_of(k, struct sys_device, kobj)
 #define to_sysdev_attr(a) container_of(a, struct sysdev_attribute, attr)
@@ -138,7 +138,7 @@ int sysdev_class_register(struct sysdev_class * cls)
        pr_debug("Registering sysdev class '%s'\n",
                 kobject_name(&cls->kset.kobj));
        INIT_LIST_HEAD(&cls->drivers);
-       cls->kset.subsys = &system_subsys;
+       cls->kset.kobj.parent = &system_subsys.kobj;
        kset_set_kset_s(cls, system_subsys);
        return kset_register(&cls->kset);
 }
@@ -309,7 +309,7 @@ void sysdev_shutdown(void)
        pr_debug("Shutting Down System Devices\n");
 
        down(&sysdev_drivers_lock);
-       list_for_each_entry_reverse(cls, &system_subsys.kset.list,
+       list_for_each_entry_reverse(cls, &system_subsys.list,
                                    kset.kobj.entry) {
                struct sys_device * sysdev;
 
@@ -384,7 +384,7 @@ int sysdev_suspend(pm_message_t state)
 
        pr_debug("Suspending System Devices\n");
 
-       list_for_each_entry_reverse(cls, &system_subsys.kset.list,
+       list_for_each_entry_reverse(cls, &system_subsys.list,
                                    kset.kobj.entry) {
 
                pr_debug("Suspending type '%s':\n",
@@ -457,7 +457,7 @@ gbl_driver:
        }
 
        /* resume other classes */
-       list_for_each_entry_continue(cls, &system_subsys.kset.list,
+       list_for_each_entry_continue(cls, &system_subsys.list,
                                        kset.kobj.entry) {
                list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
                        pr_debug(" %s\n", kobject_name(&err_dev->kobj));
@@ -483,7 +483,7 @@ int sysdev_resume(void)
 
        pr_debug("Resuming System Devices\n");
 
-       list_for_each_entry(cls, &system_subsys.kset.list, kset.kobj.entry) {
+       list_for_each_entry(cls, &system_subsys.list, kset.kobj.entry) {
                struct sys_device * sysdev;
 
                pr_debug("Resuming type '%s':\n",
@@ -501,7 +501,7 @@ int sysdev_resume(void)
 
 int __init system_bus_init(void)
 {
-       system_subsys.kset.kobj.parent = &devices_subsys.kset.kobj;
+       system_subsys.kobj.parent = &devices_subsys.kobj;
        return subsystem_register(&system_subsys);
 }
 
index 1a6aeac..01fbdd3 100644 (file)
@@ -194,15 +194,15 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail)
        sl = sl_tail = NULL;
 
        read_lock(&dev_base_lock);
-       for (ifp = dev_base; ifp; dev_put(ifp), ifp = ifp->next) {
+       for_each_netdev(ifp) {
                dev_hold(ifp);
                if (!is_aoe_netif(ifp))
-                       continue;
+                       goto cont;
 
                skb = new_skb(sizeof *h + sizeof *ch);
                if (skb == NULL) {
                        printk(KERN_INFO "aoe: skb alloc failure\n");
-                       continue;
+                       goto cont;
                }
                skb_put(skb, sizeof *h + sizeof *ch);
                skb->dev = ifp;
@@ -221,6 +221,8 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail)
 
                skb->next = sl;
                sl = skb;
+cont:
+               dev_put(ifp);
        }
        read_unlock(&dev_base_lock);
 
index 5b684fd..4941ddb 100644 (file)
@@ -145,6 +145,7 @@ static void *m1541_alloc_page(struct agp_bridge_data *bridge)
        void *addr = agp_generic_alloc_page(agp_bridge);
        u32 temp;
 
+       global_flush_tlb();
        if (!addr)
                return NULL;
 
@@ -160,6 +161,7 @@ static void ali_destroy_page(void * addr)
        if (addr) {
                global_cache_flush();   /* is this really needed?  --hch */
                agp_generic_destroy_page(addr);
+               global_flush_tlb();
        }
 }
 
index b0acf41..aa8f3a3 100644 (file)
@@ -173,7 +173,7 @@ alpha_core_agp_setup(void)
        /*
         * Build a fake pci_dev struct
         */
-       pdev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
+       pdev = alloc_pci_dev();
        if (!pdev)
                return -ENOMEM;
        pdev->vendor = 0xffff;
index f902d71..45aeb91 100644 (file)
@@ -51,28 +51,6 @@ int agp_memory_reserved;
  */
 EXPORT_SYMBOL_GPL(agp_memory_reserved);
 
-#if defined(CONFIG_X86)
-int map_page_into_agp(struct page *page)
-{
-       int i;
-       i = change_page_attr(page, 1, PAGE_KERNEL_NOCACHE);
-       /* Caller's responsibility to call global_flush_tlb() for
-        * performance reasons */
-       return i;
-}
-EXPORT_SYMBOL_GPL(map_page_into_agp);
-
-int unmap_page_from_agp(struct page *page)
-{
-       int i;
-       i = change_page_attr(page, 1, PAGE_KERNEL);
-       /* Caller's responsibility to call global_flush_tlb() for
-        * performance reasons */
-       return i;
-}
-EXPORT_SYMBOL_GPL(unmap_page_from_agp);
-#endif
-
 /*
  * Generic routines for handling agp_memory structures -
  * They use the basic page allocation routines to do the brunt of the work.
index 55392a4..9c69f2e 100644 (file)
@@ -186,8 +186,9 @@ static void *i8xx_alloc_pages(void)
                return NULL;
 
        if (change_page_attr(page, 4, PAGE_KERNEL_NOCACHE) < 0) {
+               change_page_attr(page, 4, PAGE_KERNEL);
                global_flush_tlb();
-               __free_page(page);
+               __free_pages(page, 2);
                return NULL;
        }
        global_flush_tlb();
@@ -209,7 +210,7 @@ static void i8xx_destroy_pages(void *addr)
        global_flush_tlb();
        put_page(page);
        unlock_page(page);
-       free_pages((unsigned long)addr, 2);
+       __free_pages(page, 2);
        atomic_dec(&agp_bridge->current_memory_agp);
 }
 
@@ -315,9 +316,6 @@ static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
        struct agp_memory *new;
        void *addr;
 
-       if (pg_count != 1 && pg_count != 4)
-               return NULL;
-
        switch (pg_count) {
        case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge);
                global_flush_tlb();
index 0c9dab5..6cd7373 100644 (file)
@@ -320,11 +320,11 @@ static int __devinit agp_nvidia_probe(struct pci_dev *pdev,
        u8 cap_ptr;
 
        nvidia_private.dev_1 =
-               pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 1));
+               pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 1));
        nvidia_private.dev_2 =
-               pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 2));
+               pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 2));
        nvidia_private.dev_3 =
-               pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(30, 0));
+               pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(30, 0));
 
        if (!nvidia_private.dev_1 || !nvidia_private.dev_2 || !nvidia_private.dev_3) {
                printk(KERN_INFO PFX "Detected an NVIDIA nForce/nForce2 "
@@ -443,6 +443,9 @@ static int __init agp_nvidia_init(void)
 static void __exit agp_nvidia_cleanup(void)
 {
        pci_unregister_driver(&agp_nvidia_pci_driver);
+       pci_dev_put(nvidia_private.dev_1);
+       pci_dev_put(nvidia_private.dev_2);
+       pci_dev_put(nvidia_private.dev_3);
 }
 
 module_init(agp_nvidia_init);
index 3d83b46..f4562cc 100644 (file)
@@ -329,7 +329,7 @@ parisc_agp_setup(void __iomem *ioc_hpa, void __iomem *lba_hpa)
        struct agp_bridge_data *bridge;
        int error = 0;
 
-       fake_bridge_dev = kmalloc(sizeof (struct pci_dev), GFP_KERNEL);
+       fake_bridge_dev = alloc_pci_dev();
        if (!fake_bridge_dev) {
                error = -ENOMEM;
                goto fail;
index ee8f50e..cda608c 100644 (file)
@@ -47,9 +47,8 @@ static void *sgi_tioca_alloc_page(struct agp_bridge_data *bridge)
 
        nid = info->ca_closest_node;
        page = alloc_pages_node(nid, GFP_KERNEL, 0);
-       if (page == NULL) {
-               return 0;
-       }
+       if (!page)
+               return NULL;
 
        get_page(page);
        SetPageLocked(page);
index 125f428..eb1a1c7 100644 (file)
@@ -143,96 +143,6 @@ static struct agp_bridge_driver sis_driver = {
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 };
 
-static struct agp_device_ids sis_agp_device_ids[] __devinitdata =
-{
-       {
-               .device_id      = PCI_DEVICE_ID_SI_5591_AGP,
-               .chipset_name   = "5591",
-       },
-       {
-               .device_id      = PCI_DEVICE_ID_SI_530,
-               .chipset_name   = "530",
-       },
-       {
-               .device_id      = PCI_DEVICE_ID_SI_540,
-               .chipset_name   = "540",
-       },
-       {
-               .device_id      = PCI_DEVICE_ID_SI_550,
-               .chipset_name   = "550",
-       },
-       {
-               .device_id      = PCI_DEVICE_ID_SI_620,
-               .chipset_name   = "620",
-       },
-       {
-               .device_id      = PCI_DEVICE_ID_SI_630,
-               .chipset_name   = "630",
-       },
-       {
-               .device_id      = PCI_DEVICE_ID_SI_635,
-               .chipset_name   = "635",
-       },
-       {
-               .device_id      = PCI_DEVICE_ID_SI_645,
-               .chipset_name   = "645",
-       },
-       {
-               .device_id      = PCI_DEVICE_ID_SI_646,
-               .chipset_name   = "646",
-       },
-       {
-               .device_id      = PCI_DEVICE_ID_SI_648,
-               .chipset_name   = "648",
-       },
-       {
-               .device_id      = PCI_DEVICE_ID_SI_650,
-               .chipset_name   = "650",
-       },
-       {
-               .device_id  = PCI_DEVICE_ID_SI_651,
-               .chipset_name   = "651",
-       },
-       {
-               .device_id      = PCI_DEVICE_ID_SI_655,
-               .chipset_name   = "655",
-       },
-       {
-               .device_id      = PCI_DEVICE_ID_SI_661,
-               .chipset_name   = "661",
-       },
-       {
-               .device_id      = PCI_DEVICE_ID_SI_730,
-               .chipset_name   = "730",
-       },
-       {
-               .device_id      = PCI_DEVICE_ID_SI_735,
-               .chipset_name   = "735",
-       },
-       {
-               .device_id      = PCI_DEVICE_ID_SI_740,
-               .chipset_name   = "740",
-       },
-       {
-               .device_id      = PCI_DEVICE_ID_SI_741,
-               .chipset_name   = "741",
-       },
-       {
-               .device_id      = PCI_DEVICE_ID_SI_745,
-               .chipset_name   = "745",
-       },
-       {
-               .device_id      = PCI_DEVICE_ID_SI_746,
-               .chipset_name   = "746",
-       },
-       {
-               .device_id      = PCI_DEVICE_ID_SI_760,
-               .chipset_name   = "760",
-       },
-       { }, /* dummy final entry, always present */
-};
-
-
 // chipsets that require the 'delay hack'
 static int sis_broken_chipsets[] __devinitdata = {
        PCI_DEVICE_ID_SI_648,
@@ -269,29 +179,15 @@ static void __devinit sis_get_driver(struct agp_bridge_data *bridge)
 static int __devinit agp_sis_probe(struct pci_dev *pdev,
                                   const struct pci_device_id *ent)
 {
-       struct agp_device_ids *devs = sis_agp_device_ids;
        struct agp_bridge_data *bridge;
        u8 cap_ptr;
-       int j;
 
        cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
        if (!cap_ptr)
                return -ENODEV;
 
-       /* probe for known chipsets */
-       for (j = 0; devs[j].chipset_name; j++) {
-               if (pdev->device == devs[j].device_id) {
-                       printk(KERN_INFO PFX "Detected SiS %s chipset\n",
-                                       devs[j].chipset_name);
-                       goto found;
-               }
-       }
-
-       printk(KERN_ERR PFX "Unsupported SiS chipset (device id: %04x)\n",
-                   pdev->device);
-       return -ENODEV;
 
-found:
+       printk(KERN_INFO PFX "Detected SiS chipset - id:%i\n", pdev->device);
        bridge = agp_alloc_bridge();
        if (!bridge)
                return -ENOMEM;
@@ -320,12 +216,172 @@ static void __devexit agp_sis_remove(struct pci_dev *pdev)
 
 static struct pci_device_id agp_sis_pci_table[] = {
        {
-       .class          = (PCI_CLASS_BRIDGE_HOST << 8),
-       .class_mask     = ~0,
-       .vendor         = PCI_VENDOR_ID_SI,
-       .device         = PCI_ANY_ID,
-       .subvendor      = PCI_ANY_ID,
-       .subdevice      = PCI_ANY_ID,
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_5591_AGP,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       {
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_530,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       {
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_540,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       {
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_550,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       {
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_620,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       {
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_630,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       {
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_635,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       {
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_645,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       {
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_646,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       {
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_648,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       {
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_650,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       {
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_651,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       {
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_655,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       {
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_661,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       {
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_730,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       {
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_735,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       {
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_740,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       {
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_741,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       {
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_745,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       {
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_746,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       {
+               .class          = (PCI_CLASS_BRIDGE_HOST << 8),
+               .class_mask     = ~0,
+               .vendor         = PCI_VENDOR_ID_SI,
+               .device         = PCI_DEVICE_ID_SI_760,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
        },
        { }
 };
index 55212a3..551ef25 100644 (file)
@@ -455,15 +455,6 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev,
        u32 temp, temp2;
        u8 cap_ptr = 0;
 
-       /* Everything is on func 1 here so we are hardcoding function one */
-       bridge_dev = pci_find_slot((unsigned int)pdev->bus->number,
-                       PCI_DEVFN(0, 1));
-       if (!bridge_dev) {
-               printk(KERN_INFO PFX "Detected a Serverworks chipset "
-                      "but could not find the secondary device.\n");
-               return -ENODEV;
-       }
-
        cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
 
        switch (pdev->device) {
@@ -483,6 +474,15 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev,
                return -ENODEV;
        }
 
+       /* Everything is on func 1 here so we are hardcoding function one */
+       bridge_dev = pci_get_bus_and_slot((unsigned int)pdev->bus->number,
+                       PCI_DEVFN(0, 1));
+       if (!bridge_dev) {
+               printk(KERN_INFO PFX "Detected a Serverworks chipset "
+                      "but could not find the secondary device.\n");
+               return -ENODEV;
+       }
+
        serverworks_private.svrwrks_dev = bridge_dev;
        serverworks_private.gart_addr_ofs = 0x10;
 
@@ -515,7 +515,7 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev,
 
        bridge->driver = &sworks_driver;
        bridge->dev_private_data = &serverworks_private,
-       bridge->dev = pdev;
+       bridge->dev = pci_dev_get(pdev);
 
        pci_set_drvdata(pdev, bridge);
        return agp_add_bridge(bridge);
@@ -525,8 +525,11 @@ static void __devexit agp_serverworks_remove(struct pci_dev *pdev)
 {
        struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
+       pci_dev_put(bridge->dev);
        agp_remove_bridge(bridge);
        agp_put_bridge(bridge);
+       pci_dev_put(serverworks_private.svrwrks_dev);
+       serverworks_private.svrwrks_dev = NULL;
 }
 
 static struct pci_device_id agp_serverworks_pci_table[] = {
index 9ebf84d..ec435cb 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/pci.h>
 #include <linux/hw_random.h>
 #include <asm/io.h>
 #include <asm/msr.h>
index cb8d691..c06e86a 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/input.h>
 #include <linux/reboot.h>
 
-static void kbd_disconnect(struct input_handle *handle);
 extern void ctrl_alt_del(void);
 
 /*
@@ -159,65 +158,41 @@ static int sysrq_alt_use;
 static int sysrq_alt;
 
 /*
- * Translation of scancodes to keycodes. We set them on only the first attached
- * keyboard - for per-keyboard setting, /dev/input/event is more useful.
+ * Translation of scancodes to keycodes. We set them on only the first
+ * keyboard in the list that accepts the scancode and keycode.
+ * Explanation for not choosing the first attached keyboard anymore:
+ *  USB keyboards for example have two event devices: one for all "normal"
+ *  keys and one for extra function keys (like "volume up", "make coffee",
+ *  etc.). So this means that scancodes for the extra function keys won't
+ *  be valid for the first event device, but will be for the second.
  */
 int getkeycode(unsigned int scancode)
 {
-       struct list_head *node;
-       struct input_dev *dev = NULL;
+       struct input_handle *handle;
+       int keycode;
+       int error = -ENODEV;
 
-       list_for_each(node, &kbd_handler.h_list) {
-               struct input_handle *handle = to_handle_h(node);
-               if (handle->dev->keycodesize) {
-                       dev = handle->dev;
-                       break;
-               }
+       list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
+               error = handle->dev->getkeycode(handle->dev, scancode, &keycode);
+               if (!error)
+                       return keycode;
        }
 
-       if (!dev)
-               return -ENODEV;
-
-       if (scancode >= dev->keycodemax)
-               return -EINVAL;
-
-       return INPUT_KEYCODE(dev, scancode);
+       return error;
 }
 
 int setkeycode(unsigned int scancode, unsigned int keycode)
 {
-       struct list_head *node;
-       struct input_dev *dev = NULL;
-       unsigned int i, oldkey;
+       struct input_handle *handle;
+       int error = -ENODEV;
 
-       list_for_each(node, &kbd_handler.h_list) {
-               struct input_handle *handle = to_handle_h(node);
-               if (handle->dev->keycodesize) {
-                       dev = handle->dev;
+       list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
+               error = handle->dev->setkeycode(handle->dev, scancode, keycode);
+               if (!error)
                        break;
-               }
        }
 
-       if (!dev)
-               return -ENODEV;
-
-       if (scancode >= dev->keycodemax)
-               return -EINVAL;
-       if (keycode < 0 || keycode > KEY_MAX)
-               return -EINVAL;
-       if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
-               return -EINVAL;
-
-       oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode);
-
-       clear_bit(oldkey, dev->keybit);
-       set_bit(keycode, dev->keybit);
-
-       for (i = 0; i < dev->keycodemax; i++)
-               if (INPUT_KEYCODE(dev,i) == oldkey)
-                       set_bit(oldkey, dev->keybit);
-
-       return 0;
+       return error;
 }
 
 /*
@@ -225,10 +200,9 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
  */
 static void kd_nosound(unsigned long ignored)
 {
-       struct list_head *node;
+       struct input_handle *handle;
 
-       list_for_each(node, &kbd_handler.h_list) {
-               struct input_handle *handle = to_handle_h(node);
+       list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
                if (test_bit(EV_SND, handle->dev->evbit)) {
                        if (test_bit(SND_TONE, handle->dev->sndbit))
                                input_inject_event(handle, EV_SND, SND_TONE, 0);
@@ -1161,7 +1135,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
 
        if ((raw_mode = (kbd->kbdmode == VC_RAW)) && !hw_raw)
                if (emulate_raw(vc, keycode, !down << 7))
-                       if (keycode < BTN_MISC)
+                       if (keycode < BTN_MISC && printk_ratelimit())
                                printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
 
 #ifdef CONFIG_MAGIC_SYSRQ             /* Handle the SysRq Hack */
@@ -1285,11 +1259,11 @@ static void kbd_event(struct input_handle *handle, unsigned int event_type,
  * likes it, it can open it and get events from it. In this (kbd_connect)
  * function, we should decide which VT to bind that keyboard to initially.
  */
-static struct input_handle *kbd_connect(struct input_handler *handler,
-                                       struct input_dev *dev,
-                                       const struct input_device_id *id)
+static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
+                       const struct input_device_id *id)
 {
        struct input_handle *handle;
+       int error;
        int i;
 
        for (i = KEY_RESERVED; i < BTN_MISC; i++)
@@ -1297,24 +1271,37 @@ static struct input_handle *kbd_connect(struct input_handler *handler,
                        break;
 
        if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
-               return NULL;
+               return -ENODEV;
 
        handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
        if (!handle)
-               return NULL;
+               return -ENOMEM;
 
        handle->dev = dev;
        handle->handler = handler;
        handle->name = "kbd";
 
-       input_open_device(handle);
+       error = input_register_handle(handle);
+       if (error)
+               goto err_free_handle;
+
+       error = input_open_device(handle);
+       if (error)
+               goto err_unregister_handle;
+
+       return 0;
 
-       return handle;
+ err_unregister_handle:
+       input_unregister_handle(handle);
+ err_free_handle:
+       kfree(handle);
+       return error;
 }
 
 static void kbd_disconnect(struct input_handle *handle)
 {
        input_close_device(handle);
+       input_unregister_handle(handle);
        kfree(handle);
 }
 
index 157b1d0..13808f6 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/timer.h>
 #include <linux/time.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/serial.h>
index bb9a43c..9f273f0 100644 (file)
@@ -19,7 +19,6 @@
  * 
  */
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
 #include <linux/sched.h>
index 1e4a8d7..2f7ba7a 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/init.h>
 #include <linux/pnp.h>
 #include <linux/fs.h>
-#include <linux/pci.h>
 
 #include <asm/semaphore.h>
 #include <asm/io.h>
index fc0e034..d4fd0fa 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/notifier.h>
 #include <linux/reboot.h>
 #include <linux/fs.h>
-#include <linux/pci.h>
+#include <linux/ioport.h>
 #include <linux/scx200.h>
 
 #include <asm/uaccess.h>
index d155e81..993fa7b 100644 (file)
@@ -9,6 +9,9 @@ config CPU_FREQ
          clock speed, you need to either enable a dynamic cpufreq governor
          (see below) after boot, or use a userspace tool.
 
+         To compile this driver as a module, choose M here: the
+         module will be called cpufreq.
+
          For details, take a look at <file:Documentation/cpu-freq>.
 
          If in doubt, say N.
@@ -16,7 +19,7 @@ config CPU_FREQ
 if CPU_FREQ
 
 config CPU_FREQ_TABLE
-       tristate
+       tristate
 
 config CPU_FREQ_DEBUG
        bool "Enable CPUfreq debugging"
@@ -32,19 +35,26 @@ config CPU_FREQ_DEBUG
               4 to activate CPUfreq governor debugging
 
 config CPU_FREQ_STAT
-       tristate "CPU frequency translation statistics"
-       select CPU_FREQ_TABLE
-       default y
-       help
-         This driver exports CPU frequency statistics information through sysfs
-         file system
+       tristate "CPU frequency translation statistics"
+       select CPU_FREQ_TABLE
+       default y
+       help
+         This driver exports CPU frequency statistics information through sysfs
+         file system.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cpufreq_stats.
+
+         If in doubt, say N.
 
 config CPU_FREQ_STAT_DETAILS
-       bool "CPU frequency translation statistics details"
-       depends on CPU_FREQ_STAT
-       help
-         This will show detail CPU frequency translation table in sysfs file
-         system
+       bool "CPU frequency translation statistics details"
+       depends on CPU_FREQ_STAT
+       help
+         This will show detail CPU frequency translation table in sysfs file
+         system.
+
+         If in doubt, say N.
 
 # Note that it is not currently possible to set the other governors (such as ondemand)
 # as the default, since if they fail to initialise, cpufreq will be
@@ -78,29 +88,38 @@ config CPU_FREQ_DEFAULT_GOV_USERSPACE
 endchoice
 
 config CPU_FREQ_GOV_PERFORMANCE
-       tristate "'performance' governor"
-       help
+       tristate "'performance' governor"
+       help
          This cpufreq governor sets the frequency statically to the
          highest available CPU frequency.
 
+         To compile this driver as a module, choose M here: the
+         module will be called cpufreq_performance.
+
          If in doubt, say Y.
 
 config CPU_FREQ_GOV_POWERSAVE
-       tristate "'powersave' governor"
-       help
+       tristate "'powersave' governor"
+       help
          This cpufreq governor sets the frequency statically to the
          lowest available CPU frequency.
 
+         To compile this driver as a module, choose M here: the
+         module will be called cpufreq_powersave.
+
          If in doubt, say Y.
 
 config CPU_FREQ_GOV_USERSPACE
-       tristate "'userspace' governor for userspace frequency scaling"
-       help
+       tristate "'userspace' governor for userspace frequency scaling"
+       help
          Enable this cpufreq governor when you either want to set the
          CPU frequency manually or when an userspace program shall
          be able to set the CPU dynamically, like on LART 
          <http://www.lartmaker.nl/>.
 
+         To compile this driver as a module, choose M here: the
+         module will be called cpufreq_userspace.
+
          For details, take a look at <file:Documentation/cpu-freq/>.
 
          If in doubt, say Y.
@@ -116,6 +135,9 @@ config CPU_FREQ_GOV_ONDEMAND
          do fast frequency switching (i.e, very low latency frequency
          transitions). 
 
+         To compile this driver as a module, choose M here: the
+         module will be called cpufreq_ondemand.
+
          For details, take a look at linux/Documentation/cpu-freq.
 
          If in doubt, say N.
@@ -136,6 +158,9 @@ config CPU_FREQ_GOV_CONSERVATIVE
          step-by-step latency issues between the minimum and maximum frequency
          transitions in the CPU) you will probably want to use this governor.
 
+         To compile this driver as a module, choose M here: the
+         module will be called cpufreq_conservative.
+
          For details, take a look at linux/Documentation/cpu-freq.
 
          If in doubt, say N.
index 3162010..893dbaf 100644 (file)
@@ -768,6 +768,9 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
                unlock_policy_rwsem_write(cpu);
                goto err_out;
        }
+       policy->user_policy.min = policy->cpuinfo.min_freq;
+       policy->user_policy.max = policy->cpuinfo.max_freq;
+       policy->user_policy.governor = policy->governor;
 
 #ifdef CONFIG_SMP
        for_each_cpu_mask(j, policy->cpus) {
@@ -858,10 +861,13 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
 
        policy->governor = NULL; /* to assure that the starting sequence is
                                  * run in cpufreq_set_policy */
-       unlock_policy_rwsem_write(cpu);
 
        /* set default policy */
-       ret = cpufreq_set_policy(&new_policy);
+       ret = __cpufreq_set_policy(policy, &new_policy);
+       policy->user_policy.policy = policy->policy;
+
+       unlock_policy_rwsem_write(cpu);
+
        if (ret) {
                dprintk("setting policy failed\n");
                goto err_out_unregister;
@@ -1620,43 +1626,6 @@ error_out:
 }
 
 /**
- *     cpufreq_set_policy - set a new CPUFreq policy
- *     @policy: policy to be set.
- *
- *     Sets a new CPU frequency and voltage scaling policy.
- */
-int cpufreq_set_policy(struct cpufreq_policy *policy)
-{
-       int ret = 0;
-       struct cpufreq_policy *data;
-
-       if (!policy)
-               return -EINVAL;
-
-       data = cpufreq_cpu_get(policy->cpu);
-       if (!data)
-               return -EINVAL;
-
-       if (unlikely(lock_policy_rwsem_write(policy->cpu)))
-               return -EINVAL;
-
-
-       ret = __cpufreq_set_policy(data, policy);
-       data->user_policy.min = data->min;
-       data->user_policy.max = data->max;
-       data->user_policy.policy = data->policy;
-       data->user_policy.governor = data->governor;
-
-       unlock_policy_rwsem_write(policy->cpu);
-
-       cpufreq_cpu_put(data);
-
-       return ret;
-}
-EXPORT_SYMBOL(cpufreq_set_policy);
-
-
-/**
  *     cpufreq_update_policy - re-evaluate an existing cpufreq policy
  *     @cpu: CPU which shall be re-evaluated
  *
index ff8c4be..f21fe66 100644 (file)
@@ -1,10 +1,10 @@
 menu "Hardware crypto devices"
 
 config CRYPTO_DEV_PADLOCK
-       tristate "Support for VIA PadLock ACE"
+       bool "Support for VIA PadLock ACE"
        depends on X86_32
        select CRYPTO_ALGAPI
-       default m
+       default y
        help
          Some VIA processors come with an integrated crypto engine
          (so called VIA PadLock ACE, Advanced Cryptography Engine)
@@ -14,16 +14,6 @@ config CRYPTO_DEV_PADLOCK
          The instructions are used only when the CPU supports them.
          Otherwise software encryption is used.
 
-         Selecting M for this option will compile a helper module
-         padlock.ko that should autoload all below configured
-         algorithms. Don't worry if your hardware does not support
-         some or all of them. In such case padlock.ko will
-         simply write a single line into the kernel log informing
-         about its failure but everything will keep working fine.
-
-         If you are unsure, say M. The compiled module will be
-         called padlock.ko
-
 config CRYPTO_DEV_PADLOCK_AES
        tristate "PadLock driver for AES algorithm"
        depends on CRYPTO_DEV_PADLOCK
@@ -55,7 +45,7 @@ source "arch/s390/crypto/Kconfig"
 
 config CRYPTO_DEV_GEODE
        tristate "Support for the Geode LX AES engine"
-       depends on CRYPTO && X86_32 && PCI
+       depends on X86_32 && PCI
        select CRYPTO_ALGAPI
        select CRYPTO_BLKCIPHER
        default m
index 6059cf8..d070030 100644 (file)
@@ -1,4 +1,3 @@
-obj-$(CONFIG_CRYPTO_DEV_PADLOCK) += padlock.o
 obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o
 obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o
 obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o
diff --git a/drivers/crypto/padlock.c b/drivers/crypto/padlock.c
deleted file mode 100644 (file)
index d6d7dd5..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Cryptographic API.
- *
- * Support for VIA PadLock hardware crypto engine.
- *
- * Copyright (c) 2006  Michal Ludvig <michal@logix.cz>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/crypto.h>
-#include <linux/cryptohash.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/scatterlist.h>
-#include "padlock.h"
-
-static int __init padlock_init(void)
-{
-       int success = 0;
-
-       if (crypto_has_cipher("aes-padlock", 0, 0))
-               success++;
-
-       if (crypto_has_hash("sha1-padlock", 0, 0))
-               success++;
-
-       if (crypto_has_hash("sha256-padlock", 0, 0))
-               success++;
-
-       if (!success) {
-               printk(KERN_WARNING PFX "No VIA PadLock drivers have been loaded.\n");
-               return -ENODEV;
-       }
-
-       printk(KERN_NOTICE PFX "%d drivers are available.\n", success);
-
-       return 0;
-}
-
-static void __exit padlock_fini(void)
-{
-}
-
-module_init(padlock_init);
-module_exit(padlock_fini);
-
-MODULE_DESCRIPTION("Load all configured PadLock algorithms.");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Michal Ludvig");
-
index c6281cc..1324984 100644 (file)
@@ -409,7 +409,7 @@ static struct kobj_type ktype_efivar = {
 };
 
 static ssize_t
-dummy(struct subsystem *sub, char *buf)
+dummy(struct kset *kset, char *buf)
 {
        return -ENODEV;
 }
@@ -422,7 +422,7 @@ efivar_unregister(struct efivar_entry *var)
 
 
 static ssize_t
-efivar_create(struct subsystem *sub, const char *buf, size_t count)
+efivar_create(struct kset *kset, const char *buf, size_t count)
 {
        struct efi_variable *new_var = (struct efi_variable *)buf;
        struct efivar_entry *search_efivar, *n;
@@ -480,7 +480,7 @@ efivar_create(struct subsystem *sub, const char *buf, size_t count)
 }
 
 static ssize_t
-efivar_delete(struct subsystem *sub, const char *buf, size_t count)
+efivar_delete(struct kset *kset, const char *buf, size_t count)
 {
        struct efi_variable *del_var = (struct efi_variable *)buf;
        struct efivar_entry *search_efivar, *n;
@@ -551,11 +551,11 @@ static struct subsys_attribute *var_subsys_attrs[] = {
  * the efivars driver
  */
 static ssize_t
-systab_read(struct subsystem *entry, char *buf)
+systab_read(struct kset *kset, char *buf)
 {
        char *str = buf;
 
-       if (!entry || !buf)
+       if (!kset || !buf)
                return -EINVAL;
 
        if (efi.mps != EFI_INVALID_TABLE_ADDR)
@@ -687,7 +687,7 @@ efivars_init(void)
                goto out_free;
        }
 
-       kset_set_kset_s(&vars_subsys, efi_subsys);
+       kobj_set_kset_s(&vars_subsys, efi_subsys);
 
        error = subsystem_register(&vars_subsys);
 
index 11935f6..434a61b 100644 (file)
@@ -2,9 +2,7 @@
 # I2C subsystem configuration
 #
 
-menu "I2C support"
-
-config I2C
+menuconfig I2C
        tristate "I2C support"
        ---help---
          I2C (pronounce: I-square-C) is a slow serial bus protocol used in
@@ -22,9 +20,14 @@ config I2C
          This I2C support can also be built as a module.  If so, the module
          will be called i2c-core.
 
+if I2C
+
+config I2C_BOARDINFO
+       boolean
+       default y
+
 config I2C_CHARDEV
        tristate "I2C device interface"
-       depends on I2C
        help
          Say Y here to use i2c-* device files, usually found in the /dev
          directory on your system.  They make it possible to have user-space
@@ -40,7 +43,6 @@ source drivers/i2c/chips/Kconfig
 
 config I2C_DEBUG_CORE
        bool "I2C Core debugging messages"
-       depends on I2C
        help
          Say Y here if you want the I2C core to produce a bunch of debug
          messages to the system log.  Select this if you are having a
@@ -48,7 +50,6 @@ config I2C_DEBUG_CORE
 
 config I2C_DEBUG_ALGO
        bool "I2C Algorithm debugging messages"
-       depends on I2C
        help
          Say Y here if you want the I2C algorithm drivers to produce a bunch
          of debug messages to the system log.  Select this if you are having
@@ -57,7 +58,6 @@ config I2C_DEBUG_ALGO
 
 config I2C_DEBUG_BUS
        bool "I2C Bus debugging messages"
-       depends on I2C
        help
          Say Y here if you want the I2C bus drivers to produce a bunch of
          debug messages to the system log.  Select this if you are having
@@ -66,12 +66,10 @@ config I2C_DEBUG_BUS
 
 config I2C_DEBUG_CHIP
        bool "I2C Chip debugging messages"
-       depends on I2C
        help
          Say Y here if you want the I2C chip drivers to produce a bunch of
          debug messages to the system log.  Select this if you are having
          a problem with I2C support and want to see more of what is going
          on.
 
-endmenu
-
+endif # I2C
index 71c5a85..ba26e6c 100644 (file)
@@ -2,6 +2,7 @@
 # Makefile for the i2c core.
 #
 
+obj-$(CONFIG_I2C_BOARDINFO)    += i2c-boardinfo.o
 obj-$(CONFIG_I2C)              += i2c-core.o
 obj-$(CONFIG_I2C_CHARDEV)      += i2c-dev.o
 obj-y                          += busses/ chips/ algos/
index af02034..5889907 100644 (file)
@@ -3,11 +3,9 @@
 #
 
 menu "I2C Algorithms"
-       depends on I2C
 
 config I2C_ALGOBIT
        tristate "I2C bit-banging interfaces"
-       depends on I2C
        help
          This allows you to use a range of I2C adapters called bit-banging
          adapters.  Say Y if you own an I2C adapter belonging to this class
@@ -18,7 +16,6 @@ config I2C_ALGOBIT
 
 config I2C_ALGOPCF
        tristate "I2C PCF 8584 interfaces"
-       depends on I2C
        help
          This allows you to use a range of I2C adapters called PCF adapters.
          Say Y if you own an I2C adapter belonging to this class and then say
@@ -29,7 +26,6 @@ config I2C_ALGOPCF
 
 config I2C_ALGOPCA
        tristate "I2C PCA 9564 interfaces"
-       depends on I2C
        help
          This allows you to use a range of I2C adapters called PCA adapters.
          Say Y if you own an I2C adapter belonging to this class and then say
@@ -40,11 +36,11 @@ config I2C_ALGOPCA
 
 config I2C_ALGO8XX
        tristate "MPC8xx CPM I2C interface"
-       depends on 8xx && I2C
+       depends on 8xx
 
 config I2C_ALGO_SGI
        tristate "I2C SGI interfaces"
-       depends on I2C && (SGI_IP22 || SGI_IP32 || X86_VISWS)
+       depends on SGI_IP22 || SGI_IP32 || X86_VISWS
        help
          Supports the SGI interfaces like the ones found on SGI Indy VINO
          or SGI O2 MACE.
index 95aa539..8a5f582 100644 (file)
 
 
 /* ----- global defines ----------------------------------------------- */
-#define DEB(x) if (i2c_debug>=1) x;
-#define DEB2(x) if (i2c_debug>=2) x;
-#define DEBSTAT(x) if (i2c_debug>=3) x; /* print several statistical values*/
-#define DEBPROTO(x) if (i2c_debug>=9) { x; }
-       /* debug the protocol by showing transferred bits */
 
+#ifdef DEBUG
+#define bit_dbg(level, dev, format, args...) \
+       do { \
+               if (i2c_debug >= level) \
+                       dev_dbg(dev, format, ##args); \
+       } while (0)
+#else
+#define bit_dbg(level, dev, format, args...) \
+       do {} while (0)
+#endif /* DEBUG */
 
 /* ----- global variables ---------------------------------------------        */
 
-/* module parameters:
- */
-static int i2c_debug;
 static int bit_test;   /* see if the line-setting functions work       */
+module_param(bit_test, bool, 0);
+MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");
+
+#ifdef DEBUG
+static int i2c_debug = 1;
+module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(i2c_debug,
+                "debug level - 0 off; 1 normal; 2 verbose; 3 very verbose");
+#endif
 
 /* --- setting states on the bus with the right timing: ---------------        */
 
@@ -57,19 +68,19 @@ static int bit_test;        /* see if the line-setting functions work       */
 static inline void sdalo(struct i2c_algo_bit_data *adap)
 {
        setsda(adap,0);
-       udelay(adap->udelay);
+       udelay((adap->udelay + 1) / 2);
 }
 
 static inline void sdahi(struct i2c_algo_bit_data *adap)
 {
        setsda(adap,1);
-       udelay(adap->udelay);
+       udelay((adap->udelay + 1) / 2);
 }
 
 static inline void scllo(struct i2c_algo_bit_data *adap)
 {
        setscl(adap,0);
-       udelay(adap->udelay);
+       udelay(adap->udelay / 2);
 }
 
 /*
@@ -98,7 +109,11 @@ static int sclhi(struct i2c_algo_bit_data *adap)
                }
                cond_resched();
        }
-       DEBSTAT(printk(KERN_DEBUG "needed %ld jiffies\n", jiffies-start));
+#ifdef DEBUG
+       if (jiffies != start && i2c_debug >= 3)
+               pr_debug("i2c-algo-bit: needed %ld jiffies for SCL to go "
+                        "high\n", jiffies - start);
+#endif
 
 done:
        udelay(adap->udelay);
@@ -110,30 +125,29 @@ done:
 static void i2c_start(struct i2c_algo_bit_data *adap) 
 {
        /* assert: scl, sda are high */
-       DEBPROTO(printk("S "));
-       sdalo(adap);
+       setsda(adap, 0);
+       udelay(adap->udelay);
        scllo(adap);
 }
 
 static void i2c_repstart(struct i2c_algo_bit_data *adap) 
 {
-       /* scl, sda may not be high */
-       DEBPROTO(printk(" Sr "));
-       setsda(adap,1);
+       /* assert: scl is low */
+       sdahi(adap);
        sclhi(adap);
-       
-       sdalo(adap);
+       setsda(adap, 0);
+       udelay(adap->udelay);
        scllo(adap);
 }
 
 
 static void i2c_stop(struct i2c_algo_bit_data *adap) 
 {
-       DEBPROTO(printk("P\n"));
        /* assert: scl is low */
        sdalo(adap);
        sclhi(adap); 
-       sdahi(adap);
+       setsda(adap, 1);
+       udelay(adap->udelay);
 }
 
 
@@ -145,7 +159,7 @@ static void i2c_stop(struct i2c_algo_bit_data *adap)
  * 0 if the device did not ack
  * -ETIMEDOUT if an error occurred (while raising the scl line)
  */
-static int i2c_outb(struct i2c_adapter *i2c_adap, char c)
+static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c)
 {
        int i;
        int sb;
@@ -154,34 +168,32 @@ static int i2c_outb(struct i2c_adapter *i2c_adap, char c)
 
        /* assert: scl is low */
        for ( i=7 ; i>=0 ; i-- ) {
-               sb = c & ( 1 << i );
+               sb = (c >> i) & 1;
                setsda(adap,sb);
-               udelay(adap->udelay);
-               DEBPROTO(printk(KERN_DEBUG "%d",sb!=0));
+               udelay((adap->udelay + 1) / 2);
                if (sclhi(adap)<0) { /* timed out */
-                       sdahi(adap); /* we don't want to block the net */
-                       DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x, timeout at bit #%d\n", c&0xff, i));
+                       bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
+                               "timeout at bit #%d\n", (int)c, i);
                        return -ETIMEDOUT;
                };
                /* do arbitration here: 
                 * if ( sb && ! getsda(adap) ) -> ouch! Get out of here.
                 */
-               setscl(adap, 0 );
-               udelay(adap->udelay);
+               scllo(adap);
        }
        sdahi(adap);
        if (sclhi(adap)<0){ /* timeout */
-           DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x, timeout at ack\n", c&0xff));
-           return -ETIMEDOUT;
+               bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
+                       "timeout at ack\n", (int)c);
+               return -ETIMEDOUT;
        };
        /* read ack: SDA should be pulled down by slave */
-       ack=getsda(adap);       /* ack: sda is pulled low ->success.     */
-       DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x , getsda() = %d\n", c & 0xff, ack));
+       ack = !getsda(adap);    /* ack: sda is pulled low -> success */
+       bit_dbg(2, &i2c_adap->dev, "i2c_outb: 0x%02x %s\n", (int)c,
+               ack ? "A" : "NA");
 
-       DEBPROTO( printk(KERN_DEBUG "[%2.2x]",c&0xff) );
-       DEBPROTO(if (0==ack){ printk(KERN_DEBUG " A ");} else printk(KERN_DEBUG " NA ") );
        scllo(adap);
-       return 0==ack;          /* return 1 if device acked      */
+       return ack;
        /* assert: scl is low (sda undef) */
 }
 
@@ -198,19 +210,18 @@ static int i2c_inb(struct i2c_adapter *i2c_adap)
        sdahi(adap);
        for (i=0;i<8;i++) {
                if (sclhi(adap)<0) { /* timeout */
-                       DEB2(printk(KERN_DEBUG " i2c_inb: timeout at bit #%d\n", 7-i));
+                       bit_dbg(1, &i2c_adap->dev, "i2c_inb: timeout at bit "
+                               "#%d\n", 7 - i);
                        return -ETIMEDOUT;
                };
                indata *= 2;
                if ( getsda(adap) ) 
                        indata |= 0x01;
-               scllo(adap);
+               setscl(adap, 0);
+               udelay(i == 7 ? adap->udelay / 2 : adap->udelay);
        }
        /* assert: scl is low */
-       DEB2(printk(KERN_DEBUG "i2c_inb: 0x%02x\n", indata & 0xff));
-
-       DEBPROTO(printk(KERN_DEBUG " 0x%02x", indata & 0xff));
-       return (int) (indata & 0xff);
+       return indata;
 }
 
 /*
@@ -221,73 +232,67 @@ static int test_bus(struct i2c_algo_bit_data *adap, char* name) {
        int scl,sda;
 
        if (adap->getscl==NULL)
-               printk(KERN_INFO "i2c-algo-bit.o: Testing SDA only, "
-                       "SCL is not readable.\n");
+               pr_info("%s: Testing SDA only, SCL is not readable\n", name);
 
        sda=getsda(adap);
        scl=(adap->getscl==NULL?1:getscl(adap));
-       printk(KERN_DEBUG "i2c-algo-bit.o: (0) scl=%d, sda=%d\n",scl,sda);
        if (!scl || !sda ) {
-               printk(KERN_WARNING "i2c-algo-bit.o: %s seems to be busy.\n", name);
+               printk(KERN_WARNING "%s: bus seems to be busy\n", name);
                goto bailout;
        }
 
        sdalo(adap);
        sda=getsda(adap);
        scl=(adap->getscl==NULL?1:getscl(adap));
-       printk(KERN_DEBUG "i2c-algo-bit.o: (1) scl=%d, sda=%d\n",scl,sda);
        if ( 0 != sda ) {
-               printk(KERN_WARNING "i2c-algo-bit.o: SDA stuck high!\n");
+               printk(KERN_WARNING "%s: SDA stuck high!\n", name);
                goto bailout;
        }
        if ( 0 == scl ) {
-               printk(KERN_WARNING "i2c-algo-bit.o: SCL unexpected low "
-                       "while pulling SDA low!\n");
+               printk(KERN_WARNING "%s: SCL unexpected low "
+                      "while pulling SDA low!\n", name);
                goto bailout;
        }               
 
        sdahi(adap);
        sda=getsda(adap);
        scl=(adap->getscl==NULL?1:getscl(adap));
-       printk(KERN_DEBUG "i2c-algo-bit.o: (2) scl=%d, sda=%d\n",scl,sda);
        if ( 0 == sda ) {
-               printk(KERN_WARNING "i2c-algo-bit.o: SDA stuck low!\n");
+               printk(KERN_WARNING "%s: SDA stuck low!\n", name);
                goto bailout;
        }
        if ( 0 == scl ) {
-               printk(KERN_WARNING "i2c-algo-bit.o: SCL unexpected low "
-                       "while pulling SDA high!\n");
+               printk(KERN_WARNING "%s: SCL unexpected low "
+                      "while pulling SDA high!\n", name);
                goto bailout;
        }
 
        scllo(adap);
        sda=getsda(adap);
        scl=(adap->getscl==NULL?0:getscl(adap));
-       printk(KERN_DEBUG "i2c-algo-bit.o: (3) scl=%d, sda=%d\n",scl,sda);
        if ( 0 != scl ) {
-               printk(KERN_WARNING "i2c-algo-bit.o: SCL stuck high!\n");
+               printk(KERN_WARNING "%s: SCL stuck high!\n", name);
                goto bailout;
        }
        if ( 0 == sda ) {
-               printk(KERN_WARNING "i2c-algo-bit.o: SDA unexpected low "
-                       "while pulling SCL low!\n");
+               printk(KERN_WARNING "%s: SDA unexpected low "
+                      "while pulling SCL low!\n", name);
                goto bailout;
        }
        
        sclhi(adap);
        sda=getsda(adap);
        scl=(adap->getscl==NULL?1:getscl(adap));
-       printk(KERN_DEBUG "i2c-algo-bit.o: (4) scl=%d, sda=%d\n",scl,sda);
        if ( 0 == scl ) {
-               printk(KERN_WARNING "i2c-algo-bit.o: SCL stuck low!\n");
+               printk(KERN_WARNING "%s: SCL stuck low!\n", name);
                goto bailout;
        }
        if ( 0 == sda ) {
-               printk(KERN_WARNING "i2c-algo-bit.o: SDA unexpected low "
-                       "while pulling SCL high!\n");
+               printk(KERN_WARNING "%s: SDA unexpected low "
+                      "while pulling SCL high!\n", name);
                goto bailout;
        }
-       printk(KERN_INFO "i2c-algo-bit.o: %s passed test.\n",name);
+       pr_info("%s: Test OK\n", name);
        return 0;
 bailout:
        sdahi(adap);
@@ -312,44 +317,39 @@ static int try_address(struct i2c_adapter *i2c_adap,
        int i,ret = -1;
        for (i=0;i<=retries;i++) {
                ret = i2c_outb(i2c_adap,addr);
-               if (ret==1)
-                       break;  /* success! */
-               i2c_stop(adap);
-               udelay(5/*adap->udelay*/);
-               if (i==retries)  /* no success */
+               if (ret == 1 || i == retries)
                        break;
-               i2c_start(adap);
+               bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");
+               i2c_stop(adap);
                udelay(adap->udelay);
+               yield();
+               bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");
+               i2c_start(adap);
        }
-       DEB2(if (i)
-            printk(KERN_DEBUG "i2c-algo-bit.o: Used %d tries to %s client at 0x%02x : %s\n",
-                   i+1, addr & 1 ? "read" : "write", addr>>1,
-                   ret==1 ? "success" : ret==0 ? "no ack" : "failed, timeout?" )
-           );
+       if (i && ret)
+               bit_dbg(1, &i2c_adap->dev, "Used %d tries to %s client at "
+                       "0x%02x: %s\n", i + 1,
+                       addr & 1 ? "read from" : "write to", addr >> 1,
+                       ret == 1 ? "success" : "failed, timeout?");
        return ret;
 }
 
 static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
 {
-       struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
-       char c;
-       const char *temp = msg->buf;
+       const unsigned char *temp = msg->buf;
        int count = msg->len;
        unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK; 
        int retval;
        int wrcount=0;
 
        while (count > 0) {
-               c = *temp;
-               DEB2(dev_dbg(&i2c_adap->dev, "sendbytes: writing %2.2X\n", c&0xff));
-               retval = i2c_outb(i2c_adap,c);
+               retval = i2c_outb(i2c_adap, *temp);
                if ((retval>0) || (nak_ok && (retval==0)))  { /* ok or ignored NAK */
                        count--; 
                        temp++;
                        wrcount++;
                } else { /* arbitration or no acknowledge */
                        dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n");
-                       i2c_stop(adap);
                        return (retval<0)? retval : -EFAULT;
                                /* got a better one ?? */
                }
@@ -362,7 +362,7 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
        int inval;
        int rdcount=0;          /* counts bytes read */
        struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
-       char *temp = msg->buf;
+       unsigned char *temp = msg->buf;
        int count = msg->len;
 
        while (count > 0) {
@@ -371,30 +371,44 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
                        *temp = inval;
                        rdcount++;
                } else {   /* read timed out */
-                       printk(KERN_ERR "i2c-algo-bit.o: readbytes: i2c_inb timed out.\n");
                        break;
                }
 
                temp++;
                count--;
 
-               if (msg->flags & I2C_M_NO_RD_ACK)
+               if (msg->flags & I2C_M_NO_RD_ACK) {
+                       bit_dbg(2, &i2c_adap->dev, "i2c_inb: 0x%02x\n",
+                               inval);
                        continue;
-
-               if ( count > 0 ) {              /* send ack */
-                       sdalo(adap);
-                       DEBPROTO(printk(" Am "));
-               } else {
-                       sdahi(adap);    /* neg. ack on last byte */
-                       DEBPROTO(printk(" NAm "));
                }
+
+               /* assert: sda is high */
+               if (count)              /* send ack */
+                       setsda(adap, 0);
+               udelay((adap->udelay + 1) / 2);
+               bit_dbg(2, &i2c_adap->dev, "i2c_inb: 0x%02x %s\n", inval,
+                       count ? "A" : "NA");
                if (sclhi(adap)<0) {    /* timeout */
-                       sdahi(adap);
-                       printk(KERN_ERR "i2c-algo-bit.o: readbytes: Timeout at ack\n");
+                       dev_err(&i2c_adap->dev, "readbytes: timeout at ack\n");
                        return -ETIMEDOUT;
                };
                scllo(adap);
-               sdahi(adap);
+
+               /* Some SMBus transactions require that we receive the
+                  transaction length as the first read byte. */
+               if (rdcount == 1 && (msg->flags & I2C_M_RECV_LEN)) {
+                       if (inval <= 0 || inval > I2C_SMBUS_BLOCK_MAX) {
+                               dev_err(&i2c_adap->dev, "readbytes: invalid "
+                                       "block length (%d)\n", inval);
+                               return -EREMOTEIO;
+                       }
+                       /* The original count value accounts for the extra
+                          bytes, that is, either 1 for a regular transaction,
+                          or 2 for a PEC transaction. */
+                       count += inval;
+                       msg->len += inval;
+               }
        }
        return rdcount;
 }
@@ -421,27 +435,31 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
        if ( (flags & I2C_M_TEN)  ) { 
                /* a ten bit address */
                addr = 0xf0 | (( msg->addr >> 7) & 0x03);
-               DEB2(printk(KERN_DEBUG "addr0: %d\n",addr));
+               bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr);
                /* try extended address code...*/
                ret = try_address(i2c_adap, addr, retries);
                if ((ret != 1) && !nak_ok)  {
-                       printk(KERN_ERR "died at extended address code.\n");
+                       dev_err(&i2c_adap->dev,
+                               "died at extended address code\n");
                        return -EREMOTEIO;
                }
                /* the remaining 8 bit address */
                ret = i2c_outb(i2c_adap,msg->addr & 0x7f);
                if ((ret != 1) && !nak_ok) {
                        /* the chip did not ack / xmission error occurred */
-                       printk(KERN_ERR "died at 2nd address code.\n");
+                       dev_err(&i2c_adap->dev, "died at 2nd address code\n");
                        return -EREMOTEIO;
                }
                if ( flags & I2C_M_RD ) {
+                       bit_dbg(3, &i2c_adap->dev, "emitting repeated "
+                               "start condition\n");
                        i2c_repstart(adap);
                        /* okay, now switch into reading mode */
                        addr |= 0x01;
                        ret = try_address(i2c_adap, addr, retries);
                        if ((ret!=1) && !nak_ok) {
-                               printk(KERN_ERR "died at extended address code.\n");
+                               dev_err(&i2c_adap->dev,
+                                       "died at repeated address code\n");
                                return -EREMOTEIO;
                        }
                }
@@ -468,44 +486,62 @@ static int bit_xfer(struct i2c_adapter *i2c_adap,
        int i,ret;
        unsigned short nak_ok;
 
+       bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");
        i2c_start(adap);
        for (i=0;i<num;i++) {
                pmsg = &msgs[i];
                nak_ok = pmsg->flags & I2C_M_IGNORE_NAK; 
                if (!(pmsg->flags & I2C_M_NOSTART)) {
                        if (i) {
+                               bit_dbg(3, &i2c_adap->dev, "emitting "
+                                       "repeated start condition\n");
                                i2c_repstart(adap);
                        }
                        ret = bit_doAddress(i2c_adap, pmsg);
                        if ((ret != 0) && !nak_ok) {
-                           DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: NAK from device addr %2.2x msg #%d\n"
-                                       ,msgs[i].addr,i));
-                           return (ret<0) ? ret : -EREMOTEIO;
+                               bit_dbg(1, &i2c_adap->dev, "NAK from "
+                                       "device addr 0x%02x msg #%d\n",
+                                       msgs[i].addr, i);
+                               goto bailout;
                        }
                }
                if (pmsg->flags & I2C_M_RD ) {
                        /* read bytes into buffer*/
                        ret = readbytes(i2c_adap, pmsg);
-                       DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: read %d bytes.\n",ret));
-                       if (ret < pmsg->len ) {
-                               return (ret<0)? ret : -EREMOTEIO;
+                       if (ret >= 1)
+                               bit_dbg(2, &i2c_adap->dev, "read %d byte%s\n",
+                                       ret, ret == 1 ? "" : "s");
+                       if (ret < pmsg->len) {
+                               if (ret >= 0)
+                                       ret = -EREMOTEIO;
+                               goto bailout;
                        }
                } else {
                        /* write bytes from buffer */
                        ret = sendbytes(i2c_adap, pmsg);
-                       DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: wrote %d bytes.\n",ret));
-                       if (ret < pmsg->len ) {
-                               return (ret<0) ? ret : -EREMOTEIO;
+                       if (ret >= 1)
+                               bit_dbg(2, &i2c_adap->dev, "wrote %d byte%s\n",
+                                       ret, ret == 1 ? "" : "s");
+                       if (ret < pmsg->len) {
+                               if (ret >= 0)
+                                       ret = -EREMOTEIO;
+                               goto bailout;
                        }
                }
        }
+       ret = i;
+
+bailout:
+       bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");
        i2c_stop(adap);
-       return num;
+       return ret;
 }
 
 static u32 bit_func(struct i2c_adapter *adap)
 {
        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | 
+              I2C_FUNC_SMBUS_READ_BLOCK_DATA |
+              I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
               I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
 }
 
@@ -520,7 +556,7 @@ static const struct i2c_algorithm i2c_bit_algo = {
 /* 
  * registering functions to load algorithms at runtime 
  */
-int i2c_bit_add_bus(struct i2c_adapter *adap)
+static int i2c_bit_prepare_bus(struct i2c_adapter *adap)
 {
        struct i2c_algo_bit_data *bit_adap = adap->algo_data;
 
@@ -530,25 +566,39 @@ int i2c_bit_add_bus(struct i2c_adapter *adap)
                        return -ENODEV;
        }
 
-       DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
-
        /* register new adapter to i2c module... */
        adap->algo = &i2c_bit_algo;
 
        adap->timeout = 100;    /* default values, should       */
        adap->retries = 3;      /* be replaced by defines       */
 
+       return 0;
+}
+
+int i2c_bit_add_bus(struct i2c_adapter *adap)
+{
+       int err;
+
+       err = i2c_bit_prepare_bus(adap);
+       if (err)
+               return err;
+
        return i2c_add_adapter(adap);
 }
 EXPORT_SYMBOL(i2c_bit_add_bus);
 
+int i2c_bit_add_numbered_bus(struct i2c_adapter *adap)
+{
+       int err;
+
+       err = i2c_bit_prepare_bus(adap);
+       if (err)
+               return err;
+
+       return i2c_add_numbered_adapter(adap);
+}
+EXPORT_SYMBOL(i2c_bit_add_numbered_bus);
+
 MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
 MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");
 MODULE_LICENSE("GPL");
-
-module_param(bit_test, bool, 0);
-module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
-
-MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");
-MODULE_PARM_DESC(i2c_debug,
-                "debug level - 0 off; 1 normal; 2,3 more verbose; 9 bit-protocol");
index ac2d505..6eaf145 100644 (file)
@@ -1,6 +1,7 @@
 /*
- * i2c-algo-sgi.c: i2c driver algorithms for SGI adapters.
- * 
+ * i2c-algo-sgi.c: i2c driver algorithm used by the VINO (SGI Indy) and
+ * MACE (SGI O2) chips.
+ *
  * This file is subject to the terms and conditions of the GNU General Public
  * License version 2 as published by the Free Software Foundation.
  *
@@ -162,8 +163,8 @@ static const struct i2c_algorithm sgi_algo = {
        .functionality  = sgi_func,
 };
 
-/* 
- * registering functions to load algorithms at runtime 
+/*
+ * registering functions to load algorithms at runtime
  */
 int i2c_sgi_add_bus(struct i2c_adapter *adap)
 {
index ece31d2..838dc1c 100644 (file)
@@ -3,11 +3,10 @@
 #
 
 menu "I2C Hardware Bus support"
-       depends on I2C
 
 config I2C_ALI1535
        tristate "ALI 1535"
-       depends on I2C && PCI
+       depends on PCI
        help
          If you say yes to this option, support will be included for the SMB
          Host controller on Acer Labs Inc. (ALI) M1535 South Bridges.  The SMB
@@ -19,7 +18,7 @@ config I2C_ALI1535
 
 config I2C_ALI1563
        tristate "ALI 1563"
-       depends on I2C && PCI && EXPERIMENTAL
+       depends on PCI && EXPERIMENTAL
        help
          If you say yes to this option, support will be included for the SMB
          Host controller on Acer Labs Inc. (ALI) M1563 South Bridges.  The SMB
@@ -31,7 +30,7 @@ config I2C_ALI1563
 
 config I2C_ALI15X3
        tristate "ALI 15x3"
-       depends on I2C && PCI
+       depends on PCI
        help
          If you say yes to this option, support will be included for the
          Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces.
@@ -41,7 +40,7 @@ config I2C_ALI15X3
 
 config I2C_AMD756
        tristate "AMD 756/766/768/8111 and nVidia nForce"
-       depends on I2C && PCI
+       depends on PCI
        help
          If you say yes to this option, support will be included for the AMD
          756/766/768 mainboard I2C interfaces.  The driver also includes
@@ -66,7 +65,7 @@ config I2C_AMD756_S4882
 
 config I2C_AMD8111
        tristate "AMD 8111"
-       depends on I2C && PCI
+       depends on PCI
        help
          If you say yes to this option, support will be included for the
          second (SMBus 2.0) AMD 8111 mainboard I2C interface.
@@ -76,14 +75,14 @@ config I2C_AMD8111
 
 config I2C_AT91
        tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
-       depends on I2C && ARCH_AT91 && EXPERIMENTAL
+       depends on ARCH_AT91 && EXPERIMENTAL
        help
          This supports the use of the I2C interface on Atmel AT91
          processors.
 
 config I2C_AU1550
        tristate "Au1550/Au1200 SMBus interface"
-       depends on I2C && (SOC_AU1550 || SOC_AU1200)
+       depends on SOC_AU1550 || SOC_AU1200
        help
          If you say yes to this option, support will be included for the
          Au1550 and Au1200 SMBus interface.
@@ -91,9 +90,25 @@ config I2C_AU1550
          This driver can also be built as a module.  If so, the module
          will be called i2c-au1550.
 
+config I2C_BLACKFIN_TWI
+       tristate "Blackfin TWI I2C support"
+       depends on BF534 || BF536 || BF537
+       help
+         This is the TWI I2C device driver for Blackfin 534/536/537.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-bfin-twi.
+
+config I2C_BLACKFIN_TWI_CLK_KHZ
+       int "Blackfin TWI I2C clock (kHz)"
+       depends on I2C_BLACKFIN_TWI
+       range 10 400
+       default 50
+       help
+         The unit of the TWI clock is kHz.
+
 config I2C_ELEKTOR
        tristate "Elektor ISA card"
-       depends on I2C && ISA && BROKEN_ON_SMP
+       depends on ISA && BROKEN_ON_SMP
        select I2C_ALGOPCF
        help
          This supports the PCF8584 ISA bus I2C adapter.  Say Y if you own
@@ -102,9 +117,17 @@ config I2C_ELEKTOR
          This support is also available as a module.  If so, the module 
          will be called i2c-elektor.
 
+config I2C_GPIO
+       tristate "GPIO-based bitbanging I2C"
+       depends on GENERIC_GPIO
+       select I2C_ALGOBIT
+       help
+         This is a very simple bitbanging I2C driver utilizing the
+         arch-neutral GPIO API to control the SCL and SDA lines.
+
 config I2C_HYDRA
        tristate "CHRP Apple Hydra Mac I/O I2C interface"
-       depends on I2C && PCI && PPC_CHRP && EXPERIMENTAL
+       depends on PCI && PPC_CHRP && EXPERIMENTAL
        select I2C_ALGOBIT
        help
          This supports the use of the I2C interface in the Apple Hydra Mac
@@ -116,7 +139,7 @@ config I2C_HYDRA
 
 config I2C_I801
        tristate "Intel 82801 (ICH)"
-       depends on I2C && PCI
+       depends on PCI
        help
          If you say yes to this option, support will be included for the Intel
          801 family of mainboard I2C interfaces.  Specifically, the following
@@ -139,7 +162,7 @@ config I2C_I801
 
 config I2C_I810
        tristate "Intel 810/815"
-       depends on I2C && PCI
+       depends on PCI
        select I2C_ALGOBIT
        help
          If you say yes to this option, support will be included for the Intel
@@ -156,7 +179,7 @@ config I2C_I810
 
 config I2C_PXA
        tristate "Intel PXA2XX I2C adapter (EXPERIMENTAL)"
-       depends on I2C && EXPERIMENTAL && ARCH_PXA
+       depends on EXPERIMENTAL && ARCH_PXA
        help
          If you have devices in the PXA I2C bus, say yes to this option.
          This driver can also be built as a module.  If so, the module
@@ -172,7 +195,7 @@ config I2C_PXA_SLAVE
 
 config I2C_PIIX4
        tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)"
-       depends on I2C && PCI
+       depends on PCI
        help
          If you say yes to this option, support will be included for the Intel
          PIIX4 family of mainboard I2C interfaces.  Specifically, the following
@@ -195,7 +218,7 @@ config I2C_PIIX4
 
 config I2C_IBM_IIC
        tristate "IBM PPC 4xx on-chip I2C interface"
-       depends on IBM_OCP && I2C
+       depends on IBM_OCP
        help
          Say Y here if you want to use IIC peripheral found on 
          embedded IBM PPC 4xx based systems. 
@@ -205,7 +228,7 @@ config I2C_IBM_IIC
 
 config I2C_IOP3XX
        tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface"
-       depends on (ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX) && I2C
+       depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX
        help
          Say Y here if you want to use the IIC bus controller on
          the Intel IOPx3xx I/O Processors or IXP4xx Network Processors.
@@ -215,11 +238,10 @@ config I2C_IOP3XX
 
 config I2C_ISA
        tristate
-       depends on I2C
 
 config I2C_IXP4XX
-       tristate "IXP4xx GPIO-Based I2C Interface"
-       depends on I2C && ARCH_IXP4XX
+       tristate "IXP4xx GPIO-Based I2C Interface (DEPRECATED)"
+       depends on ARCH_IXP4XX
        select I2C_ALGOBIT
        help
          Say Y here if you have an Intel IXP4xx(420,421,422,425) based 
@@ -228,9 +250,12 @@ config I2C_IXP4XX
          This support is also available as a module. If so, the module
          will be called i2c-ixp4xx.
 
+         This driver is deprecated and will be dropped soon. Use i2c-gpio
+         instead.
+
 config I2C_IXP2000
-       tristate "IXP2000 GPIO-Based I2C Interface"
-       depends on I2C && ARCH_IXP2000
+       tristate "IXP2000 GPIO-Based I2C Interface (DEPRECATED)"
+       depends on ARCH_IXP2000
        select I2C_ALGOBIT
        help
          Say Y here if you have an Intel IXP2000(2400, 2800, 2850) based 
@@ -239,9 +264,12 @@ config I2C_IXP2000
          This support is also available as a module. If so, the module
          will be called i2c-ixp2000.
 
+         This driver is deprecated and will be dropped soon. Use i2c-gpio
+         instead.
+
 config I2C_POWERMAC
        tristate "Powermac I2C interface"
-       depends on I2C && PPC_PMAC
+       depends on PPC_PMAC
        default y
        help
          This exposes the various PowerMac i2c interfaces to the linux i2c
@@ -253,7 +281,7 @@ config I2C_POWERMAC
 
 config I2C_MPC
        tristate "MPC107/824x/85xx/52xx/86xx"
-       depends on I2C && PPC32
+       depends on PPC32
        help
          If you say yes to this option, support will be included for the
          built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
@@ -265,7 +293,7 @@ config I2C_MPC
 
 config I2C_NFORCE2
        tristate "Nvidia nForce2, nForce3 and nForce4"
-       depends on I2C && PCI
+       depends on PCI
        help
          If you say yes to this option, support will be included for the Nvidia
          nForce2, nForce3 and nForce4 families of mainboard I2C interfaces.
@@ -275,7 +303,7 @@ config I2C_NFORCE2
 
 config I2C_OCORES
        tristate "OpenCores I2C Controller"
-       depends on I2C && EXPERIMENTAL
+       depends on EXPERIMENTAL
        help
          If you say yes to this option, support will be included for the
          OpenCores I2C controller. For details see
@@ -286,7 +314,7 @@ config I2C_OCORES
 
 config I2C_OMAP
        tristate "OMAP I2C adapter"
-       depends on I2C && ARCH_OMAP
+       depends on ARCH_OMAP
        default y if MACH_OMAP_H3 || MACH_OMAP_OSK
        help
          If you say yes to this option, support will be included for the
@@ -296,7 +324,7 @@ config I2C_OMAP
 
 config I2C_PARPORT
        tristate "Parallel port adapter"
-       depends on I2C && PARPORT
+       depends on PARPORT
        select I2C_ALGOBIT
        help
          This supports parallel port I2C adapters such as the ones made by
@@ -320,7 +348,6 @@ config I2C_PARPORT
 
 config I2C_PARPORT_LIGHT
        tristate "Parallel port adapter (light)"
-       depends on I2C
        select I2C_ALGOBIT
        help
          This supports parallel port I2C adapters such as the ones made by
@@ -344,13 +371,13 @@ config I2C_PARPORT_LIGHT
 
 config I2C_PASEMI
        tristate "PA Semi SMBus interface"
-       depends on PPC_PASEMI && I2C && PCI
+       depends on PPC_PASEMI && PCI
        help
          Supports the PA Semi PWRficient on-chip SMBus interfaces.
 
 config I2C_PROSAVAGE
        tristate "S3/VIA (Pro)Savage"
-       depends on I2C && PCI
+       depends on PCI
        select I2C_ALGOBIT
        help
          If you say yes to this option, support will be included for the
@@ -365,19 +392,19 @@ config I2C_PROSAVAGE
 
 config I2C_RPXLITE
        tristate "Embedded Planet RPX Lite/Classic support"
-       depends on (RPXLITE || RPXCLASSIC) && I2C
+       depends on RPXLITE || RPXCLASSIC
        select I2C_ALGO8XX
 
 config I2C_S3C2410
        tristate "S3C2410 I2C Driver"
-       depends on I2C && ARCH_S3C2410
+       depends on ARCH_S3C2410
        help
          Say Y here to include support for I2C controller in the
          Samsung S3C2410 based System-on-Chip devices.
 
 config I2C_SAVAGE4
        tristate "S3 Savage 4"
-       depends on I2C && PCI && EXPERIMENTAL
+       depends on PCI && EXPERIMENTAL
        select I2C_ALGOBIT
        help
          If you say yes to this option, support will be included for the 
@@ -388,13 +415,25 @@ config I2C_SAVAGE4
 
 config I2C_SIBYTE
        tristate "SiByte SMBus interface"
-       depends on SIBYTE_SB1xxx_SOC && I2C
+       depends on SIBYTE_SB1xxx_SOC
        help
          Supports the SiByte SOC on-chip I2C interfaces (2 channels).
 
+config I2C_SIMTEC
+       tristate "Simtec Generic I2C interface"
+       select I2C_ALGOBIT
+       help
+         If you say yes to this option, support will be inclyded for
+         the Simtec Generic I2C interface. This driver is for the
+         simple I2C bus used on newer Simtec products for general
+         I2C, such as DDC on the Simtec BBD2016A.
+
+         This driver can also be build as a module. If so, the module
+         will be called i2c-simtec.
+
 config SCx200_I2C
-       tristate "NatSemi SCx200 I2C using GPIO pins"
-       depends on SCx200_GPIO && I2C
+       tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)"
+       depends on SCx200_GPIO
        select I2C_ALGOBIT
        help
          Enable the use of two GPIO pins of a SCx200 processor as an I2C bus.
@@ -404,6 +443,9 @@ config SCx200_I2C
          This support is also available as a module.  If so, the module 
          will be called scx200_i2c.
 
+         This driver is deprecated and will be dropped soon. Use i2c-gpio
+         (or scx200_acb) instead.
+
 config SCx200_I2C_SCL
        int "GPIO pin used for SCL"
        depends on SCx200_I2C
@@ -422,7 +464,7 @@ config SCx200_I2C_SDA
 
 config SCx200_ACB
        tristate "Geode ACCESS.bus support"
-       depends on X86_32 && I2C && PCI
+       depends on X86_32 && PCI
        help
          Enable the use of the ACCESS.bus controllers on the Geode SCx200 and
          SC1100 processors and the CS5535 and CS5536 Geode companion devices.
@@ -434,7 +476,7 @@ config SCx200_ACB
 
 config I2C_SIS5595
        tristate "SiS 5595"
-       depends on I2C && PCI
+       depends on PCI
        help
          If you say yes to this option, support will be included for the 
          SiS5595 SMBus (a subset of I2C) interface.
@@ -444,7 +486,7 @@ config I2C_SIS5595
 
 config I2C_SIS630
        tristate "SiS 630/730"
-       depends on I2C && PCI
+       depends on PCI
        help
          If you say yes to this option, support will be included for the 
          SiS630 and SiS730 SMBus (a subset of I2C) interface.
@@ -454,7 +496,7 @@ config I2C_SIS630
 
 config I2C_SIS96X
        tristate "SiS 96x"
-       depends on I2C && PCI
+       depends on PCI
        help
          If you say yes to this option, support will be included for the SiS
          96x SMBus (a subset of I2C) interfaces.  Specifically, the following
@@ -472,7 +514,7 @@ config I2C_SIS96X
 
 config I2C_STUB
        tristate "I2C/SMBus Test Stub"
-       depends on I2C && EXPERIMENTAL && 'm'
+       depends on EXPERIMENTAL && m
        default 'n'
        help
          This module may be useful to developers of SMBus client drivers,
@@ -483,9 +525,20 @@ config I2C_STUB
 
          If you don't know what to do here, definitely say N.
 
+config I2C_TINY_USB
+       tristate "I2C-Tiny-USB"
+       depends on USB
+       help
+         If you say yes to this option, support will be included for the
+         i2c-tiny-usb, a simple do-it-yourself USB to I2C interface. See
+         http://www.harbaum.org/till/i2c_tiny_usb for hardware details.
+
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-tiny-usb.
+
 config I2C_VERSATILE
        tristate "ARM Versatile/Realview I2C bus support"
-       depends on I2C && (ARCH_VERSATILE || ARCH_REALVIEW)
+       depends on ARCH_VERSATILE || ARCH_REALVIEW
        select I2C_ALGOBIT
        help
          Say yes if you want to support the I2C serial bus on ARMs Versatile
@@ -496,7 +549,7 @@ config I2C_VERSATILE
 
 config I2C_ACORN
        bool "Acorn IOC/IOMD I2C bus support"
-       depends on I2C && ARCH_ACORN
+       depends on ARCH_ACORN
        default y
        select I2C_ALGOBIT
        help
@@ -506,7 +559,7 @@ config I2C_ACORN
 
 config I2C_VIA
        tristate "VIA 82C586B"
-       depends on I2C && PCI && EXPERIMENTAL
+       depends on PCI && EXPERIMENTAL
        select I2C_ALGOBIT
        help
          If you say yes to this option, support will be included for the VIA
@@ -517,7 +570,7 @@ config I2C_VIA
 
 config I2C_VIAPRO
        tristate "VIA VT82C596/82C686/82xx and CX700"
-       depends on I2C && PCI
+       depends on PCI
        help
          If you say yes to this option, support will be included for the VIA
          VT82C596 and later SMBus interface.  Specifically, the following
@@ -536,7 +589,7 @@ config I2C_VIAPRO
 
 config I2C_VOODOO3
        tristate "Voodoo 3"
-       depends on I2C && PCI
+       depends on PCI
        select I2C_ALGOBIT
        help
          If you say yes to this option, support will be included for the
@@ -547,7 +600,7 @@ config I2C_VOODOO3
 
 config I2C_PCA_ISA
        tristate "PCA9564 on an ISA bus"
-       depends on I2C
+       depends on ISA
        select I2C_ALGOPCA
        default n
        help
@@ -564,7 +617,7 @@ config I2C_PCA_ISA
 
 config I2C_MV64XXX
        tristate "Marvell mv64xxx I2C Controller"
-       depends on I2C && MV64X60 && EXPERIMENTAL
+       depends on MV64X60 && EXPERIMENTAL
        help
          If you say yes to this option, support will be included for the
          built-in I2C interface on the Marvell 64xxx line of host bridges.
@@ -574,7 +627,7 @@ config I2C_MV64XXX
 
 config I2C_PNX
        tristate "I2C bus support for Philips PNX targets"
-       depends on ARCH_PNX4008 && I2C
+       depends on ARCH_PNX4008
        help
          This driver supports the Philips IP3204 I2C IP block master and/or
          slave controller
index 290b540..14d1432 100644 (file)
@@ -10,7 +10,9 @@ obj-$(CONFIG_I2C_AMD756_S4882)        += i2c-amd756-s4882.o
 obj-$(CONFIG_I2C_AMD8111)      += i2c-amd8111.o
 obj-$(CONFIG_I2C_AT91)         += i2c-at91.o
 obj-$(CONFIG_I2C_AU1550)       += i2c-au1550.o
+obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
 obj-$(CONFIG_I2C_ELEKTOR)      += i2c-elektor.o
+obj-$(CONFIG_I2C_GPIO)         += i2c-gpio.o
 obj-$(CONFIG_I2C_HYDRA)                += i2c-hydra.o
 obj-$(CONFIG_I2C_I801)         += i2c-i801.o
 obj-$(CONFIG_I2C_I810)         += i2c-i810.o
@@ -37,10 +39,12 @@ obj-$(CONFIG_I2C_RPXLITE)   += i2c-rpx.o
 obj-$(CONFIG_I2C_S3C2410)      += i2c-s3c2410.o
 obj-$(CONFIG_I2C_SAVAGE4)      += i2c-savage4.o
 obj-$(CONFIG_I2C_SIBYTE)       += i2c-sibyte.o
+obj-$(CONFIG_I2C_SIMTEC)       += i2c-simtec.o
 obj-$(CONFIG_I2C_SIS5595)      += i2c-sis5595.o
 obj-$(CONFIG_I2C_SIS630)       += i2c-sis630.o
 obj-$(CONFIG_I2C_SIS96X)       += i2c-sis96x.o
 obj-$(CONFIG_I2C_STUB)         += i2c-stub.o
+obj-$(CONFIG_I2C_TINY_USB)     += i2c-tiny-usb.o
 obj-$(CONFIG_I2C_VERSATILE)    += i2c-versatile.o
 obj-$(CONFIG_I2C_ACORN)                += i2c-acorn.o
 obj-$(CONFIG_I2C_VIA)          += i2c-via.o
index 1e277ba..f14372a 100644 (file)
@@ -497,7 +497,7 @@ static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_
        /* set up the sysfs linkage to our parent device */
        ali1535_adapter.dev.parent = &dev->dev;
 
-       snprintf(ali1535_adapter.name, I2C_NAME_SIZE, 
+       snprintf(ali1535_adapter.name, sizeof(ali1535_adapter.name),
                "SMBus ALI1535 adapter at %04x", ali1535_smba);
        return i2c_add_adapter(&ali1535_adapter);
 }
index e47fe01..93bf87d 100644 (file)
@@ -492,7 +492,7 @@ static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_
        /* set up the sysfs linkage to our parent device */
        ali15x3_adapter.dev.parent = &dev->dev;
 
-       snprintf(ali15x3_adapter.name, I2C_NAME_SIZE,
+       snprintf(ali15x3_adapter.name, sizeof(ali15x3_adapter.name),
                "SMBus ALI15X3 adapter at %04x", ali15x3_smba);
        return i2c_add_adapter(&ali15x3_adapter);
 }
index 0c70f82..c9fca7b 100644 (file)
@@ -365,7 +365,7 @@ static int __devinit amd8111_probe(struct pci_dev *dev,
        }
 
        smbus->adapter.owner = THIS_MODULE;
-       snprintf(smbus->adapter.name, I2C_NAME_SIZE,
+       snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
                "SMBus2 AMD8111 adapter at %04x", smbus->base);
        smbus->adapter.id = I2C_HW_SMBUS_AMD8111;
        smbus->adapter.class = I2C_CLASS_HWMON;
index 67f91bd..f35156c 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/pci.h>
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
new file mode 100644 (file)
index 0000000..6311039
--- /dev/null
@@ -0,0 +1,644 @@
+/*
+ * drivers/i2c/busses/i2c-bfin-twi.c
+ *
+ * Description: Driver for Blackfin Two Wire Interface
+ *
+ * Author:      sonicz  <sonic.zhang@analog.com>
+ *
+ * Copyright (c) 2005-2007 Analog Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/mm.h>
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <asm/blackfin.h>
+#include <asm/irq.h>
+
+#define POLL_TIMEOUT       (2 * HZ)
+
+/* SMBus mode*/
+#define TWI_I2C_MODE_STANDARD          0x01
+#define TWI_I2C_MODE_STANDARDSUB       0x02
+#define TWI_I2C_MODE_COMBINED          0x04
+
+struct bfin_twi_iface {
+       struct mutex            twi_lock;
+       int                     irq;
+       spinlock_t              lock;
+       char                    read_write;
+       u8                      command;
+       u8                      *transPtr;
+       int                     readNum;
+       int                     writeNum;
+       int                     cur_mode;
+       int                     manual_stop;
+       int                     result;
+       int                     timeout_count;
+       struct timer_list       timeout_timer;
+       struct i2c_adapter      adap;
+       struct completion       complete;
+};
+
+static struct bfin_twi_iface twi_iface;
+
+static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
+{
+       unsigned short twi_int_status = bfin_read_TWI_INT_STAT();
+       unsigned short mast_stat = bfin_read_TWI_MASTER_STAT();
+
+       if (twi_int_status & XMTSERV) {
+               /* Transmit next data */
+               if (iface->writeNum > 0) {
+                       bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
+                       iface->writeNum--;
+               }
+               /* start receive immediately after complete sending in
+                * combine mode.
+                */
+               else if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
+                       bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
+                               | MDIR | RSTART);
+               } else if (iface->manual_stop)
+                       bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
+                               | STOP);
+               SSYNC();
+               /* Clear status */
+               bfin_write_TWI_INT_STAT(XMTSERV);
+               SSYNC();
+       }
+       if (twi_int_status & RCVSERV) {
+               if (iface->readNum > 0) {
+                       /* Receive next data */
+                       *(iface->transPtr) = bfin_read_TWI_RCV_DATA8();
+                       if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
+                               /* Change combine mode into sub mode after
+                                * read first data.
+                                */
+                               iface->cur_mode = TWI_I2C_MODE_STANDARDSUB;
+                               /* Get read number from first byte in block
+                                * combine mode.
+                                */
+                               if (iface->readNum == 1 && iface->manual_stop)
+                                       iface->readNum = *iface->transPtr + 1;
+                       }
+                       iface->transPtr++;
+                       iface->readNum--;
+               } else if (iface->manual_stop) {
+                       bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
+                               | STOP);
+                       SSYNC();
+               }
+               /* Clear interrupt source */
+               bfin_write_TWI_INT_STAT(RCVSERV);
+               SSYNC();
+       }
+       if (twi_int_status & MERR) {
+               bfin_write_TWI_INT_STAT(MERR);
+               bfin_write_TWI_INT_MASK(0);
+               bfin_write_TWI_MASTER_STAT(0x3e);
+               bfin_write_TWI_MASTER_CTL(0);
+               SSYNC();
+               iface->result = -1;
+               /* if both err and complete int stats are set, return proper
+                * results.
+                */
+               if (twi_int_status & MCOMP) {
+                       bfin_write_TWI_INT_STAT(MCOMP);
+                       bfin_write_TWI_INT_MASK(0);
+                       bfin_write_TWI_MASTER_CTL(0);
+                       SSYNC();
+                       /* If it is a quick transfer, only address bug no data,
+                        * not an err, return 1.
+                        */
+                       if (iface->writeNum == 0 && (mast_stat & BUFRDERR))
+                               iface->result = 1;
+                       /* If address not acknowledged return -1,
+                        * else return 0.
+                        */
+                       else if (!(mast_stat & ANAK))
+                               iface->result = 0;
+               }
+               complete(&iface->complete);
+               return;
+       }
+       if (twi_int_status & MCOMP) {
+               bfin_write_TWI_INT_STAT(MCOMP);
+               SSYNC();
+               if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
+                       if (iface->readNum == 0) {
+                               /* set the read number to 1 and ask for manual
+                                * stop in block combine mode
+                                */
+                               iface->readNum = 1;
+                               iface->manual_stop = 1;
+                               bfin_write_TWI_MASTER_CTL(
+                                       bfin_read_TWI_MASTER_CTL()
+                                       | (0xff << 6));
+                       } else {
+                               /* set the readd number in other
+                                * combine mode.
+                                */
+                               bfin_write_TWI_MASTER_CTL(
+                                       (bfin_read_TWI_MASTER_CTL() &
+                                       (~(0xff << 6))) |
+                                       ( iface->readNum << 6));
+                       }
+                       /* remove restart bit and enable master receive */
+                       bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() &
+                               ~RSTART);
+                       bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() |
+                               MEN | MDIR);
+                       SSYNC();
+               } else {
+                       iface->result = 1;
+                       bfin_write_TWI_INT_MASK(0);
+                       bfin_write_TWI_MASTER_CTL(0);
+                       SSYNC();
+                       complete(&iface->complete);
+               }
+       }
+}
+
+/* Interrupt handler */
+static irqreturn_t bfin_twi_interrupt_entry(int irq, void *dev_id)
+{
+       struct bfin_twi_iface *iface = dev_id;
+       unsigned long flags;
+
+       spin_lock_irqsave(&iface->lock, flags);
+       del_timer(&iface->timeout_timer);
+       bfin_twi_handle_interrupt(iface);
+       spin_unlock_irqrestore(&iface->lock, flags);
+       return IRQ_HANDLED;
+}
+
+static void bfin_twi_timeout(unsigned long data)
+{
+       struct bfin_twi_iface *iface = (struct bfin_twi_iface *)data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&iface->lock, flags);
+       bfin_twi_handle_interrupt(iface);
+       if (iface->result == 0) {
+               iface->timeout_count--;
+               if (iface->timeout_count > 0) {
+                       iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
+                       add_timer(&iface->timeout_timer);
+               } else {
+                       iface->result = -1;
+                       complete(&iface->complete);
+               }
+       }
+       spin_unlock_irqrestore(&iface->lock, flags);
+}
+
+/*
+ * Generic i2c master transfer entrypoint
+ */
+static int bfin_twi_master_xfer(struct i2c_adapter *adap,
+                               struct i2c_msg *msgs, int num)
+{
+       struct bfin_twi_iface *iface = adap->algo_data;
+       struct i2c_msg *pmsg;
+       int i, ret;
+       int rc = 0;
+
+       if (!(bfin_read_TWI_CONTROL() & TWI_ENA))
+               return -ENXIO;
+
+       mutex_lock(&iface->twi_lock);
+
+       while (bfin_read_TWI_MASTER_STAT() & BUSBUSY) {
+               mutex_unlock(&iface->twi_lock);
+               yield();
+               mutex_lock(&iface->twi_lock);
+       }
+
+       ret = 0;
+       for (i = 0; rc >= 0 && i < num; i++) {
+               pmsg = &msgs[i];
+               if (pmsg->flags & I2C_M_TEN) {
+                       dev_err(&(adap->dev), "i2c-bfin-twi: 10 bits addr "
+                               "not supported !\n");
+                       rc = -EINVAL;
+                       break;
+               }
+
+               iface->cur_mode = TWI_I2C_MODE_STANDARD;
+               iface->manual_stop = 0;
+               iface->transPtr = pmsg->buf;
+               iface->writeNum = iface->readNum = pmsg->len;
+               iface->result = 0;
+               iface->timeout_count = 10;
+               /* Set Transmit device address */
+               bfin_write_TWI_MASTER_ADDR(pmsg->addr);
+
+               /* FIFO Initiation. Data in FIFO should be
+                *  discarded before start a new operation.
+                */
+               bfin_write_TWI_FIFO_CTL(0x3);
+               SSYNC();
+               bfin_write_TWI_FIFO_CTL(0);
+               SSYNC();
+
+               if (pmsg->flags & I2C_M_RD)
+                       iface->read_write = I2C_SMBUS_READ;
+               else {
+                       iface->read_write = I2C_SMBUS_WRITE;
+                       /* Transmit first data */
+                       if (iface->writeNum > 0) {
+                               bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
+                               iface->writeNum--;
+                               SSYNC();
+                       }
+               }
+
+               /* clear int stat */
+               bfin_write_TWI_INT_STAT(MERR|MCOMP|XMTSERV|RCVSERV);
+
+               /* Interrupt mask . Enable XMT, RCV interrupt */
+               bfin_write_TWI_INT_MASK(MCOMP | MERR |
+                       ((iface->read_write == I2C_SMBUS_READ)?
+                       RCVSERV : XMTSERV));
+               SSYNC();
+
+               if (pmsg->len > 0 && pmsg->len <= 255)
+                       bfin_write_TWI_MASTER_CTL(pmsg->len << 6);
+               else if (pmsg->len > 255) {
+                       bfin_write_TWI_MASTER_CTL(0xff << 6);
+                       iface->manual_stop = 1;
+               } else
+                       break;
+
+               iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
+               add_timer(&iface->timeout_timer);
+
+               /* Master enable */
+               bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
+                       ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
+                       ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));
+               SSYNC();
+
+               wait_for_completion(&iface->complete);
+
+               rc = iface->result;
+               if (rc == 1)
+                       ret++;
+               else if (rc == -1)
+                       break;
+       }
+
+       /* Release mutex */
+       mutex_unlock(&iface->twi_lock);
+
+       return ret;
+}
+
+/*
+ * SMBus type transfer entrypoint
+ */
+
+int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+                       unsigned short flags, char read_write,
+                       u8 command, int size, union i2c_smbus_data *data)
+{
+       struct bfin_twi_iface *iface = adap->algo_data;
+       int rc = 0;
+
+       if (!(bfin_read_TWI_CONTROL() & TWI_ENA))
+               return -ENXIO;
+
+       mutex_lock(&iface->twi_lock);
+
+       while (bfin_read_TWI_MASTER_STAT() & BUSBUSY) {
+               mutex_unlock(&iface->twi_lock);
+               yield();
+               mutex_lock(&iface->twi_lock);
+       }
+
+       iface->writeNum = 0;
+       iface->readNum = 0;
+
+       /* Prepare datas & select mode */
+       switch (size) {
+       case I2C_SMBUS_QUICK:
+               iface->transPtr = NULL;
+               iface->cur_mode = TWI_I2C_MODE_STANDARD;
+               break;
+       case I2C_SMBUS_BYTE:
+               if (data == NULL)
+                       iface->transPtr = NULL;
+               else {
+                       if (read_write == I2C_SMBUS_READ)
+                               iface->readNum = 1;
+                       else
+                               iface->writeNum = 1;
+                       iface->transPtr = &data->byte;
+               }
+               iface->cur_mode = TWI_I2C_MODE_STANDARD;
+               break;
+       case I2C_SMBUS_BYTE_DATA:
+               if (read_write == I2C_SMBUS_READ) {
+                       iface->readNum = 1;
+                       iface->cur_mode = TWI_I2C_MODE_COMBINED;
+               } else {
+                       iface->writeNum = 1;
+                       iface->cur_mode = TWI_I2C_MODE_STANDARDSUB;
+               }
+               iface->transPtr = &data->byte;
+               break;
+       case I2C_SMBUS_WORD_DATA:
+               if (read_write == I2C_SMBUS_READ) {
+                       iface->readNum = 2;
+                       iface->cur_mode = TWI_I2C_MODE_COMBINED;
+               } else {
+                       iface->writeNum = 2;
+                       iface->cur_mode = TWI_I2C_MODE_STANDARDSUB;
+               }
+               iface->transPtr = (u8 *)&data->word;
+               break;
+       case I2C_SMBUS_PROC_CALL:
+               iface->writeNum = 2;
+               iface->readNum = 2;
+               iface->cur_mode = TWI_I2C_MODE_COMBINED;
+               iface->transPtr = (u8 *)&data->word;
+               break;
+       case I2C_SMBUS_BLOCK_DATA:
+               if (read_write == I2C_SMBUS_READ) {
+                       iface->readNum = 0;
+                       iface->cur_mode = TWI_I2C_MODE_COMBINED;
+               } else {
+                       iface->writeNum = data->block[0] + 1;
+                       iface->cur_mode = TWI_I2C_MODE_STANDARDSUB;
+               }
+               iface->transPtr = data->block;
+               break;
+       default:
+               return -1;
+       }
+
+       iface->result = 0;
+       iface->manual_stop = 0;
+       iface->read_write = read_write;
+       iface->command = command;
+       iface->timeout_count = 10;
+
+       /* FIFO Initiation. Data in FIFO should be discarded before
+        * start a new operation.
+        */
+       bfin_write_TWI_FIFO_CTL(0x3);
+       SSYNC();
+       bfin_write_TWI_FIFO_CTL(0);
+
+       /* clear int stat */
+       bfin_write_TWI_INT_STAT(MERR|MCOMP|XMTSERV|RCVSERV);
+
+       /* Set Transmit device address */
+       bfin_write_TWI_MASTER_ADDR(addr);
+       SSYNC();
+
+       iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
+       add_timer(&iface->timeout_timer);
+
+       switch (iface->cur_mode) {
+       case TWI_I2C_MODE_STANDARDSUB:
+               bfin_write_TWI_XMT_DATA8(iface->command);
+               bfin_write_TWI_INT_MASK(MCOMP | MERR |
+                       ((iface->read_write == I2C_SMBUS_READ) ?
+                       RCVSERV : XMTSERV));
+               SSYNC();
+
+               if (iface->writeNum + 1 <= 255)
+                       bfin_write_TWI_MASTER_CTL((iface->writeNum + 1) << 6);
+               else {
+                       bfin_write_TWI_MASTER_CTL(0xff << 6);
+                       iface->manual_stop = 1;
+               }
+               /* Master enable */
+               bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
+                       ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));
+               break;
+       case TWI_I2C_MODE_COMBINED:
+               bfin_write_TWI_XMT_DATA8(iface->command);
+               bfin_write_TWI_INT_MASK(MCOMP | MERR | RCVSERV | XMTSERV);
+               SSYNC();
+
+               if (iface->writeNum > 0)
+                       bfin_write_TWI_MASTER_CTL((iface->writeNum + 1) << 6);
+               else
+                       bfin_write_TWI_MASTER_CTL(0x1 << 6);
+               /* Master enable */
+               bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
+                       ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));
+               break;
+       default:
+               bfin_write_TWI_MASTER_CTL(0);
+               if (size != I2C_SMBUS_QUICK) {
+                       /* Don't access xmit data register when this is a
+                        * read operation.
+                        */
+                       if (iface->read_write != I2C_SMBUS_READ) {
+                               if (iface->writeNum > 0) {
+                                       bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
+                                       if (iface->writeNum <= 255)
+                                               bfin_write_TWI_MASTER_CTL(iface->writeNum << 6);
+                                       else {
+                                               bfin_write_TWI_MASTER_CTL(0xff << 6);
+                                               iface->manual_stop = 1;
+                                       }
+                                       iface->writeNum--;
+                               } else {
+                                       bfin_write_TWI_XMT_DATA8(iface->command);
+                                       bfin_write_TWI_MASTER_CTL(1 << 6);
+                               }
+                       } else {
+                               if (iface->readNum > 0 && iface->readNum <= 255)
+                                       bfin_write_TWI_MASTER_CTL(iface->readNum << 6);
+                               else if (iface->readNum > 255) {
+                                       bfin_write_TWI_MASTER_CTL(0xff << 6);
+                                       iface->manual_stop = 1;
+                               } else {
+                                       del_timer(&iface->timeout_timer);
+                                       break;
+                               }
+                       }
+               }
+               bfin_write_TWI_INT_MASK(MCOMP | MERR |
+                       ((iface->read_write == I2C_SMBUS_READ) ?
+                       RCVSERV : XMTSERV));
+               SSYNC();
+
+               /* Master enable */
+               bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
+                       ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
+                       ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0));
+               break;
+       }
+       SSYNC();
+
+       wait_for_completion(&iface->complete);
+
+       rc = (iface->result >= 0) ? 0 : -1;
+
+       /* Release mutex */
+       mutex_unlock(&iface->twi_lock);
+
+       return rc;
+}
+
+/*
+ * Return what the adapter supports
+ */
+static u32 bfin_twi_functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+              I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+              I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL |
+              I2C_FUNC_I2C;
+}
+
+
+static struct i2c_algorithm bfin_twi_algorithm = {
+       .master_xfer   = bfin_twi_master_xfer,
+       .smbus_xfer    = bfin_twi_smbus_xfer,
+       .functionality = bfin_twi_functionality,
+};
+
+
+static int i2c_bfin_twi_suspend(struct platform_device *dev, pm_message_t state)
+{
+/*     struct bfin_twi_iface *iface = platform_get_drvdata(dev);*/
+
+       /* Disable TWI */
+       bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() & ~TWI_ENA);
+       SSYNC();
+
+       return 0;
+}
+
+static int i2c_bfin_twi_resume(struct platform_device *dev)
+{
+/*     struct bfin_twi_iface *iface = platform_get_drvdata(dev);*/
+
+       /* Enable TWI */
+       bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA);
+       SSYNC();
+
+       return 0;
+}
+
+static int i2c_bfin_twi_probe(struct platform_device *dev)
+{
+       struct bfin_twi_iface *iface = &twi_iface;
+       struct i2c_adapter *p_adap;
+       int rc;
+
+       mutex_init(&(iface->twi_lock));
+       spin_lock_init(&(iface->lock));
+       init_completion(&(iface->complete));
+       iface->irq = IRQ_TWI;
+
+       init_timer(&(iface->timeout_timer));
+       iface->timeout_timer.function = bfin_twi_timeout;
+       iface->timeout_timer.data = (unsigned long)iface;
+
+       p_adap = &iface->adap;
+       p_adap->id = I2C_HW_BLACKFIN;
+       strlcpy(p_adap->name, dev->name, sizeof(p_adap->name));
+       p_adap->algo = &bfin_twi_algorithm;
+       p_adap->algo_data = iface;
+       p_adap->class = I2C_CLASS_ALL;
+       p_adap->dev.parent = &dev->dev;
+
+       rc = request_irq(iface->irq, bfin_twi_interrupt_entry,
+               IRQF_DISABLED, dev->name, iface);
+       if (rc) {
+               dev_err(&(p_adap->dev), "i2c-bfin-twi: can't get IRQ %d !\n",
+                       iface->irq);
+               return -ENODEV;
+       }
+
+       /* Set TWI internal clock as 10MHz */
+       bfin_write_TWI_CONTROL(((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F);
+
+       /* Set Twi interface clock as specified */
+       bfin_write_TWI_CLKDIV((( 5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ )
+                       << 8) | (( 5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ )
+                       & 0xFF));
+
+       /* Enable TWI */
+       bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA);
+       SSYNC();
+
+       rc = i2c_add_adapter(p_adap);
+       if (rc < 0)
+               free_irq(iface->irq, iface);
+       else
+               platform_set_drvdata(dev, iface);
+
+       return rc;
+}
+
+static int i2c_bfin_twi_remove(struct platform_device *pdev)
+{
+       struct bfin_twi_iface *iface = platform_get_drvdata(pdev);
+
+       platform_set_drvdata(pdev, NULL);
+
+       i2c_del_adapter(&(iface->adap));
+       free_irq(iface->irq, iface);
+
+       return 0;
+}
+
+static struct platform_driver i2c_bfin_twi_driver = {
+       .probe          = i2c_bfin_twi_probe,
+       .remove         = i2c_bfin_twi_remove,
+       .suspend        = i2c_bfin_twi_suspend,
+       .resume         = i2c_bfin_twi_resume,
+       .driver         = {
+               .name   = "i2c-bfin-twi",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init i2c_bfin_twi_init(void)
+{
+       pr_info("I2C: Blackfin I2C TWI driver\n");
+
+       return platform_driver_register(&i2c_bfin_twi_driver);
+}
+
+static void __exit i2c_bfin_twi_exit(void)
+{
+       platform_driver_unregister(&i2c_bfin_twi_driver);
+}
+
+MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
+MODULE_DESCRIPTION("I2C-Bus adapter routines for Blackfin TWI");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_bfin_twi_init);
+module_exit(i2c_bfin_twi_exit);
index 8349674..804f0a5 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/pci.h>
 #include <linux/wait.h>
 
+#include <linux/isa.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-pcf.h>
 
@@ -207,7 +208,7 @@ static struct i2c_adapter pcf_isa_ops = {
        .name           = "i2c-elektor",
 };
 
-static int __init i2c_pcfisa_init(void)
+static int __devinit elektor_match(struct device *dev, unsigned int id)
 {
 #ifdef __alpha__
        /* check to see we have memory mapped PCF8584 connected to the
@@ -222,9 +223,8 @@ static int __init i2c_pcfisa_init(void)
                        /* yeap, we've found cypress, let's check config */
                        if (!pci_read_config_byte(cy693_dev, 0x47, &config)) {
 
-                               pr_debug("%s: found cy82c693, config "
-                                        "register 0x47 = 0x%02x\n",
-                                        pcf_isa_ops.name, config);
+                               dev_dbg(dev, "found cy82c693, config "
+                                       "register 0x47 = 0x%02x\n", config);
 
                                /* UP2000 board has this register set to 0xe1,
                                   but the most significant bit as seems can be
@@ -244,9 +244,9 @@ static int __init i2c_pcfisa_init(void)
                                           8.25 MHz (PCI/4) clock
                                           (this can be read from cypress) */
                                        clock = I2C_PCF_CLK | I2C_PCF_TRNS90;
-                                       pr_info("%s: found API UP2000 like "
-                                               "board, will probe PCF8584 "
-                                               "later\n", pcf_isa_ops.name);
+                                       dev_info(dev, "found API UP2000 like "
+                                                "board, will probe PCF8584 "
+                                                "later\n");
                                }
                        }
                        pci_dev_put(cy693_dev);
@@ -256,22 +256,27 @@ static int __init i2c_pcfisa_init(void)
 
        /* sanity checks for mmapped I/O */
        if (mmapped && base < 0xc8000) {
-               printk(KERN_ERR "%s: incorrect base address (%#x) specified "
-                      "for mmapped I/O\n", pcf_isa_ops.name, base);
-               return -ENODEV;
+               dev_err(dev, "incorrect base address (%#x) specified "
+                      "for mmapped I/O\n", base);
+               return 0;
        }
 
        if (base == 0) {
                base = DEFAULT_BASE;
        }
+       return 1;
+}
 
+static int __devinit elektor_probe(struct device *dev, unsigned int id)
+{
        init_waitqueue_head(&pcf_wait);
        if (pcf_isa_init())
                return -ENODEV;
+       pcf_isa_ops.dev.parent = dev;
        if (i2c_pcf_add_bus(&pcf_isa_ops) < 0)
                goto fail;
 
-       dev_info(&pcf_isa_ops.dev, "found device at %#x\n", base);
+       dev_info(dev, "found device at %#x\n", base);
 
        return 0;
 
@@ -291,7 +296,7 @@ static int __init i2c_pcfisa_init(void)
        return -ENODEV;
 }
 
-static void i2c_pcfisa_exit(void)
+static int __devexit elektor_remove(struct device *dev, unsigned int id)
 {
        i2c_del_adapter(&pcf_isa_ops);
 
@@ -307,6 +312,28 @@ static void i2c_pcfisa_exit(void)
                iounmap(base_iomem);
                release_mem_region(base, 2);
        }
+
+       return 0;
+}
+
+static struct isa_driver i2c_elektor_driver = {
+       .match          = elektor_match,
+       .probe          = elektor_probe,
+       .remove         = __devexit_p(elektor_remove),
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = "i2c-elektor",
+       },
+};
+
+static int __init i2c_pcfisa_init(void)
+{
+       return isa_register_driver(&i2c_elektor_driver, 1);
+}
+
+static void __exit i2c_pcfisa_exit(void)
+{
+       isa_unregister_driver(&i2c_elektor_driver);
 }
 
 MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
new file mode 100644 (file)
index 0000000..a7dd546
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Bitbanging I2C bus driver using the GPIO API
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/i2c-gpio.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/gpio.h>
+
+/* Toggle SDA by changing the direction of the pin */
+static void i2c_gpio_setsda_dir(void *data, int state)
+{
+       struct i2c_gpio_platform_data *pdata = data;
+
+       if (state)
+               gpio_direction_input(pdata->sda_pin);
+       else
+               gpio_direction_output(pdata->sda_pin, 0);
+}
+
+/*
+ * Toggle SDA by changing the output value of the pin. This is only
+ * valid for pins configured as open drain (i.e. setting the value
+ * high effectively turns off the output driver.)
+ */
+static void i2c_gpio_setsda_val(void *data, int state)
+{
+       struct i2c_gpio_platform_data *pdata = data;
+
+       gpio_set_value(pdata->sda_pin, state);
+}
+
+/* Toggle SCL by changing the direction of the pin. */
+static void i2c_gpio_setscl_dir(void *data, int state)
+{
+       struct i2c_gpio_platform_data *pdata = data;
+
+       if (state)
+               gpio_direction_input(pdata->scl_pin);
+       else
+               gpio_direction_output(pdata->scl_pin, 0);
+}
+
+/*
+ * Toggle SCL by changing the output value of the pin. This is used
+ * for pins that are configured as open drain and for output-only
+ * pins. The latter case will break the i2c protocol, but it will
+ * often work in practice.
+ */
+static void i2c_gpio_setscl_val(void *data, int state)
+{
+       struct i2c_gpio_platform_data *pdata = data;
+
+       gpio_set_value(pdata->scl_pin, state);
+}
+
+int i2c_gpio_getsda(void *data)
+{
+       struct i2c_gpio_platform_data *pdata = data;
+
+       return gpio_get_value(pdata->sda_pin);
+}
+
+int i2c_gpio_getscl(void *data)
+{
+       struct i2c_gpio_platform_data *pdata = data;
+
+       return gpio_get_value(pdata->scl_pin);
+}
+
+static int __init i2c_gpio_probe(struct platform_device *pdev)
+{
+       struct i2c_gpio_platform_data *pdata;
+       struct i2c_algo_bit_data *bit_data;
+       struct i2c_adapter *adap;
+       int ret;
+
+       pdata = pdev->dev.platform_data;
+       if (!pdata)
+               return -ENXIO;
+
+       ret = -ENOMEM;
+       adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
+       if (!adap)
+               goto err_alloc_adap;
+       bit_data = kzalloc(sizeof(struct i2c_algo_bit_data), GFP_KERNEL);
+       if (!bit_data)
+               goto err_alloc_bit_data;
+
+       ret = gpio_request(pdata->sda_pin, "sda");
+       if (ret)
+               goto err_request_sda;
+       ret = gpio_request(pdata->scl_pin, "scl");
+       if (ret)
+               goto err_request_scl;
+
+       if (pdata->sda_is_open_drain) {
+               gpio_direction_output(pdata->sda_pin, 1);
+               bit_data->setsda = i2c_gpio_setsda_val;
+       } else {
+               gpio_direction_input(pdata->sda_pin);
+               bit_data->setsda = i2c_gpio_setsda_dir;
+       }
+
+       if (pdata->scl_is_open_drain || pdata->scl_is_output_only) {
+               gpio_direction_output(pdata->scl_pin, 1);
+               bit_data->setscl = i2c_gpio_setscl_val;
+       } else {
+               gpio_direction_input(pdata->scl_pin);
+               bit_data->setscl = i2c_gpio_setscl_dir;
+       }
+
+       if (!pdata->scl_is_output_only)
+               bit_data->getscl = i2c_gpio_getscl;
+       bit_data->getsda = i2c_gpio_getsda;
+
+       if (pdata->udelay)
+               bit_data->udelay = pdata->udelay;
+       else if (pdata->scl_is_output_only)
+               bit_data->udelay = 50;                  /* 10 kHz */
+       else
+               bit_data->udelay = 5;                   /* 100 kHz */
+
+       if (pdata->timeout)
+               bit_data->timeout = pdata->timeout;
+       else
+               bit_data->timeout = HZ / 10;            /* 100 ms */
+
+       bit_data->data = pdata;
+
+       adap->owner = THIS_MODULE;
+       snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
+       adap->algo_data = bit_data;
+       adap->dev.parent = &pdev->dev;
+
+       ret = i2c_bit_add_bus(adap);
+       if (ret)
+               goto err_add_bus;
+
+       platform_set_drvdata(pdev, adap);
+
+       dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n",
+                pdata->sda_pin, pdata->scl_pin,
+                pdata->scl_is_output_only
+                ? ", no clock stretching" : "");
+
+       return 0;
+
+err_add_bus:
+       gpio_free(pdata->scl_pin);
+err_request_scl:
+       gpio_free(pdata->sda_pin);
+err_request_sda:
+       kfree(bit_data);
+err_alloc_bit_data:
+       kfree(adap);
+err_alloc_adap:
+       return ret;
+}
+
+static int __exit i2c_gpio_remove(struct platform_device *pdev)
+{
+       struct i2c_gpio_platform_data *pdata;
+       struct i2c_adapter *adap;
+
+       adap = platform_get_drvdata(pdev);
+       pdata = pdev->dev.platform_data;
+
+       i2c_del_adapter(adap);
+       gpio_free(pdata->scl_pin);
+       gpio_free(pdata->sda_pin);
+       kfree(adap->algo_data);
+       kfree(adap);
+
+       return 0;
+}
+
+static struct platform_driver i2c_gpio_driver = {
+       .driver         = {
+               .name   = "i2c-gpio",
+               .owner  = THIS_MODULE,
+       },
+       .remove         = __exit_p(i2c_gpio_remove),
+};
+
+static int __init i2c_gpio_init(void)
+{
+       int ret;
+
+       ret = platform_driver_probe(&i2c_gpio_driver, i2c_gpio_probe);
+       if (ret)
+               printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret);
+
+       return ret;
+}
+module_init(i2c_gpio_init);
+
+static void __exit i2c_gpio_exit(void)
+{
+       platform_driver_unregister(&i2c_gpio_driver);
+}
+module_exit(i2c_gpio_exit);
+
+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
+MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver");
+MODULE_LICENSE("GPL");
index a320e7d..611b571 100644 (file)
@@ -527,7 +527,7 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
        /* set up the sysfs linkage to our parent device */
        i801_adapter.dev.parent = &dev->dev;
 
-       snprintf(i801_adapter.name, I2C_NAME_SIZE,
+       snprintf(i801_adapter.name, sizeof(i801_adapter.name),
                "SMBus I801 adapter at %04lx", i801_smba);
        err = i2c_add_adapter(&i801_adapter);
        if (err) {
index 5f33bc9..b0e1370 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/completion.h>
 
+/* Exported by i2c-core for i2c-isa only */
+extern void i2c_adapter_dev_release(struct device *dev);
+extern struct class i2c_adapter_class;
+
 static u32 isa_func(struct i2c_adapter *adapter);
 
 /* This is the actual algorithm we define */
@@ -64,16 +68,6 @@ static u32 isa_func(struct i2c_adapter *adapter)
 }
 
 
-/* Copied from i2c-core */
-static ssize_t show_adapter_name(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
-       return sprintf(buf, "%s\n", adap->name);
-}
-static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
-
-
 /* We implement an interface which resembles i2c_{add,del}_driver,
    but for i2c-isa drivers. We don't have to remember and handle lists
    of drivers and adapters so this is much more simple, of course. */
@@ -139,41 +133,18 @@ static int __init i2c_isa_init(void)
        isa_adapter.nr = ANY_I2C_ISA_BUS;
        isa_adapter.dev.parent = &platform_bus;
        sprintf(isa_adapter.dev.bus_id, "i2c-%d", isa_adapter.nr);
-       isa_adapter.dev.driver = &i2c_adapter_driver;
        isa_adapter.dev.release = &i2c_adapter_dev_release;
+       isa_adapter.dev.class = &i2c_adapter_class;
        err = device_register(&isa_adapter.dev);
        if (err) {
                printk(KERN_ERR "i2c-isa: Failed to register device\n");
                goto exit;
        }
-       err = device_create_file(&isa_adapter.dev, &dev_attr_name);
-       if (err) {
-               printk(KERN_ERR "i2c-isa: Failed to create name file\n");
-               goto exit_unregister;
-       }
-
-       /* Add this adapter to the i2c_adapter class */
-       memset(&isa_adapter.class_dev, 0x00, sizeof(struct class_device));
-       isa_adapter.class_dev.dev = &isa_adapter.dev;
-       isa_adapter.class_dev.class = &i2c_adapter_class;
-       strlcpy(isa_adapter.class_dev.class_id, isa_adapter.dev.bus_id,
-               BUS_ID_SIZE);
-       err = class_device_register(&isa_adapter.class_dev);
-       if (err) {
-               printk(KERN_ERR "i2c-isa: Failed to register class device\n");
-               goto exit_remove_name;
-       }
 
        dev_dbg(&isa_adapter.dev, "%s registered\n", isa_adapter.name);
 
        return 0;
 
-exit_remove_name:
-       device_remove_file(&isa_adapter.dev, &dev_attr_name);
-exit_unregister:
-       init_completion(&isa_adapter.dev_released); /* Needed? */
-       device_unregister(&isa_adapter.dev);
-       wait_for_completion(&isa_adapter.dev_released);
 exit:
        return err;
 }
@@ -201,15 +172,11 @@ static void __exit i2c_isa_exit(void)
        /* Clean up the sysfs representation */
        dev_dbg(&isa_adapter.dev, "Unregistering from sysfs\n");
        init_completion(&isa_adapter.dev_released);
-       init_completion(&isa_adapter.class_dev_released);
-       class_device_unregister(&isa_adapter.class_dev);
-       device_remove_file(&isa_adapter.dev, &dev_attr_name);
        device_unregister(&isa_adapter.dev);
 
        /* Wait for sysfs to drop all references */
        dev_dbg(&isa_adapter.dev, "Waiting for sysfs completion\n");
        wait_for_completion(&isa_adapter.dev_released);
-       wait_for_completion(&isa_adapter.class_dev_released);
 
        dev_dbg(&isa_adapter.dev, "%s unregistered\n", isa_adapter.name);
 }
index efa3ecc..6352121 100644 (file)
@@ -118,7 +118,7 @@ static int ixp2000_i2c_probe(struct platform_device *plat_dev)
 
        drv_data->adapter.id = I2C_HW_B_IXP2000,
        strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
-               I2C_NAME_SIZE);
+               sizeof(drv_data->adapter.name));
        drv_data->adapter.algo_data = &drv_data->algo_data,
 
        drv_data->adapter.dev.parent = &plat_dev->dev;
index 08e89b8..069ed7f 100644 (file)
@@ -127,7 +127,7 @@ static int ixp4xx_i2c_probe(struct platform_device *plat_dev)
        drv_data->adapter.id = I2C_HW_B_IXP4XX;
        drv_data->adapter.class = I2C_CLASS_HWMON;
        strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
-               I2C_NAME_SIZE);
+               sizeof(drv_data->adapter.name));
        drv_data->adapter.algo_data = &drv_data->algo_data;
 
        drv_data->adapter.dev.parent = &plat_dev->dev;
index ee65aa1..c6b6898 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <linux/platform_device.h>
 
 #include <asm/io.h>
index a3283b9..a55b333 100644 (file)
@@ -508,7 +508,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
        }
 
        strlcpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter",
-               I2C_NAME_SIZE);
+               sizeof(drv_data->adapter.name));
 
        init_waitqueue_head(&drv_data->waitq);
        spin_lock_init(&drv_data->lock);
index 1514ec5..3cd0d63 100644 (file)
@@ -33,6 +33,8 @@
     nForce4 MCP-04             0034
     nForce4 MCP51              0264
     nForce4 MCP55              0368
+    nForce MCP61               03EB
+    nForce MCP65               0446
 
     This driver supports the 2 SMBuses that are included in the MCP of the
     nForce2/3/4/5xx chipsets.
@@ -200,6 +202,8 @@ static struct pci_device_id nforce2_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS) },
        { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS) },
        { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS) },
+       { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS) },
+       { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS) },
        { 0 }
 };
 
@@ -240,7 +244,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
        smbus->adapter.algo = &smbus_algorithm;
        smbus->adapter.algo_data = smbus;
        smbus->adapter.dev.parent = &dev->dev;
-       snprintf(smbus->adapter.name, I2C_NAME_SIZE,
+       snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
                "SMBus nForce2 adapter at %04x", smbus->base);
 
        error = i2c_add_adapter(&smbus->adapter);
index bcd8367..e471e3b 100644 (file)
@@ -605,7 +605,8 @@ omap_i2c_probe(struct platform_device *pdev)
        adap->dev.parent = &pdev->dev;
 
        /* i2c device drivers may be active on return from add_adapter() */
-       r = i2c_add_adapter(adap);
+       adap->nr = pdev->id;
+       r = i2c_add_numbered_adapter(adap);
        if (r) {
                dev_err(dev->dev, "failure adding adapter\n");
                goto err_free_irq;
index 4bc4281..49a95e2 100644 (file)
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------ *
- * i2c-parport.c I2C bus over parallel port                                 *
+ * i2c-parport-light.c I2C bus over parallel port                           *
  * ------------------------------------------------------------------------ *
-   Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org>
+   Copyright (C) 2003-2007 Jean Delvare <khali@linux-fr.org>
    
    Based on older i2c-velleman.c driver
    Copyright (C) 1995-2000 Simon G. Vogl
@@ -27,6 +27,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <linux/ioport.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
@@ -34,6 +35,9 @@
 #include "i2c-parport.h"
 
 #define DEFAULT_BASE 0x378
+#define DRVNAME "i2c-parport-light"
+
+static struct platform_device *pdev;
 
 static u16 base;
 module_param(base, ushort, 0);
@@ -106,7 +110,7 @@ static struct i2c_algo_bit_data parport_algo_data = {
        .timeout        = HZ,
 }; 
 
-/* ----- I2c structure ---------------------------------------------------- */
+/* ----- Driver registration ---------------------------------------------- */
 
 static struct i2c_adapter parport_adapter = {
        .owner          = THIS_MODULE,
@@ -116,55 +120,141 @@ static struct i2c_adapter parport_adapter = {
        .name           = "Parallel port adapter (light)",
 };
 
-/* ----- Module loading, unloading and information ------------------------ */
+static int __devinit i2c_parport_probe(struct platform_device *pdev)
+{
+       int err;
+       struct resource *res;
+
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (!request_region(res->start, res->end - res->start + 1, DRVNAME))
+               return -EBUSY;
+
+       /* Reset hardware to a sane state (SCL and SDA high) */
+       parport_setsda(NULL, 1);
+       parport_setscl(NULL, 1);
+       /* Other init if needed (power on...) */
+       if (adapter_parm[type].init.val)
+               line_set(1, &adapter_parm[type].init);
+
+       parport_adapter.dev.parent = &pdev->dev;
+       err = i2c_bit_add_bus(&parport_adapter);
+       if (err) {
+               dev_err(&pdev->dev, "Unable to register with I2C\n");
+               goto exit_region;
+       }
+       return 0;
+
+exit_region:
+       release_region(res->start, res->end - res->start + 1);
+       return err;
+}
+
+static int __devexit i2c_parport_remove(struct platform_device *pdev)
+{
+       struct resource *res;
+
+       i2c_del_adapter(&parport_adapter);
+
+       /* Un-init if needed (power off...) */
+       if (adapter_parm[type].init.val)
+               line_set(0, &adapter_parm[type].init);
+
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       release_region(res->start, res->end - res->start + 1);
+       return 0;
+}
+
+static struct platform_driver i2c_parport_driver = {
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = DRVNAME,
+       },
+       .probe          = i2c_parport_probe,
+       .remove         = __devexit_p(i2c_parport_remove),
+};
+
+static int __init i2c_parport_device_add(u16 address)
+{
+       struct resource res = {
+               .start  = address,
+               .end    = address + 2,
+               .name   = DRVNAME,
+               .flags  = IORESOURCE_IO,
+       };
+       int err;
+
+       pdev = platform_device_alloc(DRVNAME, -1);
+       if (!pdev) {
+               err = -ENOMEM;
+               printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+               goto exit;
+       }
+
+       err = platform_device_add_resources(pdev, &res, 1);
+       if (err) {
+               printk(KERN_ERR DRVNAME ": Device resource addition failed "
+                      "(%d)\n", err);
+               goto exit_device_put;
+       }
+
+       err = platform_device_add(pdev);
+       if (err) {
+               printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
+                      err);
+               goto exit_device_put;
+       }
+
+       return 0;
+
+exit_device_put:
+       platform_device_put(pdev);
+exit:
+       return err;
+}
 
 static int __init i2c_parport_init(void)
 {
+       int err;
+
        if (type < 0) {
-               printk(KERN_WARNING "i2c-parport: adapter type unspecified\n");
+               printk(KERN_ERR DRVNAME ": adapter type unspecified\n");
                return -ENODEV;
        }
 
        if (type >= ARRAY_SIZE(adapter_parm)) {
-               printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
+               printk(KERN_ERR DRVNAME ": invalid type (%d)\n", type);
                return -ENODEV;
        }
 
        if (base == 0) {
-               printk(KERN_INFO "i2c-parport: using default base 0x%x\n", DEFAULT_BASE);
+               pr_info(DRVNAME ": using default base 0x%x\n", DEFAULT_BASE);
                base = DEFAULT_BASE;
        }
 
-       if (!request_region(base, 3, "i2c-parport"))
-               return -ENODEV;
-
         if (!adapter_parm[type].getscl.val)
                parport_algo_data.getscl = NULL;
 
-       /* Reset hardware to a sane state (SCL and SDA high) */
-       parport_setsda(NULL, 1);
-       parport_setscl(NULL, 1);
-       /* Other init if needed (power on...) */
-       if (adapter_parm[type].init.val)
-               line_set(1, &adapter_parm[type].init);
+       /* Sets global pdev as a side effect */
+       err = i2c_parport_device_add(base);
+       if (err)
+               goto exit;
 
-       if (i2c_bit_add_bus(&parport_adapter) < 0) {
-               printk(KERN_ERR "i2c-parport: Unable to register with I2C\n");
-               release_region(base, 3);
-               return -ENODEV;
-       }
+       err = platform_driver_register(&i2c_parport_driver);
+       if (err)
+               goto exit_device;
 
        return 0;
+
+exit_device:
+       platform_device_unregister(pdev);
+exit:
+       return err;
 }
 
 static void __exit i2c_parport_exit(void)
 {
-       /* Un-init if needed (power off...) */
-       if (adapter_parm[type].init.val)
-               line_set(0, &adapter_parm[type].init);
-
-       i2c_del_adapter(&parport_adapter);
-       release_region(base, 3);
+       platform_driver_unregister(&i2c_parport_driver);
+       platform_device_unregister(pdev);
 }
 
 MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
index 66696a4..8c95370 100644 (file)
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------ *
  * i2c-parport.c I2C bus over parallel port                                 *
  * ------------------------------------------------------------------------ *
-   Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org>
+   Copyright (C) 2003-2007 Jean Delvare <khali@linux-fr.org>
    
    Based on older i2c-philips-par.c driver
    Copyright (C) 1995-2000 Simon G. Vogl
@@ -137,19 +137,12 @@ static struct i2c_algo_bit_data parport_algo_data = {
        .setscl         = parport_setscl,
        .getsda         = parport_getsda,
        .getscl         = parport_getscl,
-       .udelay         = 60,
+       .udelay         = 10, /* ~50 kbps */
        .timeout        = HZ,
 }; 
 
 /* ----- I2c and parallel port call-back functions and structures --------- */
 
-static struct i2c_adapter parport_adapter = {
-       .owner          = THIS_MODULE,
-       .class          = I2C_CLASS_HWMON,
-       .id             = I2C_HW_B_LP,
-       .name           = "Parallel port adapter",
-};
-
 static void i2c_parport_attach (struct parport *port)
 {
        struct i2c_par *adapter;
@@ -169,10 +162,17 @@ static void i2c_parport_attach (struct parport *port)
        }
 
        /* Fill the rest of the structure */
-       adapter->adapter = parport_adapter;
+       adapter->adapter.owner = THIS_MODULE;
+       adapter->adapter.class = I2C_CLASS_HWMON;
+       adapter->adapter.id = I2C_HW_B_LP;
+       strlcpy(adapter->adapter.name, "Parallel port adapter",
+               sizeof(adapter->adapter.name));
        adapter->algo_data = parport_algo_data;
-       if (!adapter_parm[type].getscl.val)
+       /* Slow down if we can't sense SCL */
+       if (!adapter_parm[type].getscl.val) {
                adapter->algo_data.getscl = NULL;
+               adapter->algo_data.udelay = 50; /* ~10 kbps */
+       }
        adapter->algo_data.data = port;
        adapter->adapter.algo_data = &adapter->algo_data;
 
@@ -214,11 +214,12 @@ static void i2c_parport_detach (struct parport *port)
        for (prev = NULL, adapter = adapter_list; adapter;
             prev = adapter, adapter = adapter->next) {
                if (adapter->pdev->port == port) {
+                       i2c_del_adapter(&adapter->adapter);
+
                        /* Un-init if needed (power off...) */
                        if (adapter_parm[type].init.val)
                                line_set(port, 0, &adapter_parm[type].init);
                                
-                       i2c_del_adapter(&adapter->adapter);
                        parport_unregister_device(adapter->pdev);
                        if (prev)
                                prev->next = adapter->next;
index bf89eee..58e3271 100644 (file)
@@ -358,7 +358,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev,
        }
 
        smbus->adapter.owner = THIS_MODULE;
-       snprintf(smbus->adapter.name, I2C_NAME_SIZE,
+       snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
                 "PA Semi SMBus adapter at 0x%lx", smbus->base);
        smbus->adapter.class = I2C_CLASS_HWMON;
        smbus->adapter.algo = &smbus_algorithm;
index cc6536a..5161aaf 100644 (file)
@@ -25,9 +25,9 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/wait.h>
 
+#include <linux/isa.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-pca.h>
 
@@ -119,27 +119,26 @@ static struct i2c_adapter pca_isa_ops = {
        .name           = "PCA9564 ISA Adapter",
 };
 
-static int __init pca_isa_init(void)
+static int __devinit pca_isa_probe(struct device *dev, unsigned int id)
 {
-
        init_waitqueue_head(&pca_wait);
 
-       printk(KERN_INFO "i2c-pca-isa: i/o base %#08lx. irq %d\n", base, irq);
+       dev_info(dev, "i/o base %#08lx. irq %d\n", base, irq);
 
        if (!request_region(base, IO_SIZE, "i2c-pca-isa")) {
-               printk(KERN_ERR "i2c-pca-isa: I/O address %#08lx is in use.\n", base);
+               dev_err(dev, "I/O address %#08lx is in use\n", base);
                goto out;
        }
 
        if (irq > -1) {
                if (request_irq(irq, pca_handler, 0, "i2c-pca-isa", &pca_isa_ops) < 0) {
-                       printk(KERN_ERR "i2c-pca-isa: Request irq%d failed\n", irq);
+                       dev_err(dev, "Request irq%d failed\n", irq);
                        goto out_region;
                }
        }
 
        if (i2c_pca_add_bus(&pca_isa_ops) < 0) {
-               printk(KERN_ERR "i2c-pca-isa: Failed to add i2c bus\n");
+               dev_err(dev, "Failed to add i2c bus\n");
                goto out_irq;
        }
 
@@ -154,7 +153,7 @@ static int __init pca_isa_init(void)
        return -ENODEV;
 }
 
-static void pca_isa_exit(void)
+static int __devexit pca_isa_remove(struct device *dev, unsigned int id)
 {
        i2c_del_adapter(&pca_isa_ops);
 
@@ -163,6 +162,27 @@ static void pca_isa_exit(void)
                free_irq(irq, &pca_isa_ops);
        }
        release_region(base, IO_SIZE);
+
+       return 0;
+}
+
+static struct isa_driver pca_isa_driver = {
+       .probe          = pca_isa_probe,
+       .remove         = __devexit_p(pca_isa_remove),
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = "i2c-pca-isa",
+       }
+};
+
+static int __init pca_isa_init(void)
+{
+       return isa_register_driver(&pca_isa_driver, 1);
+}
+
+static void __exit pca_isa_exit(void)
+{
+       isa_unregister_driver(&pca_isa_driver);
 }
 
 MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>");
index 21b1809..5a52bf5 100644 (file)
@@ -428,7 +428,7 @@ static int __devinit piix4_probe(struct pci_dev *dev,
        /* set up the sysfs linkage to our parent device */
        piix4_adapter.dev.parent = &dev->dev;
 
-       snprintf(piix4_adapter.name, I2C_NAME_SIZE,
+       snprintf(piix4_adapter.name, sizeof(piix4_adapter.name),
                "SMBus PIIX4 adapter at %04x", piix4_smba);
 
        if ((retval = i2c_add_adapter(&piix4_adapter))) {
index 14e83d0..c059b27 100644 (file)
@@ -539,6 +539,18 @@ static inline void i2c_pxa_start_message(struct pxa_i2c *i2c)
        writel(icr | ICR_START | ICR_TB, _ICR(i2c));
 }
 
+static inline void i2c_pxa_stop_message(struct pxa_i2c *i2c)
+{
+       u32 icr;
+
+       /*
+        * Clear the STOP and ACK flags
+        */
+       icr = readl(_ICR(i2c));
+       icr &= ~(ICR_STOP | ICR_ACKNAK);
+       writel(icr, _IRC(i2c));
+}
+
 /*
  * We are protected by the adapter bus mutex.
  */
@@ -581,6 +593,7 @@ static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num)
         * The rest of the processing occurs in the interrupt handler.
         */
        timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
+       i2c_pxa_stop_message(i2c);
 
        /*
         * We place the return code in i2c->msg_idx.
@@ -825,7 +838,7 @@ static const struct i2c_algorithm i2c_pxa_algorithm = {
 };
 
 static struct pxa_i2c i2c_pxa = {
-       .lock   = SPIN_LOCK_UNLOCKED,
+       .lock   = __SPIN_LOCK_UNLOCKED(i2c_pxa.lock),
        .adap   = {
                .owner          = THIS_MODULE,
                .algo           = &i2c_pxa_algorithm,
index 556f244..e68a96f 100644 (file)
@@ -61,6 +61,8 @@ struct s3c24xx_i2c {
        unsigned int            msg_idx;
        unsigned int            msg_ptr;
 
+       unsigned int            tx_setup;
+
        enum s3c24xx_i2c_state  state;
 
        void __iomem            *regs;
@@ -199,8 +201,11 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
        dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr);
        writeb(addr, i2c->regs + S3C2410_IICDS);
        
-       // delay a bit and reset iiccon before setting start (per samsung)
-       udelay(1);
+       /* delay here to ensure the data byte has gotten onto the bus
+        * before the transaction is started */
+
+       ndelay(i2c->tx_setup);
+
        dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon);
        writel(iiccon, i2c->regs + S3C2410_IICCON);
        
@@ -322,7 +327,15 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
                if (!is_msgend(i2c)) {
                        byte = i2c->msg->buf[i2c->msg_ptr++];
                        writeb(byte, i2c->regs + S3C2410_IICDS);
-                       
+
+                       /* delay after writing the byte to allow the
+                        * data setup time on the bus, as writing the
+                        * data to the register causes the first bit
+                        * to appear on SDA, and SCL will change as
+                        * soon as the interrupt is acknowledged */
+
+                       ndelay(i2c->tx_setup);
+
                } else if (!is_lastmsg(i2c)) {
                        /* we need to go to the next i2c message */
 
@@ -570,9 +583,10 @@ static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
 };
 
 static struct s3c24xx_i2c s3c24xx_i2c = {
-       .lock   = SPIN_LOCK_UNLOCKED,
-       .wait   = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait),
-       .adap   = {
+       .lock           = __SPIN_LOCK_UNLOCKED(s3c24xx_i2c.lock),
+       .wait           = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait),
+       .tx_setup       = 50,
+       .adap           = {
                .name                   = "s3c2410-i2c",
                .owner                  = THIS_MODULE,
                .algo                   = &s3c24xx_i2c_algorithm,
@@ -731,26 +745,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
        return 0;
 }
 
-static void s3c24xx_i2c_free(struct s3c24xx_i2c *i2c)
-{
-       if (i2c->clk != NULL && !IS_ERR(i2c->clk)) {
-               clk_disable(i2c->clk);
-               clk_put(i2c->clk);
-               i2c->clk = NULL;
-       }
-
-       if (i2c->regs != NULL) {
-               iounmap(i2c->regs);
-               i2c->regs = NULL;
-       }
-
-       if (i2c->ioarea != NULL) {
-               release_resource(i2c->ioarea);
-               kfree(i2c->ioarea);
-               i2c->ioarea = NULL;
-       }
-}
-
 /* s3c24xx_i2c_probe
  *
  * called by the bus driver when a suitable device is found
@@ -769,7 +763,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
        if (IS_ERR(i2c->clk)) {
                dev_err(&pdev->dev, "cannot get clock\n");
                ret = -ENOENT;
-               goto out;
+               goto err_noclk;
        }
 
        dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk);
@@ -782,7 +776,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
        if (res == NULL) {
                dev_err(&pdev->dev, "cannot find IO resource\n");
                ret = -ENOENT;
-               goto out;
+               goto err_clk;
        }
 
        i2c->ioarea = request_mem_region(res->start, (res->end-res->start)+1,
@@ -791,7 +785,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
        if (i2c->ioarea == NULL) {
                dev_err(&pdev->dev, "cannot request IO\n");
                ret = -ENXIO;
-               goto out;
+               goto err_clk;
        }
 
        i2c->regs = ioremap(res->start, (res->end-res->start)+1);
@@ -799,7 +793,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
        if (i2c->regs == NULL) {
                dev_err(&pdev->dev, "cannot map IO\n");
                ret = -ENXIO;
-               goto out;
+               goto err_ioarea;
        }
 
        dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", i2c->regs, i2c->ioarea, res);
@@ -813,7 +807,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
 
        ret = s3c24xx_i2c_init(i2c);
        if (ret != 0)
-               goto out;
+               goto err_iomap;
 
        /* find the IRQ for this unit (note, this relies on the init call to
         * ensure no current IRQs pending 
@@ -823,7 +817,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
        if (res == NULL) {
                dev_err(&pdev->dev, "cannot find IRQ\n");
                ret = -ENOENT;
-               goto out;
+               goto err_iomap;
        }
 
        ret = request_irq(res->start, s3c24xx_i2c_irq, IRQF_DISABLED,
@@ -831,7 +825,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
 
        if (ret != 0) {
                dev_err(&pdev->dev, "cannot claim IRQ\n");
-               goto out;
+               goto err_iomap;
        }
 
        i2c->irq = res;
@@ -841,17 +835,29 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
        ret = i2c_add_adapter(&i2c->adap);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to add bus to i2c core\n");
-               goto out;
+               goto err_irq;
        }
 
        platform_set_drvdata(pdev, i2c);
 
        dev_info(&pdev->dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id);
+       return 0;
 
- out:
-       if (ret < 0)
-               s3c24xx_i2c_free(i2c);
+ err_irq:
+       free_irq(i2c->irq->start, i2c);
+
+ err_iomap:
+       iounmap(i2c->regs);
 
+ err_ioarea:
+       release_resource(i2c->ioarea);
+       kfree(i2c->ioarea);
+
+ err_clk:
+       clk_disable(i2c->clk);
+       clk_put(i2c->clk);
+
+ err_noclk:
        return ret;
 }
 
@@ -863,11 +869,17 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
 static int s3c24xx_i2c_remove(struct platform_device *pdev)
 {
        struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
-       
-       if (i2c != NULL) {
-               s3c24xx_i2c_free(i2c);
-               platform_set_drvdata(pdev, NULL);
-       }
+
+       i2c_del_adapter(&i2c->adap);
+       free_irq(i2c->irq->start, i2c);
+
+       clk_disable(i2c->clk);
+       clk_put(i2c->clk);
+
+       iounmap(i2c->regs);
+
+       release_resource(i2c->ioarea);
+       kfree(i2c->ioarea);
 
        return 0;
 }
diff --git a/drivers/i2c/busses/i2c-simtec.c b/drivers/i2c/busses/i2c-simtec.c
new file mode 100644 (file)
index 0000000..10af8d3
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2005 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * Simtec Generic I2C Controller
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include <asm/io.h>
+
+struct simtec_i2c_data {
+       struct resource         *ioarea;
+       void __iomem            *reg;
+       struct i2c_adapter       adap;
+       struct i2c_algo_bit_data bit;
+};
+
+#define CMD_SET_SDA    (1<<2)
+#define CMD_SET_SCL    (1<<3)
+
+#define STATE_SDA      (1<<0)
+#define STATE_SCL      (1<<1)
+
+/* i2c bit-bus functions */
+
+static void simtec_i2c_setsda(void *pw, int state)
+{
+       struct simtec_i2c_data *pd = pw;
+       writeb(CMD_SET_SDA | (state ? STATE_SDA : 0), pd->reg);
+}
+
+static void simtec_i2c_setscl(void *pw, int state)
+{
+       struct simtec_i2c_data *pd = pw;
+       writeb(CMD_SET_SCL | (state ? STATE_SCL : 0), pd->reg);
+}
+
+static int simtec_i2c_getsda(void *pw)
+{
+       struct simtec_i2c_data *pd = pw;
+       return readb(pd->reg) & STATE_SDA ? 1 : 0;
+}
+
+static int simtec_i2c_getscl(void *pw)
+{
+       struct simtec_i2c_data *pd = pw;
+       return readb(pd->reg) & STATE_SCL ? 1 : 0;
+}
+
+/* device registration */
+
+static int simtec_i2c_probe(struct platform_device *dev)
+{
+       struct simtec_i2c_data *pd;
+       struct resource *res;
+       int size;
+       int ret;
+
+       pd = kzalloc(sizeof(struct simtec_i2c_data), GFP_KERNEL);
+       if (pd == NULL) {
+               dev_err(&dev->dev, "cannot allocate private data\n");
+               return -ENOMEM;
+       }
+
+       platform_set_drvdata(dev, pd);
+
+       res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&dev->dev, "cannot find IO resource\n");
+               ret = -ENOENT;
+               goto err;
+       }
+
+       size = (res->end-res->start)+1;
+
+       pd->ioarea = request_mem_region(res->start, size, dev->name);
+       if (pd->ioarea == NULL) {
+               dev_err(&dev->dev, "cannot request IO\n");
+               ret = -ENXIO;
+               goto err;
+       }
+
+       pd->reg = ioremap(res->start, size);
+       if (pd->reg == NULL) {
+               dev_err(&dev->dev, "cannot map IO\n");
+               ret = -ENXIO;
+               goto err_res;
+       }
+
+       /* setup the private data */
+
+       pd->adap.owner = THIS_MODULE;
+       pd->adap.algo_data = &pd->bit;
+       pd->adap.dev.parent = &dev->dev;
+
+       strlcpy(pd->adap.name, "Simtec I2C", sizeof(pd->adap.name));
+
+       pd->bit.data = pd;
+       pd->bit.setsda = simtec_i2c_setsda;
+       pd->bit.setscl = simtec_i2c_setscl;
+       pd->bit.getsda = simtec_i2c_getsda;
+       pd->bit.getscl = simtec_i2c_getscl;
+       pd->bit.timeout = HZ;
+       pd->bit.udelay = 20;
+
+       ret = i2c_bit_add_bus(&pd->adap);
+       if (ret)
+               goto err_all;
+
+       return 0;
+
+ err_all:
+       iounmap(pd->reg);
+
+ err_res:
+       release_resource(pd->ioarea);
+       kfree(pd->ioarea);
+
+ err:
+       kfree(pd);
+       return ret;
+}
+
+static int simtec_i2c_remove(struct platform_device *dev)
+{
+       struct simtec_i2c_data *pd = platform_get_drvdata(dev);
+
+       i2c_del_adapter(&pd->adap);
+
+       iounmap(pd->reg);
+       release_resource(pd->ioarea);
+       kfree(pd->ioarea);
+       kfree(pd);
+
+       return 0;
+}
+
+
+/* device driver */
+
+static struct platform_driver simtec_i2c_driver = {
+       .driver         = {
+               .name           = "simtec-i2c",
+               .owner          = THIS_MODULE,
+       },
+       .probe          = simtec_i2c_probe,
+       .remove         = simtec_i2c_remove,
+};
+
+static int __init i2c_adap_simtec_init(void)
+{
+       return platform_driver_register(&simtec_i2c_driver);
+}
+
+static void __exit i2c_adap_simtec_exit(void)
+{
+       platform_driver_unregister(&simtec_i2c_driver);
+}
+
+module_init(i2c_adap_simtec_init);
+module_exit(i2c_adap_simtec_exit);
+
+MODULE_DESCRIPTION("Simtec Generic I2C Bus driver");
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_LICENSE("GPL");
index 4157b0c..dc235bb 100644 (file)
@@ -300,7 +300,7 @@ static int __devinit sis96x_probe(struct pci_dev *dev,
        /* set up the sysfs linkage to our parent device */
        sis96x_adapter.dev.parent = &dev->dev;
 
-       snprintf(sis96x_adapter.name, I2C_NAME_SIZE,
+       snprintf(sis96x_adapter.name, sizeof(sis96x_adapter.name),
                "SiS96x SMBus adapter at 0x%04x", sis96x_smbus_base);
 
        if ((retval = i2c_add_adapter(&sis96x_adapter))) {
diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c
new file mode 100644 (file)
index 0000000..9079990
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * driver for the i2c-tiny-usb adapter - 1.0
+ * http://www.harbaum.org/till/i2c_tiny_usb
+ *
+ * Copyright (C) 2006-2007 Till Harbaum (Till@Harbaum.org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+
+/* include interfaces to usb layer */
+#include <linux/usb.h>
+
+/* include interface to i2c layer */
+#include <linux/i2c.h>
+
+/* commands via USB, must match command ids in the firmware */
+#define CMD_ECHO               0
+#define CMD_GET_FUNC           1
+#define CMD_SET_DELAY          2
+#define CMD_GET_STATUS         3
+
+#define CMD_I2C_IO             4
+#define CMD_I2C_IO_BEGIN       (1<<0)
+#define CMD_I2C_IO_END         (1<<1)
+
+/* i2c bit delay, default is 10us -> 100kHz */
+static int delay = 10;
+module_param(delay, int, 0);
+MODULE_PARM_DESC(delay, "bit delay in microseconds, "
+                "e.g. 10 for 100kHz (default is 100kHz)");
+
+static int usb_read(struct i2c_adapter *adapter, int cmd,
+                   int value, int index, void *data, int len);
+
+static int usb_write(struct i2c_adapter *adapter, int cmd,
+                    int value, int index, void *data, int len);
+
+/* ----- begin of i2c layer ---------------------------------------------- */
+
+#define STATUS_IDLE            0
+#define STATUS_ADDRESS_ACK     1
+#define STATUS_ADDRESS_NAK     2
+
+static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
+{
+       unsigned char status;
+       struct i2c_msg *pmsg;
+       int i;
+
+       dev_dbg(&adapter->dev, "master xfer %d messages:\n", num);
+
+       for (i = 0 ; i < num ; i++) {
+               int cmd = CMD_I2C_IO;
+
+               if (i == 0)
+                       cmd |= CMD_I2C_IO_BEGIN;
+
+               if (i == num-1)
+                       cmd |= CMD_I2C_IO_END;
+
+               pmsg = &msgs[i];
+
+               dev_dbg(&adapter->dev,
+                       "  %d: %s (flags %d) %d bytes to 0x%02x\n",
+                       i, pmsg->flags & I2C_M_RD ? "read" : "write",
+                       pmsg->flags, pmsg->len, pmsg->addr);
+
+               /* and directly send the message */
+               if (pmsg->flags & I2C_M_RD) {
+                       /* read data */
+                       if (usb_read(adapter, cmd,
+                                    pmsg->flags, pmsg->addr,
+                                    pmsg->buf, pmsg->len) != pmsg->len) {
+                               dev_err(&adapter->dev,
+                                       "failure reading data\n");
+                               return -EREMOTEIO;
+                       }
+               } else {
+                       /* write data */
+                       if (usb_write(adapter, cmd,
+                                     pmsg->flags, pmsg->addr,
+                                     pmsg->buf, pmsg->len) != pmsg->len) {
+                               dev_err(&adapter->dev,
+                                       "failure writing data\n");
+                               return -EREMOTEIO;
+                       }
+               }
+
+               /* read status */
+               if (usb_read(adapter, CMD_GET_STATUS, 0, 0, &status, 1) != 1) {
+                       dev_err(&adapter->dev, "failure reading status\n");
+                       return -EREMOTEIO;
+               }
+
+               dev_dbg(&adapter->dev, "  status = %d\n", status);
+               if (status == STATUS_ADDRESS_NAK)
+                       return -EREMOTEIO;
+       }
+
+       return i;
+}
+
+static u32 usb_func(struct i2c_adapter *adapter)
+{
+       u32 func;
+
+       /* get functionality from adapter */
+       if (usb_read(adapter, CMD_GET_FUNC, 0, 0, &func, sizeof(func)) !=
+           sizeof(func)) {
+               dev_err(&adapter->dev, "failure reading functionality\n");
+               return 0;
+       }
+
+       return func;
+}
+
+/* This is the actual algorithm we define */
+static const struct i2c_algorithm usb_algorithm = {
+       .master_xfer    = usb_xfer,
+       .functionality  = usb_func,
+};
+
+/* ----- end of i2c layer ------------------------------------------------ */
+
+/* ----- begin of usb layer ---------------------------------------------- */
+
+/* The usb i2c interface uses a vid/pid pair donated by */
+/* Future Technology Devices International Ltd. */
+static struct usb_device_id i2c_tiny_usb_table [] = {
+       { USB_DEVICE(0x0403, 0xc631) },
+       { }                     /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, i2c_tiny_usb_table);
+
+/* Structure to hold all of our device specific stuff */
+struct i2c_tiny_usb {
+       struct usb_device *usb_dev; /* the usb device for this device */
+       struct usb_interface *interface; /* the interface for this device */
+       struct i2c_adapter adapter; /* i2c related things */
+};
+
+static int usb_read(struct i2c_adapter *adapter, int cmd,
+                   int value, int index, void *data, int len)
+{
+       struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
+
+       /* do control transfer */
+       return usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0),
+                              cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE |
+                              USB_DIR_IN, value, index, data, len, 2000);
+}
+
+static int usb_write(struct i2c_adapter *adapter, int cmd,
+                    int value, int index, void *data, int len)
+{
+       struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
+
+       /* do control transfer */
+       return usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0),
+                              cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                              value, index, data, len, 2000);
+}
+
+static void i2c_tiny_usb_free(struct i2c_tiny_usb *dev)
+{
+       usb_put_dev(dev->usb_dev);
+       kfree(dev);
+}
+
+static int i2c_tiny_usb_probe(struct usb_interface *interface,
+                             const struct usb_device_id *id)
+{
+       struct i2c_tiny_usb *dev;
+       int retval = -ENOMEM;
+       u16 version;
+
+       dev_dbg(&interface->dev, "probing usb device\n");
+
+       /* allocate memory for our device state and initialize it */
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (dev == NULL) {
+               dev_err(&interface->dev, "Out of memory\n");
+               goto error;
+       }
+
+       dev->usb_dev = usb_get_dev(interface_to_usbdev(interface));
+       dev->interface = interface;
+
+       /* save our data pointer in this interface device */
+       usb_set_intfdata(interface, dev);
+
+       version = le16_to_cpu(dev->usb_dev->descriptor.bcdDevice);
+       dev_info(&interface->dev,
+                "version %x.%02x found at bus %03d address %03d\n",
+                version >> 8, version & 0xff,
+                dev->usb_dev->bus->busnum, dev->usb_dev->devnum);
+
+       /* setup i2c adapter description */
+       dev->adapter.owner = THIS_MODULE;
+       dev->adapter.class = I2C_CLASS_HWMON;
+       dev->adapter.algo = &usb_algorithm;
+       dev->adapter.algo_data = dev;
+       snprintf(dev->adapter.name, I2C_NAME_SIZE,
+                "i2c-tiny-usb at bus %03d device %03d",
+                dev->usb_dev->bus->busnum, dev->usb_dev->devnum);
+
+       if (usb_write(&dev->adapter, CMD_SET_DELAY,
+                     cpu_to_le16(delay), 0, NULL, 0) != 0) {
+               dev_err(&dev->adapter.dev,
+                       "failure setting delay to %dus\n", delay);
+               retval = -EIO;
+               goto error;
+       }
+
+       dev->adapter.dev.parent = &dev->interface->dev;
+
+       /* and finally attach to i2c layer */
+       i2c_add_adapter(&dev->adapter);
+
+       /* inform user about successful attachment to i2c layer */
+       dev_info(&dev->adapter.dev, "connected i2c-tiny-usb device\n");
+
+       return 0;
+
+ error:
+       if (dev)
+               i2c_tiny_usb_free(dev);
+
+       return retval;
+}
+
+static void i2c_tiny_usb_disconnect(struct usb_interface *interface)
+{
+       struct i2c_tiny_usb *dev = usb_get_intfdata(interface);
+
+       i2c_del_adapter(&dev->adapter);
+       usb_set_intfdata(interface, NULL);
+       i2c_tiny_usb_free(dev);
+
+       dev_dbg(&interface->dev, "disconnected\n");
+}
+
+static struct usb_driver i2c_tiny_usb_driver = {
+       .name           = "i2c-tiny-usb",
+       .probe          = i2c_tiny_usb_probe,
+       .disconnect     = i2c_tiny_usb_disconnect,
+       .id_table       = i2c_tiny_usb_table,
+};
+
+static int __init usb_i2c_tiny_usb_init(void)
+{
+       /* register this driver with the USB subsystem */
+       return usb_register(&i2c_tiny_usb_driver);
+}
+
+static void __exit usb_i2c_tiny_usb_exit(void)
+{
+       /* deregister this driver with the USB subsystem */
+       usb_deregister(&i2c_tiny_usb_driver);
+}
+
+module_init(usb_i2c_tiny_usb_init);
+module_exit(usb_i2c_tiny_usb_exit);
+
+/* ----- end of usb layer ------------------------------------------------ */
+
+MODULE_AUTHOR("Till Harbaum <Till@Harbaum.org>");
+MODULE_DESCRIPTION("i2c-tiny-usb driver v1.0");
+MODULE_LICENSE("GPL");
index 03c5fc8..7a2bc06 100644 (file)
@@ -404,7 +404,7 @@ found:
        }
 
        vt596_adapter.dev.parent = &pdev->dev;
-       snprintf(vt596_adapter.name, I2C_NAME_SIZE,
+       snprintf(vt596_adapter.name, sizeof(vt596_adapter.name),
                 "SMBus Via Pro adapter at %04x", vt596_smba);
 
        vt596_pdev = pci_dev_get(pdev);
index 0b082c5..0db56e7 100644 (file)
@@ -441,7 +441,7 @@ static __init struct scx200_acb_iface *scx200_create_iface(const char *text,
 
        adapter = &iface->adapter;
        i2c_set_adapdata(adapter, iface);
-       snprintf(adapter->name, I2C_NAME_SIZE, "%s ACB%d", text, index);
+       snprintf(adapter->name, sizeof(adapter->name), "%s ACB%d", text, index);
        adapter->owner = THIS_MODULE;
        adapter->id = I2C_HW_SMBUS_SCX200;
        adapter->algo = &scx200_acb_algorithm;
@@ -599,6 +599,7 @@ static __init int scx200_scan_pci(void)
                else {
                        int i;
 
+                       pci_dev_put(pdev);
                        for (i = 0; i < MAX_DEVICES; ++i) {
                                if (base[i] == 0)
                                        continue;
index 87ee3ce..ea085a0 100644 (file)
@@ -3,11 +3,10 @@
 #
 
 menu "Miscellaneous I2C Chip support"
-       depends on I2C
 
 config SENSORS_DS1337
        tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock"
-       depends on I2C && EXPERIMENTAL
+       depends on EXPERIMENTAL
        help
          If you say yes here you get support for Dallas Semiconductor
          DS1337 and DS1339 real-time clock chips.
@@ -17,7 +16,7 @@ config SENSORS_DS1337
 
 config SENSORS_DS1374
        tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock"
-       depends on I2C && EXPERIMENTAL
+       depends on EXPERIMENTAL
        help
          If you say yes here you get support for Dallas Semiconductor
          DS1374 real-time clock chips.
@@ -27,7 +26,7 @@ config SENSORS_DS1374
 
 config SENSORS_EEPROM
        tristate "EEPROM reader"
-       depends on I2C && EXPERIMENTAL
+       depends on EXPERIMENTAL
        help
          If you say yes here you get read-only access to the EEPROM data
          available on modern memory DIMMs and Sony Vaio laptops.  Such
@@ -38,7 +37,7 @@ config SENSORS_EEPROM
 
 config SENSORS_PCF8574
        tristate "Philips PCF8574 and PCF8574A"
-       depends on I2C && EXPERIMENTAL
+       depends on EXPERIMENTAL
        default n
        help
          If you say yes here you get support for Philips PCF8574 and 
@@ -52,7 +51,7 @@ config SENSORS_PCF8574
 
 config SENSORS_PCA9539
        tristate "Philips PCA9539 16-bit I/O port"
-       depends on I2C && EXPERIMENTAL
+       depends on EXPERIMENTAL
        help
          If you say yes here you get support for the Philips PCA9539
          16-bit I/O port.
@@ -62,7 +61,7 @@ config SENSORS_PCA9539
 
 config SENSORS_PCF8591
        tristate "Philips PCF8591"
-       depends on I2C && EXPERIMENTAL
+       depends on EXPERIMENTAL
        default n
        help
          If you say yes here you get support for Philips PCF8591 chips.
@@ -75,7 +74,7 @@ config SENSORS_PCF8591
 
 config ISP1301_OMAP
        tristate "Philips ISP1301 with OMAP OTG"
-       depends on I2C && ARCH_OMAP_OTG
+       depends on ARCH_OMAP_OTG
        help
          If you say yes here you get support for the Philips ISP1301
          USB-On-The-Go transceiver working with the OMAP OTG controller.
@@ -90,7 +89,7 @@ config ISP1301_OMAP
 # and having mostly OMAP-specific board support
 config TPS65010
        tristate "TPS6501x Power Management chips"
-       depends on I2C && ARCH_OMAP
+       depends on ARCH_OMAP
        default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
        help
          If you say yes here you get support for the TPS6501x series of
@@ -103,7 +102,7 @@ config TPS65010
 
 config SENSORS_M41T00
        tristate "ST M41T00 RTC chip"
-       depends on I2C && PPC32
+       depends on PPC32
        help
          If you say yes here you get support for the ST M41T00 RTC chip.
 
@@ -112,7 +111,7 @@ config SENSORS_M41T00
 
 config SENSORS_MAX6875
        tristate "Maxim MAX6875 Power supply supervisor"
-       depends on I2C && EXPERIMENTAL
+       depends on EXPERIMENTAL
        help
          If you say yes here you get support for the Maxim MAX6875
          EEPROM-programmable, quad power-supply sequencer/supervisor.
diff --git a/drivers/i2c/i2c-boardinfo.c b/drivers/i2c/i2c-boardinfo.c
new file mode 100644 (file)
index 0000000..ffb35f0
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * i2c-boardinfo.h - collect pre-declarations of I2C devices
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+
+#include "i2c-core.h"
+
+
+/* These symbols are exported ONLY FOR the i2c core.
+ * No other users will be supported.
+ */
+DEFINE_MUTEX(__i2c_board_lock);
+EXPORT_SYMBOL_GPL(__i2c_board_lock);
+
+LIST_HEAD(__i2c_board_list);
+EXPORT_SYMBOL_GPL(__i2c_board_list);
+
+int __i2c_first_dynamic_bus_num;
+EXPORT_SYMBOL_GPL(__i2c_first_dynamic_bus_num);
+
+
+/**
+ * i2c_register_board_info - statically declare I2C devices
+ * @busnum: identifies the bus to which these devices belong
+ * @info: vector of i2c device descriptors
+ * @len: how many descriptors in the vector; may be zero to reserve
+ *     the specified bus number.
+ *
+ * Systems using the Linux I2C driver stack can declare tables of board info
+ * while they initialize.  This should be done in board-specific init code
+ * near arch_initcall() time, or equivalent, before any I2C adapter driver is
+ * registered.  For example, mainboard init code could define several devices,
+ * as could the init code for each daughtercard in a board stack.
+ *
+ * The I2C devices will be created later, after the adapter for the relevant
+ * bus has been registered.  After that moment, standard driver model tools
+ * are used to bind "new style" I2C drivers to the devices.  The bus number
+ * for any device declared using this routine is not available for dynamic
+ * allocation.
+ *
+ * The board info passed can safely be __initdata, but be careful of embedded
+ * pointers (for platform_data, functions, etc) since that won't be copied.
+ */
+int __init
+i2c_register_board_info(int busnum,
+       struct i2c_board_info const *info, unsigned len)
+{
+       int status;
+
+       mutex_lock(&__i2c_board_lock);
+
+       /* dynamic bus numbers will be assigned after the last static one */
+       if (busnum >= __i2c_first_dynamic_bus_num)
+               __i2c_first_dynamic_bus_num = busnum + 1;
+
+       for (status = 0; len; len--, info++) {
+               struct i2c_devinfo      *devinfo;
+
+               devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
+               if (!devinfo) {
+                       pr_debug("i2c-core: can't register boardinfo!\n");
+                       status = -ENOMEM;
+                       break;
+               }
+
+               devinfo->busnum = busnum;
+               devinfo->board_info = *info;
+               list_add_tail(&devinfo->list, &__i2c_board_list);
+       }
+
+       mutex_unlock(&__i2c_board_lock);
+
+       return status;
+}
index 21fe140..64f8e56 100644 (file)
 #include <linux/completion.h>
 #include <asm/uaccess.h>
 
+#include "i2c-core.h"
+
 
 static LIST_HEAD(adapters);
 static LIST_HEAD(drivers);
 static DEFINE_MUTEX(core_lists);
 static DEFINE_IDR(i2c_adapter_idr);
 
+#define is_newstyle_driver(d) ((d)->probe || (d)->remove)
 
 /* ------------------------------------------------------------------------- */
 
-/* match always succeeds, as we want the probe() to tell if we really accept this match */
 static int i2c_device_match(struct device *dev, struct device_driver *drv)
 {
-       return 1;
+       struct i2c_client       *client = to_i2c_client(dev);
+       struct i2c_driver       *driver = to_i2c_driver(drv);
+
+       /* make legacy i2c drivers bypass driver model probing entirely;
+        * such drivers scan each i2c adapter/bus themselves.
+        */
+       if (!is_newstyle_driver(driver))
+               return 0;
+
+       /* new style drivers use the same kind of driver matching policy
+        * as platform devices or SPI:  compare device and driver IDs.
+        */
+       return strcmp(client->driver_name, drv->name) == 0;
+}
+
+#ifdef CONFIG_HOTPLUG
+
+/* uevent helps with hotplug: modprobe -q $(MODALIAS) */
+static int i2c_device_uevent(struct device *dev, char **envp, int num_envp,
+                     char *buffer, int buffer_size)
+{
+       struct i2c_client       *client = to_i2c_client(dev);
+       int                     i = 0, length = 0;
+
+       /* by definition, legacy drivers can't hotplug */
+       if (dev->driver || !client->driver_name)
+               return 0;
+
+       if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+                       "MODALIAS=%s", client->driver_name))
+               return -ENOMEM;
+       envp[i] = NULL;
+       dev_dbg(dev, "uevent\n");
+       return 0;
 }
 
+#else
+#define i2c_device_uevent      NULL
+#endif /* CONFIG_HOTPLUG */
+
 static int i2c_device_probe(struct device *dev)
 {
-       return -ENODEV;
+       struct i2c_client       *client = to_i2c_client(dev);
+       struct i2c_driver       *driver = to_i2c_driver(dev->driver);
+
+       if (!driver->probe)
+               return -ENODEV;
+       client->driver = driver;
+       dev_dbg(dev, "probe\n");
+       return driver->probe(client);
 }
 
 static int i2c_device_remove(struct device *dev)
 {
-       return 0;
+       struct i2c_client       *client = to_i2c_client(dev);
+       struct i2c_driver       *driver;
+       int                     status;
+
+       if (!dev->driver)
+               return 0;
+
+       driver = to_i2c_driver(dev->driver);
+       if (driver->remove) {
+               dev_dbg(dev, "remove\n");
+               status = driver->remove(client);
+       } else {
+               dev->driver = NULL;
+               status = 0;
+       }
+       if (status == 0)
+               client->driver = NULL;
+       return status;
 }
 
 static void i2c_device_shutdown(struct device *dev)
@@ -95,122 +158,184 @@ static int i2c_device_resume(struct device * dev)
        return driver->resume(to_i2c_client(dev));
 }
 
+static void i2c_client_release(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       complete(&client->released);
+}
+
+static void i2c_client_dev_release(struct device *dev)
+{
+       kfree(to_i2c_client(dev));
+}
+
+static ssize_t show_client_name(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       return sprintf(buf, "%s\n", client->name);
+}
+
+static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       return client->driver_name
+               ? sprintf(buf, "%s\n", client->driver_name)
+               : 0;
+}
+
+static struct device_attribute i2c_dev_attrs[] = {
+       __ATTR(name, S_IRUGO, show_client_name, NULL),
+       /* modalias helps coldplug:  modprobe $(cat .../modalias) */
+       __ATTR(modalias, S_IRUGO, show_modalias, NULL),
+       { },
+};
+
 struct bus_type i2c_bus_type = {
        .name           = "i2c",
+       .dev_attrs      = i2c_dev_attrs,
        .match          = i2c_device_match,
+       .uevent         = i2c_device_uevent,
        .probe          = i2c_device_probe,
        .remove         = i2c_device_remove,
        .shutdown       = i2c_device_shutdown,
        .suspend        = i2c_device_suspend,
        .resume         = i2c_device_resume,
 };
+EXPORT_SYMBOL_GPL(i2c_bus_type);
 
-/* ------------------------------------------------------------------------- */
+/**
+ * i2c_new_device - instantiate an i2c device for use with a new style driver
+ * @adap: the adapter managing the device
+ * @info: describes one I2C device; bus_num is ignored
+ *
+ * Create a device to work with a new style i2c driver, where binding is
+ * handled through driver model probe()/remove() methods.  This call is not
+ * appropriate for use by mainboad initialization logic, which usually runs
+ * during an arch_initcall() long before any i2c_adapter could exist.
+ *
+ * This returns the new i2c client, which may be saved for later use with
+ * i2c_unregister_device(); or NULL to indicate an error.
+ */
+struct i2c_client *
+i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
+{
+       struct i2c_client       *client;
+       int                     status;
 
-void i2c_adapter_dev_release(struct device *dev)
+       client = kzalloc(sizeof *client, GFP_KERNEL);
+       if (!client)
+               return NULL;
+
+       client->adapter = adap;
+
+       client->dev.platform_data = info->platform_data;
+       client->flags = info->flags;
+       client->addr = info->addr;
+       client->irq = info->irq;
+
+       strlcpy(client->driver_name, info->driver_name,
+               sizeof(client->driver_name));
+       strlcpy(client->name, info->type, sizeof(client->name));
+
+       /* a new style driver may be bound to this device when we
+        * return from this function, or any later moment (e.g. maybe
+        * hotplugging will load the driver module).  and the device
+        * refcount model is the standard driver model one.
+        */
+       status = i2c_attach_client(client);
+       if (status < 0) {
+               kfree(client);
+               client = NULL;
+       }
+       return client;
+}
+EXPORT_SYMBOL_GPL(i2c_new_device);
+
+
+/**
+ * i2c_unregister_device - reverse effect of i2c_new_device()
+ * @client: value returned from i2c_new_device()
+ */
+void i2c_unregister_device(struct i2c_client *client)
 {
-       struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
-       complete(&adap->dev_released);
+       struct i2c_adapter      *adapter = client->adapter;
+       struct i2c_driver       *driver = client->driver;
+
+       if (driver && !is_newstyle_driver(driver)) {
+               dev_err(&client->dev, "can't unregister devices "
+                       "with legacy drivers\n");
+               WARN_ON(1);
+               return;
+       }
+
+       mutex_lock(&adapter->clist_lock);
+       list_del(&client->list);
+       mutex_unlock(&adapter->clist_lock);
+
+       device_unregister(&client->dev);
 }
+EXPORT_SYMBOL_GPL(i2c_unregister_device);
 
-struct device_driver i2c_adapter_driver = {
-       .owner = THIS_MODULE,
-       .name = "i2c_adapter",
-       .bus = &i2c_bus_type,
-};
 
 /* ------------------------------------------------------------------------- */
 
 /* I2C bus adapters -- one roots each I2C or SMBUS segment */
 
-static void i2c_adapter_class_dev_release(struct class_device *dev)
+void i2c_adapter_dev_release(struct device *dev)
 {
-       struct i2c_adapter *adap = class_dev_to_i2c_adapter(dev);
-       complete(&adap->class_dev_released);
+       struct i2c_adapter *adap = to_i2c_adapter(dev);
+       complete(&adap->dev_released);
 }
+EXPORT_SYMBOL_GPL(i2c_adapter_dev_release);    /* exported to i2c-isa */
 
-static ssize_t i2c_adapter_show_name(struct class_device *cdev, char *buf)
+static ssize_t
+show_adapter_name(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct i2c_adapter *adap = class_dev_to_i2c_adapter(cdev);
+       struct i2c_adapter *adap = to_i2c_adapter(dev);
        return sprintf(buf, "%s\n", adap->name);
 }
 
-static struct class_device_attribute i2c_adapter_attrs[] = {
-       __ATTR(name, S_IRUGO, i2c_adapter_show_name, NULL),
+static struct device_attribute i2c_adapter_attrs[] = {
+       __ATTR(name, S_IRUGO, show_adapter_name, NULL),
        { },
 };
 
 struct class i2c_adapter_class = {
        .owner                  = THIS_MODULE,
        .name                   = "i2c-adapter",
-       .class_dev_attrs        = i2c_adapter_attrs,
-       .release                = &i2c_adapter_class_dev_release,
+       .dev_attrs              = i2c_adapter_attrs,
 };
+EXPORT_SYMBOL_GPL(i2c_adapter_class);          /* exported to i2c-isa */
 
-static ssize_t show_adapter_name(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
-       return sprintf(buf, "%s\n", adap->name);
-}
-static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
-
-
-static void i2c_client_release(struct device *dev)
-{
-       struct i2c_client *client = to_i2c_client(dev);
-       complete(&client->released);
-}
-
-static ssize_t show_client_name(struct device *dev, struct device_attribute *attr, char *buf)
+static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       return sprintf(buf, "%s\n", client->name);
+       struct i2c_devinfo      *devinfo;
+
+       mutex_lock(&__i2c_board_lock);
+       list_for_each_entry(devinfo, &__i2c_board_list, list) {
+               if (devinfo->busnum == adapter->nr
+                               && !i2c_new_device(adapter,
+                                               &devinfo->board_info))
+                       printk(KERN_ERR "i2c-core: can't create i2c%d-%04x\n",
+                               i2c_adapter_id(adapter),
+                               devinfo->board_info.addr);
+       }
+       mutex_unlock(&__i2c_board_lock);
 }
 
-/*
- * We can't use the DEVICE_ATTR() macro here, as we used the same name for
- * an i2c adapter attribute (above).
- */
-static struct device_attribute dev_attr_client_name =
-       __ATTR(name, S_IRUGO, &show_client_name, NULL);
-
-
-/* ---------------------------------------------------
- * registering functions
- * ---------------------------------------------------
- */
-
-/* -----
- * i2c_add_adapter is called from within the algorithm layer,
- * when a new hw adapter registers. A new device is register to be
- * available for clients.
- */
-int i2c_add_adapter(struct i2c_adapter *adap)
+static int i2c_register_adapter(struct i2c_adapter *adap)
 {
-       int id, res = 0;
+       int res = 0;
        struct list_head   *item;
        struct i2c_driver  *driver;
 
-       mutex_lock(&core_lists);
-
-       if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) {
-               res = -ENOMEM;
-               goto out_unlock;
-       }
-
-       res = idr_get_new(&i2c_adapter_idr, adap, &id);
-       if (res < 0) {
-               if (res == -EAGAIN)
-                       res = -ENOMEM;
-               goto out_unlock;
-       }
-
-       adap->nr =  id & MAX_ID_MASK;
        mutex_init(&adap->bus_lock);
        mutex_init(&adap->clist_lock);
-       list_add_tail(&adap->list,&adapters);
        INIT_LIST_HEAD(&adap->clients);
 
+       mutex_lock(&core_lists);
+       list_add_tail(&adap->list, &adapters);
+
        /* Add the adapter to the driver core.
         * If the parent pointer is not set up,
         * we add this adapter to the host bus.
@@ -221,27 +346,19 @@ int i2c_add_adapter(struct i2c_adapter *adap)
                         "physical device\n", adap->name);
        }
        sprintf(adap->dev.bus_id, "i2c-%d", adap->nr);
-       adap->dev.driver = &i2c_adapter_driver;
        adap->dev.release = &i2c_adapter_dev_release;
+       adap->dev.class = &i2c_adapter_class;
        res = device_register(&adap->dev);
        if (res)
                goto out_list;
-       res = device_create_file(&adap->dev, &dev_attr_name);
-       if (res)
-               goto out_unregister;
-
-       /* Add this adapter to the i2c_adapter class */
-       memset(&adap->class_dev, 0x00, sizeof(struct class_device));
-       adap->class_dev.dev = &adap->dev;
-       adap->class_dev.class = &i2c_adapter_class;
-       strlcpy(adap->class_dev.class_id, adap->dev.bus_id, BUS_ID_SIZE);
-       res = class_device_register(&adap->class_dev);
-       if (res)
-               goto out_remove_name;
 
        dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
 
-       /* inform drivers of new adapters */
+       /* create pre-declared device nodes for new-style drivers */
+       if (adap->nr < __i2c_first_dynamic_bus_num)
+               i2c_scan_static_board_info(adap);
+
+       /* let legacy drivers scan this bus for matching devices */
        list_for_each(item,&drivers) {
                driver = list_entry(item, struct i2c_driver, list);
                if (driver->attach_adapter)
@@ -253,18 +370,98 @@ out_unlock:
        mutex_unlock(&core_lists);
        return res;
 
-out_remove_name:
-       device_remove_file(&adap->dev, &dev_attr_name);
-out_unregister:
-       init_completion(&adap->dev_released); /* Needed? */
-       device_unregister(&adap->dev);
-       wait_for_completion(&adap->dev_released);
 out_list:
        list_del(&adap->list);
        idr_remove(&i2c_adapter_idr, adap->nr);
        goto out_unlock;
 }
 
+/**
+ * i2c_add_adapter - declare i2c adapter, use dynamic bus number
+ * @adapter: the adapter to add
+ *
+ * This routine is used to declare an I2C adapter when its bus number
+ * doesn't matter.  Examples: for I2C adapters dynamically added by
+ * USB links or PCI plugin cards.
+ *
+ * When this returns zero, a new bus number was allocated and stored
+ * in adap->nr, and the specified adapter became available for clients.
+ * Otherwise, a negative errno value is returned.
+ */
+int i2c_add_adapter(struct i2c_adapter *adapter)
+{
+       int     id, res = 0;
+
+retry:
+       if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
+               return -ENOMEM;
+
+       mutex_lock(&core_lists);
+       /* "above" here means "above or equal to", sigh */
+       res = idr_get_new_above(&i2c_adapter_idr, adapter,
+                               __i2c_first_dynamic_bus_num, &id);
+       mutex_unlock(&core_lists);
+
+       if (res < 0) {
+               if (res == -EAGAIN)
+                       goto retry;
+               return res;
+       }
+
+       adapter->nr = id;
+       return i2c_register_adapter(adapter);
+}
+EXPORT_SYMBOL(i2c_add_adapter);
+
+/**
+ * i2c_add_numbered_adapter - declare i2c adapter, use static bus number
+ * @adap: the adapter to register (with adap->nr initialized)
+ *
+ * This routine is used to declare an I2C adapter when its bus number
+ * matters.  Example: for I2C adapters from system-on-chip CPUs, or
+ * otherwise built in to the system's mainboard, and where i2c_board_info
+ * is used to properly configure I2C devices.
+ *
+ * If no devices have pre-been declared for this bus, then be sure to
+ * register the adapter before any dynamically allocated ones.  Otherwise
+ * the required bus ID may not be available.
+ *
+ * When this returns zero, the specified adapter became available for
+ * clients using the bus number provided in adap->nr.  Also, the table
+ * of I2C devices pre-declared using i2c_register_board_info() is scanned,
+ * and the appropriate driver model device nodes are created.  Otherwise, a
+ * negative errno value is returned.
+ */
+int i2c_add_numbered_adapter(struct i2c_adapter *adap)
+{
+       int     id;
+       int     status;
+
+       if (adap->nr & ~MAX_ID_MASK)
+               return -EINVAL;
+
+retry:
+       if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
+               return -ENOMEM;
+
+       mutex_lock(&core_lists);
+       /* "above" here means "above or equal to", sigh;
+        * we need the "equal to" result to force the result
+        */
+       status = idr_get_new_above(&i2c_adapter_idr, adap, adap->nr, &id);
+       if (status == 0 && id != adap->nr) {
+               status = -EBUSY;
+               idr_remove(&i2c_adapter_idr, id);
+       }
+       mutex_unlock(&core_lists);
+       if (status == -EAGAIN)
+               goto retry;
+
+       if (status == 0)
+               status = i2c_register_adapter(adap);
+       return status;
+}
+EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter);
 
 int i2c_del_adapter(struct i2c_adapter *adap)
 {
@@ -302,9 +499,19 @@ int i2c_del_adapter(struct i2c_adapter *adap)
        /* detach any active clients. This must be done first, because
         * it can fail; in which case we give up. */
        list_for_each_safe(item, _n, &adap->clients) {
+               struct i2c_driver       *driver;
+
                client = list_entry(item, struct i2c_client, list);
+               driver = client->driver;
+
+               /* new style, follow standard driver model */
+               if (!driver || is_newstyle_driver(driver)) {
+                       i2c_unregister_device(client);
+                       continue;
+               }
 
-               if ((res=client->driver->detach_client(client))) {
+               /* legacy drivers create and remove clients themselves */
+               if ((res = driver->detach_client(client))) {
                        dev_err(&adap->dev, "detach_client failed for client "
                                "[%s] at address 0x%02x\n", client->name,
                                client->addr);
@@ -314,17 +521,13 @@ int i2c_del_adapter(struct i2c_adapter *adap)
 
        /* clean up the sysfs representation */
        init_completion(&adap->dev_released);
-       init_completion(&adap->class_dev_released);
-       class_device_unregister(&adap->class_dev);
-       device_remove_file(&adap->dev, &dev_attr_name);
        device_unregister(&adap->dev);
        list_del(&adap->list);
 
        /* wait for sysfs to drop all references */
        wait_for_completion(&adap->dev_released);
-       wait_for_completion(&adap->class_dev_released);
 
-       /* free dynamically allocated bus id */
+       /* free bus id */
        idr_remove(&i2c_adapter_idr, adap->nr);
 
        dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
@@ -333,24 +536,42 @@ int i2c_del_adapter(struct i2c_adapter *adap)
        mutex_unlock(&core_lists);
        return res;
 }
+EXPORT_SYMBOL(i2c_del_adapter);
+
 
+/* ------------------------------------------------------------------------- */
 
-/* -----
- * What follows is the "upwards" interface: commands for talking to clients,
- * which implement the functions to access the physical information of the
- * chips.
+/*
+ * An i2c_driver is used with one or more i2c_client (device) nodes to access
+ * i2c slave chips, on a bus instance associated with some i2c_adapter.  There
+ * are two models for binding the driver to its device:  "new style" drivers
+ * follow the standard Linux driver model and just respond to probe() calls
+ * issued if the driver core sees they match(); "legacy" drivers create device
+ * nodes themselves.
  */
 
 int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
 {
-       struct list_head   *item;
-       struct i2c_adapter *adapter;
        int res;
 
+       /* new style driver methods can't mix with legacy ones */
+       if (is_newstyle_driver(driver)) {
+               if (driver->attach_adapter || driver->detach_adapter
+                               || driver->detach_client) {
+                       printk(KERN_WARNING
+                                       "i2c-core: driver [%s] is confused\n",
+                                       driver->driver.name);
+                       return -EINVAL;
+               }
+       }
+
        /* add the driver to the list of i2c drivers in the driver core */
        driver->driver.owner = owner;
        driver->driver.bus = &i2c_bus_type;
 
+       /* for new style drivers, when registration returns the driver core
+        * will have called probe() for all matching-but-unbound devices.
+        */
        res = driver_register(&driver->driver);
        if (res)
                return res;
@@ -360,10 +581,11 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
        list_add_tail(&driver->list,&drivers);
        pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
 
-       /* now look for instances of driver on our adapters */
+       /* legacy drivers scan i2c busses directly */
        if (driver->attach_adapter) {
-               list_for_each(item,&adapters) {
-                       adapter = list_entry(item, struct i2c_adapter, list);
+               struct i2c_adapter *adapter;
+
+               list_for_each_entry(adapter, &adapters, list) {
                        driver->attach_adapter(adapter);
                }
        }
@@ -373,16 +595,22 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
 }
 EXPORT_SYMBOL(i2c_register_driver);
 
-int i2c_del_driver(struct i2c_driver *driver)
+/**
+ * i2c_del_driver - unregister I2C driver
+ * @driver: the driver being unregistered
+ */
+void i2c_del_driver(struct i2c_driver *driver)
 {
        struct list_head   *item1, *item2, *_n;
        struct i2c_client  *client;
        struct i2c_adapter *adap;
 
-       int res = 0;
-
        mutex_lock(&core_lists);
 
+       /* new-style driver? */
+       if (is_newstyle_driver(driver))
+               goto unregister;
+
        /* Have a look at each adapter, if clients of this driver are still
         * attached. If so, detach them to be able to kill the driver
         * afterwards.
@@ -390,11 +618,10 @@ int i2c_del_driver(struct i2c_driver *driver)
        list_for_each(item1,&adapters) {
                adap = list_entry(item1, struct i2c_adapter, list);
                if (driver->detach_adapter) {
-                       if ((res = driver->detach_adapter(adap))) {
+                       if (driver->detach_adapter(adap)) {
                                dev_err(&adap->dev, "detach_adapter failed "
                                        "for driver [%s]\n",
                                        driver->driver.name);
-                               goto out_unlock;
                        }
                } else {
                        list_for_each_safe(item2, _n, &adap->clients) {
@@ -404,25 +631,26 @@ int i2c_del_driver(struct i2c_driver *driver)
                                dev_dbg(&adap->dev, "detaching client [%s] "
                                        "at 0x%02x\n", client->name,
                                        client->addr);
-                               if ((res = driver->detach_client(client))) {
+                               if (driver->detach_client(client)) {
                                        dev_err(&adap->dev, "detach_client "
                                                "failed for client [%s] at "
                                                "0x%02x\n", client->name,
                                                client->addr);
-                                       goto out_unlock;
                                }
                        }
                }
        }
 
+ unregister:
        driver_unregister(&driver->driver);
        list_del(&driver->list);
        pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
 
- out_unlock:
        mutex_unlock(&core_lists);
-       return 0;
 }
+EXPORT_SYMBOL(i2c_del_driver);
+
+/* ------------------------------------------------------------------------- */
 
 static int __i2c_check_addr(struct i2c_adapter *adapter, unsigned int addr)
 {
@@ -447,6 +675,7 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr)
 
        return rval;
 }
+EXPORT_SYMBOL(i2c_check_addr);
 
 int i2c_attach_client(struct i2c_client *client)
 {
@@ -463,9 +692,15 @@ int i2c_attach_client(struct i2c_client *client)
        client->usage_count = 0;
 
        client->dev.parent = &client->adapter->dev;
-       client->dev.driver = &client->driver->driver;
        client->dev.bus = &i2c_bus_type;
-       client->dev.release = &i2c_client_release;
+
+       if (client->driver)
+               client->dev.driver = &client->driver->driver;
+
+       if (client->driver && !is_newstyle_driver(client->driver))
+               client->dev.release = i2c_client_release;
+       else
+               client->dev.release = i2c_client_dev_release;
 
        snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
                "%d-%04x", i2c_adapter_id(adapter), client->addr);
@@ -474,9 +709,6 @@ int i2c_attach_client(struct i2c_client *client)
        res = device_register(&client->dev);
        if (res)
                goto out_list;
-       res = device_create_file(&client->dev, &dev_attr_client_name);
-       if (res)
-               goto out_unregister;
        mutex_unlock(&adapter->clist_lock);
 
        if (adapter->client_register)  {
@@ -489,10 +721,6 @@ int i2c_attach_client(struct i2c_client *client)
 
        return 0;
 
-out_unregister:
-       init_completion(&client->released); /* Needed? */
-       device_unregister(&client->dev);
-       wait_for_completion(&client->released);
 out_list:
        list_del(&client->list);
        dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x "
@@ -501,7 +729,7 @@ out_unlock:
        mutex_unlock(&adapter->clist_lock);
        return res;
 }
-
+EXPORT_SYMBOL(i2c_attach_client);
 
 int i2c_detach_client(struct i2c_client *client)
 {
@@ -527,7 +755,6 @@ int i2c_detach_client(struct i2c_client *client)
        mutex_lock(&adapter->clist_lock);
        list_del(&client->list);
        init_completion(&client->released);
-       device_remove_file(&client->dev, &dev_attr_client_name);
        device_unregister(&client->dev);
        mutex_unlock(&adapter->clist_lock);
        wait_for_completion(&client->released);
@@ -535,6 +762,7 @@ int i2c_detach_client(struct i2c_client *client)
  out:
        return res;
 }
+EXPORT_SYMBOL(i2c_detach_client);
 
 static int i2c_inc_use_client(struct i2c_client *client)
 {
@@ -567,6 +795,7 @@ int i2c_use_client(struct i2c_client *client)
 
        return 0;
 }
+EXPORT_SYMBOL(i2c_use_client);
 
 int i2c_release_client(struct i2c_client *client)
 {
@@ -581,6 +810,7 @@ int i2c_release_client(struct i2c_client *client)
 
        return 0;
 }
+EXPORT_SYMBOL(i2c_release_client);
 
 void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)
 {
@@ -601,6 +831,7 @@ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)
        }
        mutex_unlock(&adap->clist_lock);
 }
+EXPORT_SYMBOL(i2c_clients_command);
 
 static int __init i2c_init(void)
 {
@@ -609,16 +840,12 @@ static int __init i2c_init(void)
        retval = bus_register(&i2c_bus_type);
        if (retval)
                return retval;
-       retval = driver_register(&i2c_adapter_driver);
-       if (retval)
-               return retval;
        return class_register(&i2c_adapter_class);
 }
 
 static void __exit i2c_exit(void)
 {
        class_unregister(&i2c_adapter_class);
-       driver_unregister(&i2c_adapter_driver);
        bus_unregister(&i2c_bus_type);
 }
 
@@ -638,8 +865,9 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
 #ifdef DEBUG
                for (ret = 0; ret < num; ret++) {
                        dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, "
-                               "len=%d\n", ret, msgs[ret].flags & I2C_M_RD ?
-                               'R' : 'W', msgs[ret].addr, msgs[ret].len);
+                               "len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD)
+                               ? 'R' : 'W', msgs[ret].addr, msgs[ret].len,
+                               (msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : "");
                }
 #endif
 
@@ -653,6 +881,7 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
                return -ENOSYS;
        }
 }
+EXPORT_SYMBOL(i2c_transfer);
 
 int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
 {
@@ -671,6 +900,7 @@ int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
           transmitted, else error code. */
        return (ret == 1) ? count : ret;
 }
+EXPORT_SYMBOL(i2c_master_send);
 
 int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
 {
@@ -690,7 +920,7 @@ int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
           transmitted, else error code. */
        return (ret == 1) ? count : ret;
 }
-
+EXPORT_SYMBOL(i2c_master_recv);
 
 int i2c_control(struct i2c_client *client,
        unsigned int cmd, unsigned long arg)
@@ -712,6 +942,7 @@ int i2c_control(struct i2c_client *client,
        }
        return ret;
 }
+EXPORT_SYMBOL(i2c_control);
 
 /* ----------------------------------------------------
  * the i2c address scanning function
@@ -853,6 +1084,70 @@ int i2c_probe(struct i2c_adapter *adapter,
 
        return 0;
 }
+EXPORT_SYMBOL(i2c_probe);
+
+struct i2c_client *
+i2c_new_probed_device(struct i2c_adapter *adap,
+                     struct i2c_board_info *info,
+                     unsigned short const *addr_list)
+{
+       int i;
+
+       /* Stop here if the bus doesn't support probing */
+       if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE)) {
+               dev_err(&adap->dev, "Probing not supported\n");
+               return NULL;
+       }
+
+       mutex_lock(&adap->clist_lock);
+       for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) {
+               /* Check address validity */
+               if (addr_list[i] < 0x03 || addr_list[i] > 0x77) {
+                       dev_warn(&adap->dev, "Invalid 7-bit address "
+                                "0x%02x\n", addr_list[i]);
+                       continue;
+               }
+
+               /* Check address availability */
+               if (__i2c_check_addr(adap, addr_list[i])) {
+                       dev_dbg(&adap->dev, "Address 0x%02x already in "
+                               "use, not probing\n", addr_list[i]);
+                       continue;
+               }
+
+               /* Test address responsiveness
+                  The default probe method is a quick write, but it is known
+                  to corrupt the 24RF08 EEPROMs due to a state machine bug,
+                  and could also irreversibly write-protect some EEPROMs, so
+                  for address ranges 0x30-0x37 and 0x50-0x5f, we use a byte
+                  read instead. Also, some bus drivers don't implement
+                  quick write, so we fallback to a byte read it that case
+                  too. */
+               if ((addr_list[i] & ~0x07) == 0x30
+                || (addr_list[i] & ~0x0f) == 0x50
+                || !i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK)) {
+                       if (i2c_smbus_xfer(adap, addr_list[i], 0,
+                                          I2C_SMBUS_READ, 0,
+                                          I2C_SMBUS_BYTE, NULL) >= 0)
+                               break;
+               } else {
+                       if (i2c_smbus_xfer(adap, addr_list[i], 0,
+                                          I2C_SMBUS_WRITE, 0,
+                                          I2C_SMBUS_QUICK, NULL) >= 0)
+                               break;
+               }
+       }
+       mutex_unlock(&adap->clist_lock);
+
+       if (addr_list[i] == I2C_CLIENT_END) {
+               dev_dbg(&adap->dev, "Probing failed, no device found\n");
+               return NULL;
+       }
+
+       info->addr = addr_list[i];
+       return i2c_new_device(adap, info);
+}
+EXPORT_SYMBOL_GPL(i2c_new_probed_device);
 
 struct i2c_adapter* i2c_get_adapter(int id)
 {
@@ -866,11 +1161,13 @@ struct i2c_adapter* i2c_get_adapter(int id)
        mutex_unlock(&core_lists);
        return adapter;
 }
+EXPORT_SYMBOL(i2c_get_adapter);
 
 void i2c_put_adapter(struct i2c_adapter *adap)
 {
        module_put(adap->owner);
 }
+EXPORT_SYMBOL(i2c_put_adapter);
 
 /* The SMBus parts */
 
@@ -939,6 +1236,7 @@ s32 i2c_smbus_write_quick(struct i2c_client *client, u8 value)
        return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
                              value,0,I2C_SMBUS_QUICK,NULL);
 }
+EXPORT_SYMBOL(i2c_smbus_write_quick);
 
 s32 i2c_smbus_read_byte(struct i2c_client *client)
 {
@@ -949,12 +1247,14 @@ s32 i2c_smbus_read_byte(struct i2c_client *client)
        else
                return data.byte;
 }
+EXPORT_SYMBOL(i2c_smbus_read_byte);
 
 s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
 {
        return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
                              I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
 }
+EXPORT_SYMBOL(i2c_smbus_write_byte);
 
 s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
 {
@@ -965,6 +1265,7 @@ s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
        else
                return data.byte;
 }
+EXPORT_SYMBOL(i2c_smbus_read_byte_data);
 
 s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value)
 {
@@ -974,6 +1275,7 @@ s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value)
                              I2C_SMBUS_WRITE,command,
                              I2C_SMBUS_BYTE_DATA,&data);
 }
+EXPORT_SYMBOL(i2c_smbus_write_byte_data);
 
 s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command)
 {
@@ -984,6 +1286,7 @@ s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command)
        else
                return data.word;
 }
+EXPORT_SYMBOL(i2c_smbus_read_word_data);
 
 s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
 {
@@ -993,6 +1296,23 @@ s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
                              I2C_SMBUS_WRITE,command,
                              I2C_SMBUS_WORD_DATA,&data);
 }
+EXPORT_SYMBOL(i2c_smbus_write_word_data);
+
+/* Returns the number of read bytes */
+s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command,
+                             u8 *values)
+{
+       union i2c_smbus_data data;
+
+       if (i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+                          I2C_SMBUS_READ, command,
+                          I2C_SMBUS_BLOCK_DATA, &data))
+               return -1;
+
+       memcpy(values, &data.block[1], data.block[0]);
+       return data.block[0];
+}
+EXPORT_SYMBOL(i2c_smbus_read_block_data);
 
 s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
                               u8 length, const u8 *values)
@@ -1007,6 +1327,7 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
                              I2C_SMBUS_WRITE,command,
                              I2C_SMBUS_BLOCK_DATA,&data);
 }
+EXPORT_SYMBOL(i2c_smbus_write_block_data);
 
 /* Returns the number of read bytes */
 s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values)
@@ -1021,6 +1342,7 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *val
        memcpy(values, &data.block[1], data.block[0]);
        return data.block[0];
 }
+EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data);
 
 s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command,
                                   u8 length, const u8 *values)
@@ -1035,6 +1357,7 @@ s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command,
                              I2C_SMBUS_WRITE, command,
                              I2C_SMBUS_I2C_BLOCK_DATA, &data);
 }
+EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data);
 
 /* Simulate a SMBus command using the i2c protocol
    No checking of parameters is done!  */
@@ -1098,9 +1421,9 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                break;
        case I2C_SMBUS_BLOCK_DATA:
                if (read_write == I2C_SMBUS_READ) {
-                       dev_err(&adapter->dev, "Block read not supported "
-                              "under I2C emulation!\n");
-                       return -1;
+                       msg[1].flags |= I2C_M_RECV_LEN;
+                       msg[1].len = 1; /* block length will be added by
+                                          the underlying bus driver */
                } else {
                        msg[0].len = data->block[0] + 2;
                        if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) {
@@ -1114,9 +1437,21 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                }
                break;
        case I2C_SMBUS_BLOCK_PROC_CALL:
-               dev_dbg(&adapter->dev, "Block process call not supported "
-                      "under I2C emulation!\n");
-               return -1;
+               num = 2; /* Another special case */
+               read_write = I2C_SMBUS_READ;
+               if (data->block[0] > I2C_SMBUS_BLOCK_MAX) {
+                       dev_err(&adapter->dev, "%s called with invalid "
+                               "block proc call size (%d)\n", __FUNCTION__,
+                               data->block[0]);
+                       return -1;
+               }
+               msg[0].len = data->block[0] + 2;
+               for (i = 1; i < msg[0].len; i++)
+                       msgbuf0[i] = data->block[i-1];
+               msg[1].flags |= I2C_M_RECV_LEN;
+               msg[1].len = 1; /* block length will be added by
+                                  the underlying bus driver */
+               break;
        case I2C_SMBUS_I2C_BLOCK_DATA:
                if (read_write == I2C_SMBUS_READ) {
                        msg[1].len = I2C_SMBUS_BLOCK_MAX;
@@ -1180,6 +1515,11 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                                for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++)
                                        data->block[i+1] = msgbuf1[i];
                                break;
+                       case I2C_SMBUS_BLOCK_DATA:
+                       case I2C_SMBUS_BLOCK_PROC_CALL:
+                               for (i = 0; i < msgbuf1[0] + 1; i++)
+                                       data->block[i] = msgbuf1[i];
+                               break;
                }
        return 0;
 }
@@ -1204,43 +1544,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
 
        return res;
 }
-
-
-/* Next four are needed by i2c-isa */
-EXPORT_SYMBOL_GPL(i2c_adapter_dev_release);
-EXPORT_SYMBOL_GPL(i2c_adapter_driver);
-EXPORT_SYMBOL_GPL(i2c_adapter_class);
-EXPORT_SYMBOL_GPL(i2c_bus_type);
-
-EXPORT_SYMBOL(i2c_add_adapter);
-EXPORT_SYMBOL(i2c_del_adapter);
-EXPORT_SYMBOL(i2c_del_driver);
-EXPORT_SYMBOL(i2c_attach_client);
-EXPORT_SYMBOL(i2c_detach_client);
-EXPORT_SYMBOL(i2c_use_client);
-EXPORT_SYMBOL(i2c_release_client);
-EXPORT_SYMBOL(i2c_clients_command);
-EXPORT_SYMBOL(i2c_check_addr);
-
-EXPORT_SYMBOL(i2c_master_send);
-EXPORT_SYMBOL(i2c_master_recv);
-EXPORT_SYMBOL(i2c_control);
-EXPORT_SYMBOL(i2c_transfer);
-EXPORT_SYMBOL(i2c_get_adapter);
-EXPORT_SYMBOL(i2c_put_adapter);
-EXPORT_SYMBOL(i2c_probe);
-
 EXPORT_SYMBOL(i2c_smbus_xfer);
-EXPORT_SYMBOL(i2c_smbus_write_quick);
-EXPORT_SYMBOL(i2c_smbus_read_byte);
-EXPORT_SYMBOL(i2c_smbus_write_byte);
-EXPORT_SYMBOL(i2c_smbus_read_byte_data);
-EXPORT_SYMBOL(i2c_smbus_write_byte_data);
-EXPORT_SYMBOL(i2c_smbus_read_word_data);
-EXPORT_SYMBOL(i2c_smbus_write_word_data);
-EXPORT_SYMBOL(i2c_smbus_write_block_data);
-EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data);
-EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data);
 
 MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
 MODULE_DESCRIPTION("I2C-Bus main module");
diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h
new file mode 100644 (file)
index 0000000..cd5bff8
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * i2c-core.h - interfaces internal to the I2C framework
+ *
+ * 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.
+ */
+
+struct i2c_devinfo {
+       struct list_head        list;
+       int                     busnum;
+       struct i2c_board_info   board_info;
+};
+
+/* board_lock protects board_list and first_dynamic_bus_num.
+ * only i2c core components are allowed to use these symbols.
+ */
+extern struct mutex    __i2c_board_lock;
+extern struct list_head        __i2c_board_list;
+extern int             __i2c_first_dynamic_bus_num;
+
index 556455f..5e8efc8 100644 (file)
@@ -730,7 +730,7 @@ static int speed_cris_ide(ide_drive_t *drive, u8 speed)
 
        if (speed >= XFER_PIO_0 && speed <= XFER_PIO_4) {
                tune_cris_ide(drive, speed - XFER_PIO_0);
-               return 0;
+               return ide_config_drive_speed(drive, speed);
        }
 
        switch(speed)
@@ -760,7 +760,8 @@ static int speed_cris_ide(ide_drive_t *drive, u8 speed)
                        hold = ATA_DMA2_HOLD;
                        break;
                default:
-                       return 0;
+                       BUG();
+                       break;
        }
 
        if (speed >= XFER_UDMA_0)
@@ -768,7 +769,7 @@ static int speed_cris_ide(ide_drive_t *drive, u8 speed)
        else
                cris_ide_set_speed(TYPE_DMA, 0, strobe, hold);
 
-       return 0;
+       return ide_config_drive_speed(drive, speed);
 }
 
 void __init
@@ -821,7 +822,6 @@ init_e100_ide (void)
                hwif->udma_four = 0;
                hwif->ultra_mask = cris_ultra_mask;
                hwif->mwdma_mask = 0x07; /* Multiword DMA 0-2 */
-               hwif->swdma_mask = 0x07; /* Singleword DMA 0-2 */
                hwif->autodma = 1;
                hwif->drives[0].autodma = 1;
                hwif->drives[1].autodma = 1;
@@ -1010,7 +1010,6 @@ static int cris_config_drive_for_dma (ide_drive_t *drive)
                return 0;
 
        speed_cris_ide(drive, speed);
-       ide_config_drive_speed(drive, speed);
 
        return ide_dma_enable(drive);
 }
index b08c37c..c6522a6 100644 (file)
@@ -401,6 +401,7 @@ static struct pcmcia_device_id ide_ids[] = {
        PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
        PCMCIA_DEVICE_PROD_ID1("TRANSCEND    512M   ", 0xd0909443),
        PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),
+       PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2),
        PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
        PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
        PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918),
index 990eafe..73bdf64 100644 (file)
@@ -1,7 +1,8 @@
 /*
- * linux/drivers/ide/pci/aec62xx.c             Version 0.11    March 27, 2002
+ * linux/drivers/ide/pci/aec62xx.c             Version 0.21    Apr 21, 2007
  *
  * Copyright (C) 1999-2002     Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2007          MontaVista Software, Inc. <source@mvista.com>
  *
  */
 
@@ -193,18 +194,8 @@ static int config_chipset_for_dma (ide_drive_t *drive)
 
 static void aec62xx_tune_drive (ide_drive_t *drive, u8 pio)
 {
-       u8 speed = 0;
-       u8 new_pio = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
-
-       switch(pio) {
-               case 5:         speed = new_pio; break;
-               case 4:         speed = XFER_PIO_4; break;
-               case 3:         speed = XFER_PIO_3; break;
-               case 2:         speed = XFER_PIO_2; break;
-               case 1:         speed = XFER_PIO_1; break;
-               default:        speed = XFER_PIO_0; break;
-       }
-       (void) aec62xx_tune_chipset(drive, speed);
+       pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+       (void) aec62xx_tune_chipset(drive, pio + XFER_PIO_0);
 }
 
 static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive)
@@ -213,7 +204,7 @@ static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive)
                return 0;
 
        if (ide_use_fast_pio(drive))
-               aec62xx_tune_drive(drive, 5);
+               aec62xx_tune_drive(drive, 255);
 
        return -1;
 }
@@ -288,11 +279,10 @@ static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif)
 
        hwif->ultra_mask = 0x7f;
        hwif->mwdma_mask = 0x07;
-       hwif->swdma_mask = 0x07;
 
        hwif->ide_dma_check     = &aec62xx_config_drive_xfer_rate;
        hwif->ide_dma_lostirq   = &aec62xx_irq_timeout;
-       hwif->ide_dma_timeout   = &aec62xx_irq_timeout;
+
        if (!noautodma)
                hwif->autodma = 1;
        hwif->drives[0].autodma = hwif->autodma;
index 83e0aa6..946a127 100644 (file)
@@ -534,7 +534,7 @@ static int ali15x3_config_drive_for_dma(ide_drive_t *drive)
        struct hd_driveid *id   = drive->id;
 
        if ((m5229_revision<=0x20) && (drive->media!=ide_disk))
-               goto no_dma_set;
+               goto ata_pio;
 
        drive->init_speed = 0;
 
@@ -555,20 +555,19 @@ try_dma_modes:
                            (id->dma_1word & hwif->swdma_mask)) {
                                /* Force if Capable regular DMA modes */
                                if (!config_chipset_for_dma(drive))
-                                       goto no_dma_set;
+                                       goto ata_pio;
                        }
                } else if (__ide_dma_good_drive(drive) &&
                           (id->eide_dma_time < 150)) {
                        /* Consult the list of known "good" drives */
                        if (!config_chipset_for_dma(drive))
-                               goto no_dma_set;
+                               goto ata_pio;
                } else {
                        goto ata_pio;
                }
        } else {
 ata_pio:
                hwif->tuneproc(drive, 255);
-no_dma_set:
                return -1;
        }
 
index 561197f..77f51ab 100644 (file)
@@ -1,10 +1,7 @@
-/* $Id: cmd64x.c,v 1.21 2000/01/30 23:23:16
- *
- * linux/drivers/ide/pci/cmd64x.c              Version 1.42    Feb 8, 2007
+/*
+ * linux/drivers/ide/pci/cmd64x.c              Version 1.47    Mar 19, 2007
  *
  * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
- *           Note, this driver is not used at all on other systems because
- *           there the "BIOS" has done all of the following already.
  *           Due to massive hardware bugs, UltraDMA is only supported
  *           on the 646U2 and not on the 646U.
  *
  * CMD64x specific registers definition.
  */
 #define CFR            0x50
-#define   CFR_INTR_CH0         0x02
+#define   CFR_INTR_CH0         0x04
 #define CNTRL          0x51
-#define          CNTRL_DIS_RA0         0x40
-#define   CNTRL_DIS_RA1                0x80
-#define          CNTRL_ENA_2ND         0x08
+#define   CNTRL_ENA_1ST        0x04
+#define   CNTRL_ENA_2ND        0x08
+#define   CNTRL_DIS_RA0        0x40
+#define   CNTRL_DIS_RA1        0x80
 
 #define        CMDTIM          0x52
 #define        ARTTIM0         0x53
@@ -90,86 +88,67 @@ static int n_cmd_devs;
 static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index)
 {
        char *p = buf;
-
-       u8 reg53 = 0, reg54 = 0, reg55 = 0, reg56 = 0;  /* primary */
-       u8 reg57 = 0, reg58 = 0, reg5b;                 /* secondary */
        u8 reg72 = 0, reg73 = 0;                        /* primary */
        u8 reg7a = 0, reg7b = 0;                        /* secondary */
-       u8 reg50 = 0, reg71 = 0;                        /* extra */
+       u8 reg50 = 1, reg51 = 1, reg57 = 0, reg71 = 0;  /* extra */
+       u8 rev = 0;
 
        p += sprintf(p, "\nController: %d\n", index);
-       p += sprintf(p, "CMD%x Chipset.\n", dev->device);
+       p += sprintf(p, "PCI-%x Chipset.\n", dev->device);
+
        (void) pci_read_config_byte(dev, CFR,       &reg50);
-       (void) pci_read_config_byte(dev, ARTTIM0,   &reg53);
-       (void) pci_read_config_byte(dev, DRWTIM0,   &reg54);
-       (void) pci_read_config_byte(dev, ARTTIM1,   &reg55);
-       (void) pci_read_config_byte(dev, DRWTIM1,   &reg56);
-       (void) pci_read_config_byte(dev, ARTTIM2,   &reg57);
-       (void) pci_read_config_byte(dev, DRWTIM2,   &reg58);
-       (void) pci_read_config_byte(dev, DRWTIM3,   &reg5b);
+       (void) pci_read_config_byte(dev, CNTRL,     &reg51);
+       (void) pci_read_config_byte(dev, ARTTIM23,  &reg57);
        (void) pci_read_config_byte(dev, MRDMODE,   &reg71);
        (void) pci_read_config_byte(dev, BMIDESR0,  &reg72);
        (void) pci_read_config_byte(dev, UDIDETCR0, &reg73);
        (void) pci_read_config_byte(dev, BMIDESR1,  &reg7a);
        (void) pci_read_config_byte(dev, UDIDETCR1, &reg7b);
 
-       p += sprintf(p, "--------------- Primary Channel "
-                       "---------------- Secondary Channel "
-                       "-------------\n");
-       p += sprintf(p, "                %sabled           "
-                       "              %sabled\n",
-               (reg72&0x80)?"dis":" en",
-               (reg7a&0x80)?"dis":" en");
-       p += sprintf(p, "--------------- drive0 "
-               "--------- drive1 -------- drive0 "
-               "---------- drive1 ------\n");
-       p += sprintf(p, "DMA enabled:    %s              %s"
-                       "             %s               %s\n",
-               (reg72&0x20)?"yes":"no ", (reg72&0x40)?"yes":"no ",
-               (reg7a&0x20)?"yes":"no ", (reg7a&0x40)?"yes":"no ");
-
-       p += sprintf(p, "DMA Mode:       %s(%s)          %s(%s)",
-               (reg72&0x20)?((reg73&0x01)?"UDMA":" DMA"):" PIO",
-               (reg72&0x20)?(
-                       ((reg73&0x30)==0x30)?(((reg73&0x35)==0x35)?"3":"0"):
-                       ((reg73&0x20)==0x20)?(((reg73&0x25)==0x25)?"3":"1"):
-                       ((reg73&0x10)==0x10)?(((reg73&0x15)==0x15)?"4":"2"):
-                       ((reg73&0x00)==0x00)?(((reg73&0x05)==0x05)?"5":"2"):
-                       "X"):"?",
-               (reg72&0x40)?((reg73&0x02)?"UDMA":" DMA"):" PIO",
-               (reg72&0x40)?(
-                       ((reg73&0xC0)==0xC0)?(((reg73&0xC5)==0xC5)?"3":"0"):
-                       ((reg73&0x80)==0x80)?(((reg73&0x85)==0x85)?"3":"1"):
-                       ((reg73&0x40)==0x40)?(((reg73&0x4A)==0x4A)?"4":"2"):
-                       ((reg73&0x00)==0x00)?(((reg73&0x0A)==0x0A)?"5":"2"):
-                       "X"):"?");
-       p += sprintf(p, "         %s(%s)           %s(%s)\n",
-               (reg7a&0x20)?((reg7b&0x01)?"UDMA":" DMA"):" PIO",
-               (reg7a&0x20)?(
-                       ((reg7b&0x30)==0x30)?(((reg7b&0x35)==0x35)?"3":"0"):
-                       ((reg7b&0x20)==0x20)?(((reg7b&0x25)==0x25)?"3":"1"):
-                       ((reg7b&0x10)==0x10)?(((reg7b&0x15)==0x15)?"4":"2"):
-                       ((reg7b&0x00)==0x00)?(((reg7b&0x05)==0x05)?"5":"2"):
-                       "X"):"?",
-               (reg7a&0x40)?((reg7b&0x02)?"UDMA":" DMA"):" PIO",
-               (reg7a&0x40)?(
-                       ((reg7b&0xC0)==0xC0)?(((reg7b&0xC5)==0xC5)?"3":"0"):
-                       ((reg7b&0x80)==0x80)?(((reg7b&0x85)==0x85)?"3":"1"):
-                       ((reg7b&0x40)==0x40)?(((reg7b&0x4A)==0x4A)?"4":"2"):
-                       ((reg7b&0x00)==0x00)?(((reg7b&0x0A)==0x0A)?"5":"2"):
-                       "X"):"?" );
-       p += sprintf(p, "PIO Mode:       %s                %s"
-                       "               %s                 %s\n",
-                       "?", "?", "?", "?");
-       p += sprintf(p, "                %s                     %s\n",
-               (reg50 & CFR_INTR_CH0) ? "interrupting" : "polling     ",
-               (reg57 & ARTTIM23_INTR_CH1) ? "interrupting" : "polling");
-       p += sprintf(p, "                %s                          %s\n",
-               (reg71 & MRDMODE_INTR_CH0) ? "pending" : "clear  ",
-               (reg71 & MRDMODE_INTR_CH1) ? "pending" : "clear");
-       p += sprintf(p, "                %s                          %s\n",
-               (reg71 & MRDMODE_BLK_CH0) ? "blocked" : "enabled",
-               (reg71 & MRDMODE_BLK_CH1) ? "blocked" : "enabled");
+       /* PCI0643/6 originally didn't have the primary channel enable bit */
+       (void) pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+       if ((dev->device == PCI_DEVICE_ID_CMD_643) ||
+           (dev->device == PCI_DEVICE_ID_CMD_646 && rev < 3))
+               reg51 |= CNTRL_ENA_1ST;
+
+       p += sprintf(p, "---------------- Primary Channel "
+                       "---------------- Secondary Channel ------------\n");
+       p += sprintf(p, "                 %s                         %s\n",
+                (reg51 & CNTRL_ENA_1ST) ? "enabled " : "disabled",
+                (reg51 & CNTRL_ENA_2ND) ? "enabled " : "disabled");
+       p += sprintf(p, "---------------- drive0 --------- drive1 "
+                       "-------- drive0 --------- drive1 ------\n");
+       p += sprintf(p, "DMA enabled:     %s              %s"
+                       "             %s              %s\n",
+               (reg72 & 0x20) ? "yes" : "no ", (reg72 & 0x40) ? "yes" : "no ",
+               (reg7a & 0x20) ? "yes" : "no ", (reg7a & 0x40) ? "yes" : "no ");
+       p += sprintf(p, "UltraDMA mode:   %s (%c)          %s (%c)",
+               ( reg73 & 0x01) ? " on" : "off",
+               ((reg73 & 0x30) == 0x30) ? ((reg73 & 0x04) ? '3' : '0') :
+               ((reg73 & 0x30) == 0x20) ? ((reg73 & 0x04) ? '3' : '1') :
+               ((reg73 & 0x30) == 0x10) ? ((reg73 & 0x04) ? '4' : '2') :
+               ((reg73 & 0x30) == 0x00) ? ((reg73 & 0x04) ? '5' : '2') : '?',
+               ( reg73 & 0x02) ? " on" : "off",
+               ((reg73 & 0xC0) == 0xC0) ? ((reg73 & 0x08) ? '3' : '0') :
+               ((reg73 & 0xC0) == 0x80) ? ((reg73 & 0x08) ? '3' : '1') :
+               ((reg73 & 0xC0) == 0x40) ? ((reg73 & 0x08) ? '4' : '2') :
+               ((reg73 & 0xC0) == 0x00) ? ((reg73 & 0x08) ? '5' : '2') : '?');
+       p += sprintf(p, "         %s (%c)          %s (%c)\n",
+               ( reg7b & 0x01) ? " on" : "off",
+               ((reg7b & 0x30) == 0x30) ? ((reg7b & 0x04) ? '3' : '0') :
+               ((reg7b & 0x30) == 0x20) ? ((reg7b & 0x04) ? '3' : '1') :
+               ((reg7b & 0x30) == 0x10) ? ((reg7b & 0x04) ? '4' : '2') :
+               ((reg7b & 0x30) == 0x00) ? ((reg7b & 0x04) ? '5' : '2') : '?',
+               ( reg7b & 0x02) ? " on" : "off",
+               ((reg7b & 0xC0) == 0xC0) ? ((reg7b & 0x08) ? '3' : '0') :
+               ((reg7b & 0xC0) == 0x80) ? ((reg7b & 0x08) ? '3' : '1') :
+               ((reg7b & 0xC0) == 0x40) ? ((reg7b & 0x08) ? '4' : '2') :
+               ((reg7b & 0xC0) == 0x00) ? ((reg7b & 0x08) ? '5' : '2') : '?');
+       p += sprintf(p, "Interrupt:       %s, %s                 %s, %s\n",
+               (reg71 & MRDMODE_BLK_CH0  ) ? "blocked" : "enabled",
+               (reg50 & CFR_INTR_CH0     ) ? "pending" : "clear  ",
+               (reg71 & MRDMODE_BLK_CH1  ) ? "blocked" : "enabled",
+               (reg57 & ARTTIM23_INTR_CH1) ? "pending" : "clear  ");
 
        return (char *)p;
 }
@@ -179,7 +158,6 @@ static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count)
        char *p = buffer;
        int i;
 
-       p += sprintf(p, "\n");
        for (i = 0; i < n_cmd_devs; i++) {
                struct pci_dev *dev     = cmd_devs[i];
                p = print_cmd64x_get_info(p, dev, i);
@@ -195,116 +173,103 @@ static u8 quantize_timing(int timing, int quant)
 }
 
 /*
- * This routine writes the prepared setup/active/recovery counts
- * for a drive into the cmd646 chipset registers to active them.
+ * This routine calculates active/recovery counts and then writes them into
+ * the chipset registers.
  */
-static void program_drive_counts (ide_drive_t *drive, int setup_count, int active_count, int recovery_count)
+static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time)
 {
-       unsigned long flags;
-       struct pci_dev *dev = HWIF(drive)->pci_dev;
-       ide_drive_t *drives = HWIF(drive)->drives;
-       u8 temp_b;
-       static const u8 setup_counts[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
-       static const u8 recovery_counts[] =
+       struct pci_dev *dev     = HWIF(drive)->pci_dev;
+       int clock_time          = 1000 / system_bus_clock();
+       u8  cycle_count, active_count, recovery_count, drwtim;
+       static const u8 recovery_values[] =
                {15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0};
-       static const u8 arttim_regs[2][2] = {
-                       { ARTTIM0, ARTTIM1 },
-                       { ARTTIM23, ARTTIM23 }
-               };
-       static const u8 drwtim_regs[2][2] = {
-                       { DRWTIM0, DRWTIM1 },
-                       { DRWTIM2, DRWTIM3 }
-               };
-       int channel = (int) HWIF(drive)->channel;
-       int slave = (drives != drive);  /* Is this really the best way to determine this?? */
-
-       cmdprintk("program_drive_count parameters = s(%d),a(%d),r(%d),p(%d)\n",
-               setup_count, active_count, recovery_count, drive->present);
+       static const u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM2, DRWTIM3};
+
+       cmdprintk("program_cycle_times parameters: total=%d, active=%d\n",
+                 cycle_time, active_time);
+
+       cycle_count     = quantize_timing( cycle_time, clock_time);
+       active_count    = quantize_timing(active_time, clock_time);
+       recovery_count  = cycle_count - active_count;
+
        /*
-        * Set up address setup count registers.
-        * Primary interface has individual count/timing registers for
-        * each drive.  Secondary interface has one common set of registers,
-        * for address setup so we merge these timings, using the slowest
-        * value.
+        * In case we've got too long recovery phase, try to lengthen
+        * the active phase
         */
-       if (channel) {
-               drive->drive_data = setup_count;
-               setup_count = max(drives[0].drive_data,
-                                       drives[1].drive_data);
-               cmdprintk("Secondary interface, setup_count = %d\n",
-                                       setup_count);
+       if (recovery_count > 16) {
+               active_count += recovery_count - 16;
+               recovery_count = 16;
        }
+       if (active_count > 16)          /* shouldn't actually happen... */
+               active_count = 16;
+
+       cmdprintk("Final counts: total=%d, active=%d, recovery=%d\n",
+                 cycle_count, active_count, recovery_count);
 
        /*
         * Convert values to internal chipset representation
         */
-       setup_count = (setup_count > 5) ? 0xc0 : (int) setup_counts[setup_count];
-       active_count &= 0xf; /* Remember, max value is 16 */
-       recovery_count = (int) recovery_counts[recovery_count];
+       recovery_count = recovery_values[recovery_count];
+       active_count  &= 0x0f;
 
-       cmdprintk("Final values = %d,%d,%d\n",
-               setup_count, active_count, recovery_count);
-
-       /*
-        * Now that everything is ready, program the new timings
-        */
-       local_irq_save(flags);
-       /*
-        * Program the address_setup clocks into ARTTIM reg,
-        * and then the active/recovery counts into the DRWTIM reg
-        */
-       (void) pci_read_config_byte(dev, arttim_regs[channel][slave], &temp_b);
-       (void) pci_write_config_byte(dev, arttim_regs[channel][slave],
-               ((u8) setup_count) | (temp_b & 0x3f));
-       (void) pci_write_config_byte(dev, drwtim_regs[channel][slave],
-               (u8) ((active_count << 4) | recovery_count));
-       cmdprintk ("Write %x to %x\n",
-               ((u8) setup_count) | (temp_b & 0x3f),
-               arttim_regs[channel][slave]);
-       cmdprintk ("Write %x to %x\n",
-               (u8) ((active_count << 4) | recovery_count),
-               drwtim_regs[channel][slave]);
-       local_irq_restore(flags);
+       /* Program the active/recovery counts into the DRWTIM register */
+       drwtim = (active_count << 4) | recovery_count;
+       (void) pci_write_config_byte(dev, drwtim_regs[drive->dn], drwtim);
+       cmdprintk("Write 0x%02x to reg 0x%x\n", drwtim, drwtim_regs[drive->dn]);
 }
 
 /*
- * This routine selects drive's best PIO mode, calculates setup/active/recovery
- * counts, and then writes them into the chipset registers.
+ * This routine selects drive's best PIO mode and writes into the chipset
+ * registers setup/active/recovery timings.
  */
 static u8 cmd64x_tune_pio (ide_drive_t *drive, u8 mode_wanted)
 {
-       int setup_time, active_time, cycle_time;
-       u8  cycle_count, setup_count, active_count, recovery_count;
-       u8  pio_mode;
-       int clock_time = 1000 / system_bus_clock();
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = hwif->pci_dev;
        ide_pio_data_t pio;
-
+       u8 pio_mode, setup_count, arttim = 0;
+       static const u8 setup_values[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
+       static const u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};
        pio_mode = ide_get_best_pio_mode(drive, mode_wanted, 5, &pio);
-       cycle_time = pio.cycle_time;
 
-       setup_time  = ide_pio_timings[pio_mode].setup_time;
-       active_time = ide_pio_timings[pio_mode].active_time;
+       cmdprintk("%s: PIO mode wanted %d, selected %d (%d ns)%s\n",
+                 drive->name, mode_wanted, pio_mode, pio.cycle_time,
+                 pio.overridden ? " (overriding vendor mode)" : "");
 
-       setup_count  = quantize_timing( setup_time, clock_time);
-       cycle_count  = quantize_timing( cycle_time, clock_time);
-       active_count = quantize_timing(active_time, clock_time);
+       program_cycle_times(drive, pio.cycle_time,
+                           ide_pio_timings[pio_mode].active_time);
 
-       recovery_count = cycle_count - active_count;
-       /* program_drive_counts() takes care of zero recovery cycles */
-       if (recovery_count > 16) {
-               active_count += recovery_count - 16;
-               recovery_count = 16;
+       setup_count = quantize_timing(ide_pio_timings[pio_mode].setup_time,
+                                     1000 / system_bus_clock());
+
+       /*
+        * The primary channel has individual address setup timing registers
+        * for each drive and the hardware selects the slowest timing itself.
+        * The secondary channel has one common register and we have to select
+        * the slowest address setup timing ourselves.
+        */
+       if (hwif->channel) {
+               ide_drive_t *drives = hwif->drives;
+
+               drive->drive_data = setup_count;
+               setup_count = max(drives[0].drive_data, drives[1].drive_data);
        }
-       if (active_count > 16)
-               active_count = 16; /* maximum allowed by cmd64x */
 
-       program_drive_counts (drive, setup_count, active_count, recovery_count);
+       if (setup_count > 5)            /* shouldn't actually happen... */
+               setup_count = 5;
+       cmdprintk("Final address setup count: %d\n", setup_count);
 
-       cmdprintk("%s: PIO mode wanted %d, selected %d (%dns)%s, "
-               "clocks=%d/%d/%d\n",
-               drive->name, mode_wanted, pio_mode, cycle_time,
-               pio.overridden ? " (overriding vendor mode)" : "",
-               setup_count, active_count, recovery_count);
+       /*
+        * Program the address setup clocks into the ARTTIM registers.
+        * Avoid clearing the secondary channel's interrupt bit.
+        */
+       (void) pci_read_config_byte (dev, arttim_regs[drive->dn], &arttim);
+       if (hwif->channel)
+               arttim &= ~ARTTIM23_INTR_CH1;
+       arttim &= ~0xc0;
+       arttim |= setup_values[setup_count];
+       (void) pci_write_config_byte(dev, arttim_regs[drive->dn], arttim);
+       cmdprintk("Write 0x%02x to reg 0x%x\n", arttim, arttim_regs[drive->dn]);
 
        return pio_mode;
 }
@@ -376,61 +341,64 @@ static u8 cmd64x_ratemask (ide_drive_t *drive)
        return mode;
 }
 
-static int cmd64x_tune_chipset (ide_drive_t *drive, u8 xferspeed)
+static int cmd64x_tune_chipset (ide_drive_t *drive, u8 speed)
 {
        ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev *dev     = hwif->pci_dev;
+       u8 unit                 = drive->dn & 0x01;
+       u8 regU = 0, pciU       = hwif->channel ? UDIDETCR1 : UDIDETCR0;
 
-       u8 unit                 = (drive->select.b.unit & 0x01);
-       u8 regU = 0, pciU       = (hwif->channel) ? UDIDETCR1 : UDIDETCR0;
-       u8 regD = 0, pciD       = (hwif->channel) ? BMIDESR1 : BMIDESR0;
-
-       u8 speed        = ide_rate_filter(cmd64x_ratemask(drive), xferspeed);
+       speed = ide_rate_filter(cmd64x_ratemask(drive), speed);
 
        if (speed >= XFER_SW_DMA_0) {
-               (void) pci_read_config_byte(dev, pciD, &regD);
                (void) pci_read_config_byte(dev, pciU, &regU);
-               regD &= ~(unit ? 0x40 : 0x20);
                regU &= ~(unit ? 0xCA : 0x35);
-               (void) pci_write_config_byte(dev, pciD, regD);
-               (void) pci_write_config_byte(dev, pciU, regU);
-               (void) pci_read_config_byte(dev, pciD, &regD);
-               (void) pci_read_config_byte(dev, pciU, &regU);
        }
 
        switch(speed) {
-               case XFER_UDMA_5:       regU |= (unit ? 0x0A : 0x05); break;
-               case XFER_UDMA_4:       regU |= (unit ? 0x4A : 0x15); break;
-               case XFER_UDMA_3:       regU |= (unit ? 0x8A : 0x25); break;
-               case XFER_UDMA_2:       regU |= (unit ? 0x42 : 0x11); break;
-               case XFER_UDMA_1:       regU |= (unit ? 0x82 : 0x21); break;
-               case XFER_UDMA_0:       regU |= (unit ? 0xC2 : 0x31); break;
-               case XFER_MW_DMA_2:     regD |= (unit ? 0x40 : 0x10); break;
-               case XFER_MW_DMA_1:     regD |= (unit ? 0x80 : 0x20); break;
-               case XFER_MW_DMA_0:     regD |= (unit ? 0xC0 : 0x30); break;
-               case XFER_SW_DMA_2:     regD |= (unit ? 0x40 : 0x10); break;
-               case XFER_SW_DMA_1:     regD |= (unit ? 0x80 : 0x20); break;
-               case XFER_SW_DMA_0:     regD |= (unit ? 0xC0 : 0x30); break;
-               case XFER_PIO_5:
-               case XFER_PIO_4:
-               case XFER_PIO_3:
-               case XFER_PIO_2:
-               case XFER_PIO_1:
-               case XFER_PIO_0:
-                       (void) cmd64x_tune_pio(drive, speed - XFER_PIO_0);
-                       break;
-
-               default:
-                       return 1;
+       case XFER_UDMA_5:
+               regU |= unit ? 0x0A : 0x05;
+               break;
+       case XFER_UDMA_4:
+               regU |= unit ? 0x4A : 0x15;
+               break;
+       case XFER_UDMA_3:
+               regU |= unit ? 0x8A : 0x25;
+               break;
+       case XFER_UDMA_2:
+               regU |= unit ? 0x42 : 0x11;
+               break;
+       case XFER_UDMA_1:
+               regU |= unit ? 0x82 : 0x21;
+               break;
+       case XFER_UDMA_0:
+               regU |= unit ? 0xC2 : 0x31;
+               break;
+       case XFER_MW_DMA_2:
+               program_cycle_times(drive, 120, 70);
+               break;
+       case XFER_MW_DMA_1:
+               program_cycle_times(drive, 150, 80);
+               break;
+       case XFER_MW_DMA_0:
+               program_cycle_times(drive, 480, 215);
+               break;
+       case XFER_PIO_5:
+       case XFER_PIO_4:
+       case XFER_PIO_3:
+       case XFER_PIO_2:
+       case XFER_PIO_1:
+       case XFER_PIO_0:
+               (void) cmd64x_tune_pio(drive, speed - XFER_PIO_0);
+               break;
+       default:
+               return 1;
        }
 
-       if (speed >= XFER_SW_DMA_0) {
+       if (speed >= XFER_SW_DMA_0)
                (void) pci_write_config_byte(dev, pciU, regU);
-               regD |= (unit ? 0x40 : 0x20);
-               (void) pci_write_config_byte(dev, pciD, regD);
-       }
 
-       return (ide_config_drive_speed(drive, speed));
+       return ide_config_drive_speed(drive, speed);
 }
 
 static int config_chipset_for_dma (ide_drive_t *drive)
@@ -457,67 +425,80 @@ static int cmd64x_config_drive_for_dma (ide_drive_t *drive)
        return -1;
 }
 
-static int cmd64x_alt_dma_status (struct pci_dev *dev)
+static int cmd648_ide_dma_end (ide_drive_t *drive)
 {
-       switch(dev->device) {
-               case PCI_DEVICE_ID_CMD_648:
-               case PCI_DEVICE_ID_CMD_649:
-                       return 1;
-               default:
-                       break;
-       }
-       return 0;
+       ide_hwif_t *hwif        = HWIF(drive);
+       int err                 = __ide_dma_end(drive);
+       u8  irq_mask            = hwif->channel ? MRDMODE_INTR_CH1 :
+                                                 MRDMODE_INTR_CH0;
+       u8  mrdmode             = inb(hwif->dma_master + 0x01);
+
+       /* clear the interrupt bit */
+       outb(mrdmode | irq_mask, hwif->dma_master + 0x01);
+
+       return err;
 }
 
 static int cmd64x_ide_dma_end (ide_drive_t *drive)
 {
-       u8 dma_stat = 0, dma_cmd = 0;
        ide_hwif_t *hwif        = HWIF(drive);
        struct pci_dev *dev     = hwif->pci_dev;
+       int irq_reg             = hwif->channel ? ARTTIM23 : CFR;
+       u8  irq_mask            = hwif->channel ? ARTTIM23_INTR_CH1 :
+                                                 CFR_INTR_CH0;
+       u8  irq_stat            = 0;
+       int err                 = __ide_dma_end(drive);
 
-       drive->waiting_for_dma = 0;
-       /* read DMA command state */
-       dma_cmd = inb(hwif->dma_command);
-       /* stop DMA */
-       outb(dma_cmd & ~1, hwif->dma_command);
-       /* get DMA status */
-       dma_stat = inb(hwif->dma_status);
-       /* clear the INTR & ERROR bits */
-       outb(dma_stat | 6, hwif->dma_status);
-       if (cmd64x_alt_dma_status(dev)) {
-               u8 dma_intr     = 0;
-               u8 dma_mask     = (hwif->channel) ? ARTTIM23_INTR_CH1 :
-                                                   CFR_INTR_CH0;
-               u8 dma_reg      = (hwif->channel) ? ARTTIM2 : CFR;
-               (void) pci_read_config_byte(dev, dma_reg, &dma_intr);
-               /* clear the INTR bit */
-               (void) pci_write_config_byte(dev, dma_reg, dma_intr|dma_mask);
-       }
-       /* purge DMA mappings */
-       ide_destroy_dmatable(drive);
-       /* verify good DMA status */
-       return (dma_stat & 7) != 4;
+       (void) pci_read_config_byte(dev, irq_reg, &irq_stat);
+       /* clear the interrupt bit */
+       (void) pci_write_config_byte(dev, irq_reg, irq_stat | irq_mask);
+
+       return err;
+}
+
+static int cmd648_ide_dma_test_irq (ide_drive_t *drive)
+{
+       ide_hwif_t *hwif        = HWIF(drive);
+       u8 irq_mask             = hwif->channel ? MRDMODE_INTR_CH1 :
+                                                 MRDMODE_INTR_CH0;
+       u8 dma_stat             = inb(hwif->dma_status);
+       u8 mrdmode              = inb(hwif->dma_master + 0x01);
+
+#ifdef DEBUG
+       printk("%s: dma_stat: 0x%02x mrdmode: 0x%02x irq_mask: 0x%02x\n",
+              drive->name, dma_stat, mrdmode, irq_mask);
+#endif
+       if (!(mrdmode & irq_mask))
+               return 0;
+
+       /* return 1 if INTR asserted */
+       if (dma_stat & 4)
+               return 1;
+
+       return 0;
 }
 
 static int cmd64x_ide_dma_test_irq (ide_drive_t *drive)
 {
-       ide_hwif_t *hwif                = HWIF(drive);
-       struct pci_dev *dev             = hwif->pci_dev;
-        u8 dma_alt_stat = 0, mask      = (hwif->channel) ? MRDMODE_INTR_CH1 :
-                                                           MRDMODE_INTR_CH0;
-       u8 dma_stat = inb(hwif->dma_status);
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = hwif->pci_dev;
+       int irq_reg             = hwif->channel ? ARTTIM23 : CFR;
+       u8  irq_mask            = hwif->channel ? ARTTIM23_INTR_CH1 :
+                                                 CFR_INTR_CH0;
+       u8  dma_stat            = inb(hwif->dma_status);
+       u8  irq_stat            = 0;
+
+       (void) pci_read_config_byte(dev, irq_reg, &irq_stat);
 
-       (void) pci_read_config_byte(dev, MRDMODE, &dma_alt_stat);
 #ifdef DEBUG
-       printk("%s: dma_stat: 0x%02x dma_alt_stat: "
-               "0x%02x mask: 0x%02x\n", drive->name,
-               dma_stat, dma_alt_stat, mask);
+       printk("%s: dma_stat: 0x%02x irq_stat: 0x%02x irq_mask: 0x%02x\n",
+              drive->name, dma_stat, irq_stat, irq_mask);
 #endif
-       if (!(dma_alt_stat & mask))
+       if (!(irq_stat & irq_mask))
                return 0;
 
        /* return 1 if INTR asserted */
-       if ((dma_stat & 4) == 4)
+       if (dma_stat & 4)
                return 1;
 
        return 0;
@@ -665,7 +646,6 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
 
        hwif->ultra_mask = 0x3f;
        hwif->mwdma_mask = 0x07;
-       hwif->swdma_mask = 0x07;
 
        if (dev->device == PCI_DEVICE_ID_CMD_643)
                hwif->ultra_mask = 0x80;
@@ -678,17 +658,25 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
        if (!(hwif->udma_four))
                hwif->udma_four = ata66_cmd64x(hwif);
 
-       if (dev->device == PCI_DEVICE_ID_CMD_646) {
+       switch(dev->device) {
+       case PCI_DEVICE_ID_CMD_648:
+       case PCI_DEVICE_ID_CMD_649:
+       alt_irq_bits:
+               hwif->ide_dma_end       = &cmd648_ide_dma_end;
+               hwif->ide_dma_test_irq  = &cmd648_ide_dma_test_irq;
+               break;
+       case PCI_DEVICE_ID_CMD_646:
                hwif->chipset = ide_cmd646;
                if (class_rev == 0x01) {
                        hwif->ide_dma_end = &cmd646_1_ide_dma_end;
-               } else {
-                       hwif->ide_dma_end = &cmd64x_ide_dma_end;
-                       hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq;
-               }
-       } else {
-               hwif->ide_dma_end = &cmd64x_ide_dma_end;
-               hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq;
+                       break;
+               } else if (class_rev >= 0x03)
+                       goto alt_irq_bits;
+               /* fall thru */
+       default:
+               hwif->ide_dma_end       = &cmd64x_ide_dma_end;
+               hwif->ide_dma_test_irq  = &cmd64x_ide_dma_test_irq;
+               break;
        }
 
 
@@ -698,42 +686,75 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
        hwif->drives[1].autodma = hwif->autodma;
 }
 
+static int __devinit init_setup_cmd64x(struct pci_dev *dev, ide_pci_device_t *d)
+{
+       return ide_setup_pci_device(dev, d);
+}
+
+static int __devinit init_setup_cmd646(struct pci_dev *dev, ide_pci_device_t *d)
+{
+       u8 rev = 0;
+
+       /*
+        * The original PCI0646 didn't have the primary channel enable bit,
+        * it appeared starting with PCI0646U (i.e. revision ID 3).
+        */
+       pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+       if (rev < 3)
+               d->enablebits[0].reg = 0;
+
+       return ide_setup_pci_device(dev, d);
+}
+
 static ide_pci_device_t cmd64x_chipsets[] __devinitdata = {
        {       /* 0 */
                .name           = "CMD643",
+               .init_setup     = init_setup_cmd64x,
                .init_chipset   = init_chipset_cmd64x,
                .init_hwif      = init_hwif_cmd64x,
                .channels       = 2,
                .autodma        = AUTODMA,
+               .enablebits     = {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
                .bootable       = ON_BOARD,
        },{     /* 1 */
                .name           = "CMD646",
+               .init_setup     = init_setup_cmd646,
                .init_chipset   = init_chipset_cmd64x,
                .init_hwif      = init_hwif_cmd64x,
                .channels       = 2,
                .autodma        = AUTODMA,
-               .enablebits     = {{0x00,0x00,0x00}, {0x51,0x80,0x80}},
+               .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
                .bootable       = ON_BOARD,
        },{     /* 2 */
                .name           = "CMD648",
+               .init_setup     = init_setup_cmd64x,
                .init_chipset   = init_chipset_cmd64x,
                .init_hwif      = init_hwif_cmd64x,
                .channels       = 2,
                .autodma        = AUTODMA,
+               .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
                .bootable       = ON_BOARD,
        },{     /* 3 */
                .name           = "CMD649",
+               .init_setup     = init_setup_cmd64x,
                .init_chipset   = init_chipset_cmd64x,
                .init_hwif      = init_hwif_cmd64x,
                .channels       = 2,
                .autodma        = AUTODMA,
+               .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
                .bootable       = ON_BOARD,
        }
 };
 
+/*
+ * We may have to modify enablebits for PCI0646, so we'd better pass
+ * a local copy of the ide_pci_device_t structure down the call chain...
+ */
 static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       return ide_setup_pci_device(dev, &cmd64x_chipsets[id->driver_data]);
+       ide_pci_device_t d = cmd64x_chipsets[id->driver_data];
+
+       return d.init_setup(dev, &d);
 }
 
 static struct pci_device_id cmd64x_pci_tbl[] = {
index ab6fa27..cf9d344 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/pci/hpt366.c              Version 1.02    Apr 18, 2007
+ * linux/drivers/ide/pci/hpt366.c              Version 1.03    May 4, 2007
  *
  * Copyright (C) 1999-2003             Andre Hedrick <andre@linux-ide.org>
  * Portions Copyright (C) 2001         Sun Microsystems, Inc.
@@ -1527,7 +1527,12 @@ static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
        if (rev > 2)
                goto init_single;
 
+       /*
+        * HPT36x chips are single channel and
+        * do not seem to have the channel enable bit...
+        */
        d->channels = 1;
+       d->enablebits[0].reg = 0;
 
        if ((dev2 = pci_get_slot(dev->bus, dev->devfn + 1)) != NULL) {
                u8  pin1 = 0, pin2 = 0;
index a132767..4e12548 100644 (file)
@@ -1,8 +1,9 @@
 
 /*
- * linux/drivers/ide/pci/it821x.c              Version 0.09    December 2004
+ * linux/drivers/ide/pci/it821x.c              Version 0.10    Mar 10 2007
  *
  * Copyright (C) 2004          Red Hat <alan@redhat.com>
+ * Copyright (C) 2007          Bartlomiej Zolnierkiewicz
  *
  *  May be copied or modified under the terms of the GNU General Public License
  *  Based in part on the ITE vendor provided SCSI driver.
@@ -104,6 +105,7 @@ static int it8212_noraid;
 /**
  *     it821x_program  -       program the PIO/MWDMA registers
  *     @drive: drive to tune
+ *     @timing: timing info
  *
  *     Program the PIO/MWDMA timing for this channel according to the
  *     current clock.
@@ -127,6 +129,7 @@ static void it821x_program(ide_drive_t *drive, u16 timing)
 /**
  *     it821x_program_udma     -       program the UDMA registers
  *     @drive: drive to tune
+ *     @timing: timing info
  *
  *     Program the UDMA timing for this drive according to the
  *     current clock.
@@ -153,10 +156,9 @@ static void it821x_program_udma(ide_drive_t *drive, u16 timing)
        }
 }
 
-
 /**
  *     it821x_clock_strategy
- *     @hwif: hardware interface
+ *     @drive: drive to set up
  *
  *     Select between the 50 and 66Mhz base clocks to get the best
  *     results for this interface.
@@ -182,8 +184,11 @@ static void it821x_clock_strategy(ide_drive_t *drive)
                altclock = itdev->want[0][1];
        }
 
-       /* Master doesn't care does the slave ? */
-       if(clock == ATA_ANY)
+       /*
+        * if both clocks can be used for the mode with the higher priority
+        * use the clock needed by the mode with the lower priority
+        */
+       if (clock == ATA_ANY)
                clock = altclock;
 
        /* Nobody cares - keep the same clock */
@@ -240,37 +245,56 @@ static u8 it821x_ratemask (ide_drive_t *drive)
 }
 
 /**
- *     it821x_tuneproc -       tune a drive
+ *     it821x_tunepio  -       tune a drive
  *     @drive: drive to tune
- *     @mode_wanted: the target operating mode
- *
- *     Load the timing settings for this device mode into the
- *     controller. By the time we are called the mode has been
- *     modified as neccessary to handle the absence of seperate
- *     master/slave timers for MWDMA/PIO.
+ *     @pio: the desired PIO mode
  *
- *     This code is only used in pass through mode.
+ *     Try to tune the drive/host to the desired PIO mode taking into
+ *     the consideration the maximum PIO mode supported by the other
+ *     device on the cable.
  */
 
-static void it821x_tuneproc (ide_drive_t *drive, byte mode_wanted)
+static int it821x_tunepio(ide_drive_t *drive, u8 set_pio)
 {
        ide_hwif_t *hwif        = drive->hwif;
        struct it821x_dev *itdev = ide_get_hwifdata(hwif);
        int unit = drive->select.b.unit;
+       ide_drive_t *pair = &hwif->drives[1 - unit];
 
        /* Spec says 89 ref driver uses 88 */
        static u16 pio[]        = { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 };
        static u8 pio_want[]    = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY };
 
-       if(itdev->smart)
-               return;
+       /*
+        * Compute the best PIO mode we can for a given device. We must
+        * pick a speed that does not cause problems with the other device
+        * on the cable.
+        */
+       if (pair) {
+               u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4, NULL);
+               /* trim PIO to the slowest of the master/slave */
+               if (pair_pio < set_pio)
+                       set_pio = pair_pio;
+       }
+
+       if (itdev->smart)
+               goto set_drive_speed;
 
        /* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */
-       itdev->want[unit][1] = pio_want[mode_wanted];
+       itdev->want[unit][1] = pio_want[set_pio];
        itdev->want[unit][0] = 1;       /* PIO is lowest priority */
-       itdev->pio[unit] = pio[mode_wanted];
+       itdev->pio[unit] = pio[set_pio];
        it821x_clock_strategy(drive);
        it821x_program(drive, itdev->pio[unit]);
+
+set_drive_speed:
+       return ide_config_drive_speed(drive, XFER_PIO_0 + set_pio);
+}
+
+static void it821x_tuneproc(ide_drive_t *drive, u8 pio)
+{
+       pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+       (void)it821x_tunepio(drive, pio);
 }
 
 /**
@@ -354,40 +378,6 @@ static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted)
 }
 
 /**
- *     config_it821x_chipset_for_pio   -       set drive timings
- *     @drive: drive to tune
- *     @speed we want
- *
- *     Compute the best pio mode we can for a given device. We must
- *     pick a speed that does not cause problems with the other device
- *     on the cable.
- */
-
-static void config_it821x_chipset_for_pio (ide_drive_t *drive, byte set_speed)
-{
-       u8 unit = drive->select.b.unit;
-       ide_hwif_t *hwif = drive->hwif;
-       ide_drive_t *pair = &hwif->drives[1-unit];
-       u8 speed = 0, set_pio   = ide_get_best_pio_mode(drive, 255, 5, NULL);
-       u8 pair_pio;
-
-       /* We have to deal with this mess in pairs */
-       if(pair != NULL) {
-               pair_pio = ide_get_best_pio_mode(pair, 255, 5, NULL);
-               /* Trim PIO to the slowest of the master/slave */
-               if(pair_pio < set_pio)
-                       set_pio = pair_pio;
-       }
-       it821x_tuneproc(drive, set_pio);
-       speed = XFER_PIO_0 + set_pio;
-       /* XXX - We trim to the lowest of the pair so the other drive
-          will always be fine at this point until we do hotplug passthru */
-
-       if (set_speed)
-               (void) ide_config_drive_speed(drive, speed);
-}
-
-/**
  *     it821x_dma_read -       DMA hook
  *     @drive: drive for DMA
  *
@@ -450,15 +440,17 @@ static int it821x_tune_chipset (ide_drive_t *drive, byte xferspeed)
        struct it821x_dev *itdev = ide_get_hwifdata(hwif);
        u8 speed                = ide_rate_filter(it821x_ratemask(drive), xferspeed);
 
-       if(!itdev->smart) {
-               switch(speed) {
-                       case XFER_PIO_4:
-                       case XFER_PIO_3:
-                       case XFER_PIO_2:
-                       case XFER_PIO_1:
-                       case XFER_PIO_0:
-                               it821x_tuneproc(drive, (speed - XFER_PIO_0));
-                               break;
+       switch (speed) {
+       case XFER_PIO_4:
+       case XFER_PIO_3:
+       case XFER_PIO_2:
+       case XFER_PIO_1:
+       case XFER_PIO_0:
+               return it821x_tunepio(drive, speed - XFER_PIO_0);
+       }
+
+       if (itdev->smart == 0) {
+               switch (speed) {
                        /* MWDMA tuning is really hard because our MWDMA and PIO
                           timings are kept in the same place. We can switch in the
                           host dma on/off callbacks */
@@ -498,14 +490,12 @@ static int config_chipset_for_dma (ide_drive_t *drive)
 {
        u8 speed        = ide_dma_speed(drive, it821x_ratemask(drive));
 
-       if (speed) {
-               config_it821x_chipset_for_pio(drive, 0);
-               it821x_tune_chipset(drive, speed);
+       if (speed == 0)
+               return 0;
 
-               return ide_dma_enable(drive);
-       }
+       it821x_tune_chipset(drive, speed);
 
-       return 0;
+       return ide_dma_enable(drive);
 }
 
 /**
@@ -523,7 +513,7 @@ static int it821x_config_drive_for_dma (ide_drive_t *drive)
        if (ide_use_dma(drive) && config_chipset_for_dma(drive))
                return 0;
 
-       config_it821x_chipset_for_pio(drive, 1);
+       it821x_tuneproc(drive, 255);
 
        return -1;
 }
index ace9892..2da5cbb 100644 (file)
@@ -255,9 +255,6 @@ static int config_chipset_for_dma(ide_drive_t *drive)
                printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name);
        }
 
-       if (drive->media != ide_disk && drive->media != ide_cdrom)
-               return 0;
-
        if (id->capability & 4) {
                /*
                 * Set IORDY_EN & PREFETCH_EN (this seems to have
index 71eccdf..c0188de 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/pci/siimage.c             Version 1.11    Jan 27, 2007
+ * linux/drivers/ide/pci/siimage.c             Version 1.12    Mar 10 2007
  *
  * Copyright (C) 2001-2002     Andre Hedrick <andre@linux-ide.org>
  * Copyright (C) 2003          Red Hat <alan@redhat.com>
@@ -287,11 +287,6 @@ static void config_siimage_chipset_for_pio (ide_drive_t *drive, byte set_speed)
                (void) ide_config_drive_speed(drive, speed);
 }
 
-static void config_chipset_for_pio (ide_drive_t *drive, byte set_speed)
-{
-       config_siimage_chipset_for_pio(drive, set_speed);
-}
-
 /**
  *     siimage_tune_chipset    -       set controller timings
  *     @drive: Drive to set up
@@ -396,8 +391,6 @@ static int config_chipset_for_dma (ide_drive_t *drive)
 {
        u8 speed        = ide_dma_speed(drive, siimage_ratemask(drive));
 
-       config_chipset_for_pio(drive, !speed);
-
        if (!speed)
                return 0;
 
@@ -423,7 +416,7 @@ static int siimage_config_drive_for_dma (ide_drive_t *drive)
                return 0;
 
        if (ide_use_fast_pio(drive))
-               config_chipset_for_pio(drive, 1);
+               config_siimage_chipset_for_pio(drive, 1);
 
        return -1;
 }
@@ -1015,7 +1008,6 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
 
        hwif->ultra_mask = 0x7f;
        hwif->mwdma_mask = 0x07;
-       hwif->swdma_mask = 0x07;
 
        if (!is_sata(hwif))
                hwif->atapi_dma = 1;
index 3a8a76f..fe3b4b9 100644 (file)
@@ -11,6 +11,8 @@
  * Merge in Russell's HW workarounds, fix various problems
  * with the timing registers setup.
  *  -- Benjamin Herrenschmidt (01/11/03) benh@kernel.crashing.org
+ *
+ * Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com>
  */
 
 #include <linux/types.h>
 #define CTRL_P0EN       (1 << 0)
 
 /*
- * Convert a PIO mode and cycle time to the required on/off
- * times for the interface.  This has protection against run-away
- * timings.
+ * Convert a PIO mode and cycle time to the required on/off times
+ * for the interface.  This has protection against runaway timings.
  */
-static unsigned int get_timing_sl82c105(ide_pio_data_t *p)
+static unsigned int get_pio_timings(ide_pio_data_t *p)
 {
-       unsigned int cmd_on;
-       unsigned int cmd_off;
+       unsigned int cmd_on, cmd_off;
 
-       cmd_on = (ide_pio_timings[p->pio_mode].active_time + 29) / 30;
+       cmd_on  = (ide_pio_timings[p->pio_mode].active_time + 29) / 30;
        cmd_off = (p->cycle_time - 30 * cmd_on + 29) / 30;
 
-       if (cmd_on > 32)
-               cmd_on = 32;
        if (cmd_on == 0)
                cmd_on = 1;
 
-       if (cmd_off > 32)
-               cmd_off = 32;
        if (cmd_off == 0)
                cmd_off = 1;
 
@@ -73,100 +69,59 @@ static unsigned int get_timing_sl82c105(ide_pio_data_t *p)
 }
 
 /*
- * Configure the drive and chipset for PIO
+ * Configure the chipset for PIO mode.
  */
-static void config_for_pio(ide_drive_t *drive, int pio, int report, int chipset_only)
+static u8 sl82c105_tune_pio(ide_drive_t *drive, u8 pio)
 {
-       ide_hwif_t *hwif = HWIF(drive);
-       struct pci_dev *dev = hwif->pci_dev;
+       struct pci_dev *dev     = HWIF(drive)->pci_dev;
+       int reg                 = 0x44 + drive->dn * 4;
        ide_pio_data_t p;
-       u16 drv_ctrl = 0x909;
-       unsigned int xfer_mode, reg;
+       u16 drv_ctrl;
 
-       DBG(("config_for_pio(drive:%s, pio:%d, report:%d, chipset_only:%d)\n",
-               drive->name, pio, report, chipset_only));
-               
-       reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0);
+       DBG(("sl82c105_tune_pio(drive:%s, pio:%u)\n", drive->name, pio));
 
        pio = ide_get_best_pio_mode(drive, pio, 5, &p);
 
-       xfer_mode = XFER_PIO_0 + pio;
-
-       if (chipset_only || ide_config_drive_speed(drive, xfer_mode) == 0) {
-               drv_ctrl = get_timing_sl82c105(&p);
-               drive->pio_speed = xfer_mode;
-       } else
-               drive->pio_speed = XFER_PIO_0;
+       drive->drive_data = drv_ctrl = get_pio_timings(&p);
 
-       if (drive->using_dma == 0) {
+       if (!drive->using_dma) {
                /*
                 * If we are actually using MW DMA, then we can not
                 * reprogram the interface drive control register.
                 */
-               pci_write_config_word(dev, reg, drv_ctrl);
-               pci_read_config_word(dev, reg, &drv_ctrl);
-
-               if (report) {
-                       printk("%s: selected %s (%dns) (%04X)\n", drive->name,
-                              ide_xfer_verbose(xfer_mode), p.cycle_time, drv_ctrl);
-               }
+               pci_write_config_word(dev, reg,  drv_ctrl);
+               pci_read_config_word (dev, reg, &drv_ctrl);
        }
+
+       printk(KERN_DEBUG "%s: selected %s (%dns) (%04X)\n", drive->name,
+              ide_xfer_verbose(pio + XFER_PIO_0), p.cycle_time, drv_ctrl);
+
+       return pio;
 }
 
 /*
- * Configure the drive and the chipset for DMA
+ * Configure the drive for DMA.
+ * We'll program the chipset only when DMA is actually turned on.
  */
-static int config_for_dma (ide_drive_t *drive)
+static int config_for_dma(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = HWIF(drive);
-       struct pci_dev *dev = hwif->pci_dev;
-       unsigned int reg;
-
        DBG(("config_for_dma(drive:%s)\n", drive->name));
 
-       reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0);
-
        if (ide_config_drive_speed(drive, XFER_MW_DMA_2) != 0)
-               return 1;
+               return 0;
 
-       pci_write_config_word(dev, reg, 0x0240);
-
-       return 0;
+       return ide_dma_enable(drive);
 }
 
 /*
- * Check to see if the drive and
- * chipset is capable of DMA mode
+ * Check to see if the drive and chipset are capable of DMA mode.
  */
-
-static int sl82c105_check_drive (ide_drive_t *drive)
+static int sl82c105_ide_dma_check(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
-
-       DBG(("sl82c105_check_drive(drive:%s)\n", drive->name));
-
-       do {
-               struct hd_driveid *id = drive->id;
-
-               if (!drive->autodma)
-                       break;
-
-               if (!id || !(id->capability & 1))
-                       break;
+       DBG(("sl82c105_ide_dma_check(drive:%s)\n", drive->name));
 
-               /* Consult the list of known "bad" drives */
-               if (__ide_dma_bad_drive(drive))
-                       break;
-
-               if (id->field_valid & 2) {
-                       if ((id->dma_mword & hwif->mwdma_mask) ||
-                           (id->dma_1word & hwif->swdma_mask))
-                               return 0;
-               }
-
-               if (__ide_dma_good_drive(drive) && id->eide_dma_time < 150)
-                       return 0;
-       } while (0);
+       if (ide_use_dma(drive) && config_for_dma(drive))
+               return 0;
 
        return -1;
 }
@@ -195,14 +150,14 @@ static inline void sl82c105_reset_host(struct pci_dev *dev)
  * This function is called when the IDE timer expires, the drive
  * indicates that it is READY, and we were waiting for DMA to complete.
  */
-static int sl82c105_ide_dma_lost_irq(ide_drive_t *drive)
+static int sl82c105_ide_dma_lostirq(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = HWIF(drive);
-       struct pci_dev *dev = hwif->pci_dev;
-       u32 val, mask = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA;
-       unsigned long dma_base = hwif->dma_base;
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = hwif->pci_dev;
+       u32 val, mask           = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA;
+       u8 dma_cmd;
 
-       printk("sl82c105: lost IRQ: resetting host\n");
+       printk("sl82c105: lost IRQ, resetting host\n");
 
        /*
         * Check the raw interrupt from the drive.
@@ -215,15 +170,15 @@ static int sl82c105_ide_dma_lost_irq(ide_drive_t *drive)
         * Was DMA enabled?  If so, disable it - we're resetting the
         * host.  The IDE layer will be handling the drive for us.
         */
-       val = inb(dma_base);
-       if (val & 1) {
-               outb(val & ~1, dma_base);
+       dma_cmd = inb(hwif->dma_command);
+       if (dma_cmd & 1) {
+               outb(dma_cmd & ~1, hwif->dma_command);
                printk("sl82c105: DMA was enabled\n");
        }
 
        sl82c105_reset_host(dev);
 
-       /* ide_dmaproc would return 1, so we do as well */
+       /* __ide_dma_lostirq would return 1, so we do as well */
        return 1;
 }
 
@@ -235,10 +190,10 @@ static int sl82c105_ide_dma_lost_irq(ide_drive_t *drive)
  * The generic IDE core will have disabled the BMEN bit before this
  * function is called.
  */
-static void sl82c105_ide_dma_start(ide_drive_t *drive)
+static void sl82c105_dma_start(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = HWIF(drive);
-       struct pci_dev *dev = hwif->pci_dev;
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = hwif->pci_dev;
 
        sl82c105_reset_host(dev);
        ide_dma_start(drive);
@@ -246,8 +201,8 @@ static void sl82c105_ide_dma_start(ide_drive_t *drive)
 
 static int sl82c105_ide_dma_timeout(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = HWIF(drive);
-       struct pci_dev *dev = hwif->pci_dev;
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = hwif->pci_dev;
 
        DBG(("sl82c105_ide_dma_timeout(drive:%s)\n", drive->name));
 
@@ -255,26 +210,32 @@ static int sl82c105_ide_dma_timeout(ide_drive_t *drive)
        return __ide_dma_timeout(drive);
 }
 
-static int sl82c105_ide_dma_on (ide_drive_t *drive)
+static int sl82c105_ide_dma_on(ide_drive_t *drive)
 {
+       struct pci_dev *dev     = HWIF(drive)->pci_dev;
+       int rc, reg             = 0x44 + drive->dn * 4;
+
        DBG(("sl82c105_ide_dma_on(drive:%s)\n", drive->name));
 
-       if (config_for_dma(drive))
-               return 1;
-       printk(KERN_INFO "%s: DMA enabled\n", drive->name);
-       return __ide_dma_on(drive);
+       rc = __ide_dma_on(drive);
+       if (rc == 0) {
+               pci_write_config_word(dev, reg, 0x0200);
+
+               printk(KERN_INFO "%s: DMA enabled\n", drive->name);
+       }
+       return rc;
 }
 
 static void sl82c105_dma_off_quietly(ide_drive_t *drive)
 {
-       u8 speed = XFER_PIO_0;
+       struct pci_dev *dev     = HWIF(drive)->pci_dev;
+       int reg                 = 0x44 + drive->dn * 4;
 
        DBG(("sl82c105_dma_off_quietly(drive:%s)\n", drive->name));
 
+       pci_write_config_word(dev, reg, drive->drive_data);
+
        ide_dma_off_quietly(drive);
-       if (drive->pio_speed)
-               speed = drive->pio_speed - XFER_PIO_0;
-       config_for_pio(drive, speed, 0, 1);
 }
 
 /*
@@ -286,8 +247,8 @@ static void sl82c105_dma_off_quietly(ide_drive_t *drive)
  */
 static void sl82c105_selectproc(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = HWIF(drive);
-       struct pci_dev *dev = hwif->pci_dev;
+       ide_hwif_t *hwif        = HWIF(drive);
+       struct pci_dev *dev     = hwif->pci_dev;
        u32 val, old, mask;
 
        //DBG(("sl82c105_selectproc(drive:%s)\n", drive->name));
@@ -323,18 +284,12 @@ static void sl82c105_resetproc(ide_drive_t *drive)
  * We only deal with PIO mode here - DMA mode 'using_dma' is not
  * initialised at the point that this function is called.
  */
-static void tune_sl82c105(ide_drive_t *drive, u8 pio)
+static void sl82c105_tune_drive(ide_drive_t *drive, u8 pio)
 {
-       DBG(("tune_sl82c105(drive:%s)\n", drive->name));
-
-       config_for_pio(drive, pio, 1, 0);
+       DBG(("sl82c105_tune_drive(drive:%s, pio:%u)\n", drive->name, pio));
 
-       /*
-        * We support 32-bit I/O on this interface, and it
-        * doesn't have problems with interrupts.
-        */
-       drive->io_32bit = 1;
-       drive->unmask = 1;
+       pio = sl82c105_tune_pio(drive, pio);
+       (void) ide_config_drive_speed(drive, XFER_PIO_0 + pio);
 }
 
 /*
@@ -393,7 +348,7 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c
 }
 
 /*
- * Initialise the chip
+ * Initialise IDE channel
  */
 static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
 {
@@ -401,24 +356,22 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
 
        DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index));
 
-       hwif->tuneproc = tune_sl82c105;
-       hwif->selectproc = sl82c105_selectproc;
-       hwif->resetproc = sl82c105_resetproc;
+       hwif->tuneproc          = &sl82c105_tune_drive;
+       hwif->selectproc        = &sl82c105_selectproc;
+       hwif->resetproc         = &sl82c105_resetproc;
+
+       /*
+        * We support 32-bit I/O on this interface, and
+        * it doesn't have problems with interrupts.
+        */
+       hwif->drives[0].io_32bit = hwif->drives[1].io_32bit = 1;
+       hwif->drives[0].unmask   = hwif->drives[1].unmask   = 1;
 
        /*
-        * Default to PIO 0 for fallback unless tuned otherwise.
         * We always autotune PIO,  this is done before DMA is checked,
         * so there's no risk of accidentally disabling DMA
         */
-       hwif->drives[0].pio_speed = XFER_PIO_0;
-       hwif->drives[0].autotune = 1;
-       hwif->drives[1].pio_speed = XFER_PIO_0;
-       hwif->drives[1].autotune = 1;
-
-       hwif->atapi_dma = 0;
-       hwif->mwdma_mask = 0;
-       hwif->swdma_mask = 0;
-       hwif->autodma = 0;
+       hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
 
        if (!hwif->dma_base)
                return;
@@ -429,27 +382,27 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
                 * Never ever EVER under any circumstances enable
                 * DMA when the bridge is this old.
                 */
-               printk("    %s: Winbond 553 bridge revision %d, BM-DMA disabled\n",
-                      hwif->name, rev);
-       } else {
-               hwif->atapi_dma = 1;
-               hwif->mwdma_mask = 0x04;
-
-               hwif->ide_dma_check = &sl82c105_check_drive;
-               hwif->ide_dma_on = &sl82c105_ide_dma_on;
-               hwif->dma_off_quietly = &sl82c105_dma_off_quietly;
-               hwif->ide_dma_lostirq = &sl82c105_ide_dma_lost_irq;
-               hwif->dma_start = &sl82c105_ide_dma_start;
-               hwif->ide_dma_timeout = &sl82c105_ide_dma_timeout;
-
-               if (!noautodma)
-                       hwif->autodma = 1;
-               hwif->drives[0].autodma = hwif->autodma;
-               hwif->drives[1].autodma = hwif->autodma;
-
-               if (hwif->mate)
-                       hwif->serialized = hwif->mate->serialized = 1;
+               printk("    %s: Winbond W83C553 bridge revision %d, "
+                      "BM-DMA disabled\n", hwif->name, rev);
+               return;
        }
+
+       hwif->atapi_dma  = 1;
+       hwif->mwdma_mask = 0x04;
+
+       hwif->ide_dma_check             = &sl82c105_ide_dma_check;
+       hwif->ide_dma_on                = &sl82c105_ide_dma_on;
+       hwif->dma_off_quietly           = &sl82c105_dma_off_quietly;
+       hwif->ide_dma_lostirq           = &sl82c105_ide_dma_lostirq;
+       hwif->dma_start                 = &sl82c105_dma_start;
+       hwif->ide_dma_timeout           = &sl82c105_ide_dma_timeout;
+
+       if (!noautodma)
+               hwif->autodma = 1;
+       hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
+
+       if (hwif->mate)
+               hwif->serialized = hwif->mate->serialized = 1;
 }
 
 static ide_pci_device_t sl82c105_chipset __devinitdata = {
index 6164a9a..bd0755c 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/list.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/pci.h>
 #include <linux/timer.h>
 #include <linux/jiffies.h>
 #include <linux/mutex.h>
index 842cd0b..eff591d 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/err.h>
 #include <linux/idr.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/random.h>
 #include <linux/rbtree.h>
 #include <linux/spinlock.h>
index 891d1fa..223b1aa 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/err.h>
 #include <linux/idr.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/rbtree.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
index de89717..9be5cc0 100644 (file)
@@ -39,7 +39,6 @@
 
 #include <linux/completion.h>
 #include <linux/err.h>
-#include <linux/pci.h>
 #include <linux/workqueue.h>
 #include <rdma/ib_mad.h>
 #include <rdma/ib_smi.h>
index 4a579b3..1e13ab4 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/bitops.h>
 #include <linux/random.h>
 
index 9a7eaad..6469406 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/random.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
-#include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/kref.h>
 #include <linux/idr.h>
index 8199b83..d97ded2 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/err.h>
 #include <linux/fs.h>
 #include <linux/cdev.h>
-#include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/poll.h>
 #include <linux/rwsem.h>
index ed55979..036ed1e 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/pagemap.h>
 #include <linux/init.h>
 #include <linux/namei.h>
-#include <linux/pci.h>
 
 #include "ipath_kernel.h"
 
index e46aa4e..05a1d2b 100644 (file)
@@ -37,7 +37,6 @@
  */
 
 #include <linux/io.h>
-#include <linux/pci.h>
 #include <asm/byteorder.h>
 
 #include "ipath_kernel.h"
index 9307f71..d8b5e4c 100644 (file)
@@ -31,8 +31,6 @@
  * SOFTWARE.
  */
 
-#include <linux/pci.h>
-
 #include "ipath_kernel.h"
 
 struct infinipath_stats ipath_stats;
index ffa6318..4dc398d 100644 (file)
@@ -32,7 +32,6 @@
  */
 
 #include <linux/ctype.h>
-#include <linux/pci.h>
 
 #include "ipath_kernel.h"
 #include "ipath_common.h"
index 5941441..a1ab068 100644 (file)
@@ -38,7 +38,6 @@
 #define MTHCA_MEMFREE_H
 
 #include <linux/list.h>
-#include <linux/pci.h>
 #include <linux/mutex.h>
 
 #define MTHCA_ICM_CHUNK_LEN \
index fd55826..d8f6bb4 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <linux/workqueue.h>
-#include <linux/pci.h>
 #include <linux/kref.h>
 #include <linux/if_infiniband.h>
 #include <linux/mutex.h>
index 278fcbc..3651072 100644 (file)
@@ -201,7 +201,7 @@ static int iser_post_receive_control(struct iscsi_conn *conn)
         * what's common for both schemes is that the connection is not started
         */
        if (conn->c_stage != ISCSI_CONN_STARTED)
-               rx_data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
+               rx_data_size = ISCSI_DEF_MAX_RECV_SEG_LEN;
        else /* FIXME till user space sets conn->max_recv_dlength correctly */
                rx_data_size = 128;
 
index da575de..b4cd106 100644 (file)
@@ -13,7 +13,6 @@ obj-$(CONFIG_INPUT_MOUSEDEV)  += mousedev.o
 obj-$(CONFIG_INPUT_JOYDEV)     += joydev.o
 obj-$(CONFIG_INPUT_EVDEV)      += evdev.o
 obj-$(CONFIG_INPUT_TSDEV)      += tsdev.o
-obj-$(CONFIG_INPUT_POWER)      += power.o
 obj-$(CONFIG_INPUT_EVBUG)      += evbug.o
 
 obj-$(CONFIG_INPUT_KEYBOARD)   += keyboard/
index 5a9653c..c21f2f1 100644 (file)
@@ -38,31 +38,43 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Input driver event debug module");
 MODULE_LICENSE("GPL");
 
-static char evbug_name[] = "evbug";
-
 static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
 {
        printk(KERN_DEBUG "evbug.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n",
                handle->dev->phys, type, code, value);
 }
 
-static struct input_handle *evbug_connect(struct input_handler *handler, struct input_dev *dev,
-                                         const struct input_device_id *id)
+static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
+                        const struct input_device_id *id)
 {
        struct input_handle *handle;
+       int error;
 
-       if (!(handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL)))
-               return NULL;
+       handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
+       if (!handle)
+               return -ENOMEM;
 
        handle->dev = dev;
        handle->handler = handler;
-       handle->name = evbug_name;
+       handle->name = "evbug";
+
+       error = input_register_handle(handle);
+       if (error)
+               goto err_free_handle;
 
-       input_open_device(handle);
+       error = input_open_device(handle);
+       if (error)
+               goto err_unregister_handle;
 
        printk(KERN_DEBUG "evbug.c: Connected device: \"%s\", %s\n", dev->name, dev->phys);
 
-       return handle;
+       return 0;
+
+ err_unregister_handle:
+       input_unregister_handle(handle);
+ err_free_handle:
+       kfree(handle);
+       return error;
 }
 
 static void evbug_disconnect(struct input_handle *handle)
@@ -70,7 +82,7 @@ static void evbug_disconnect(struct input_handle *handle)
        printk(KERN_DEBUG "evbug.c: Disconnected device: %s\n", handle->dev->phys);
 
        input_close_device(handle);
-
+       input_unregister_handle(handle);
        kfree(handle);
 }
 
index 6439f37..1f6fcec 100644 (file)
@@ -29,11 +29,11 @@ struct evdev {
        char name[16];
        struct input_handle handle;
        wait_queue_head_t wait;
-       struct evdev_list *grab;
-       struct list_head list;
+       struct evdev_client *grab;
+       struct list_head client_list;
 };
 
-struct evdev_list {
+struct evdev_client {
        struct input_event buffer[EVDEV_BUFFER_SIZE];
        int head;
        int tail;
@@ -47,28 +47,28 @@ static struct evdev *evdev_table[EVDEV_MINORS];
 static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
 {
        struct evdev *evdev = handle->private;
-       struct evdev_list *list;
+       struct evdev_client *client;
 
        if (evdev->grab) {
-               list = evdev->grab;
+               client = evdev->grab;
 
-               do_gettimeofday(&list->buffer[list->head].time);
-               list->buffer[list->head].type = type;
-               list->buffer[list->head].code = code;
-               list->buffer[list->head].value = value;
-               list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1);
+               do_gettimeofday(&client->buffer[client->head].time);
+               client->buffer[client->head].type = type;
+               client->buffer[client->head].code = code;
+               client->buffer[client->head].value = value;
+               client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1);
 
-               kill_fasync(&list->fasync, SIGIO, POLL_IN);
+               kill_fasync(&client->fasync, SIGIO, POLL_IN);
        } else
-               list_for_each_entry(list, &evdev->list, node) {
+               list_for_each_entry(client, &evdev->client_list, node) {
 
-                       do_gettimeofday(&list->buffer[list->head].time);
-                       list->buffer[list->head].type = type;
-                       list->buffer[list->head].code = code;
-                       list->buffer[list->head].value = value;
-                       list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1);
+                       do_gettimeofday(&client->buffer[client->head].time);
+                       client->buffer[client->head].type = type;
+                       client->buffer[client->head].code = code;
+                       client->buffer[client->head].value = value;
+                       client->head = (client->head + 1) & (EVDEV_BUFFER_SIZE - 1);
 
-                       kill_fasync(&list->fasync, SIGIO, POLL_IN);
+                       kill_fasync(&client->fasync, SIGIO, POLL_IN);
                }
 
        wake_up_interruptible(&evdev->wait);
@@ -76,22 +76,23 @@ static void evdev_event(struct input_handle *handle, unsigned int type, unsigned
 
 static int evdev_fasync(int fd, struct file *file, int on)
 {
+       struct evdev_client *client = file->private_data;
        int retval;
-       struct evdev_list *list = file->private_data;
 
-       retval = fasync_helper(fd, file, on, &list->fasync);
+       retval = fasync_helper(fd, file, on, &client->fasync);
 
        return retval < 0 ? retval : 0;
 }
 
 static int evdev_flush(struct file *file, fl_owner_t id)
 {
-       struct evdev_list *list = file->private_data;
+       struct evdev_client *client = file->private_data;
+       struct evdev *evdev = client->evdev;
 
-       if (!list->evdev->exist)
+       if (!evdev->exist)
                return -ENODEV;
 
-       return input_flush_device(&list->evdev->handle, file);
+       return input_flush_device(&evdev->handle, file);
 }
 
 static void evdev_free(struct evdev *evdev)
@@ -100,48 +101,62 @@ static void evdev_free(struct evdev *evdev)
        kfree(evdev);
 }
 
-static int evdev_release(struct inode * inode, struct file * file)
+static int evdev_release(struct inode *inode, struct file *file)
 {
-       struct evdev_list *list = file->private_data;
+       struct evdev_client *client = file->private_data;
+       struct evdev *evdev = client->evdev;
 
-       if (list->evdev->grab == list) {
-               input_release_device(&list->evdev->handle);
-               list->evdev->grab = NULL;
+       if (evdev->grab == client) {
+               input_release_device(&evdev->handle);
+               evdev->grab = NULL;
        }
 
        evdev_fasync(-1, file, 0);
-       list_del(&list->node);
+       list_del(&client->node);
+       kfree(client);
 
-       if (!--list->evdev->open) {
-               if (list->evdev->exist)
-                       input_close_device(&list->evdev->handle);
+       if (!--evdev->open) {
+               if (evdev->exist)
+                       input_close_device(&evdev->handle);
                else
-                       evdev_free(list->evdev);
+                       evdev_free(evdev);
        }
 
-       kfree(list);
        return 0;
 }
 
-static int evdev_open(struct inode * inode, struct file * file)
+static int evdev_open(struct inode *inode, struct file *file)
 {
-       struct evdev_list *list;
+       struct evdev_client *client;
+       struct evdev *evdev;
        int i = iminor(inode) - EVDEV_MINOR_BASE;
+       int error;
 
-       if (i >= EVDEV_MINORS || !evdev_table[i] || !evdev_table[i]->exist)
+       if (i >= EVDEV_MINORS)
                return -ENODEV;
 
-       if (!(list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL)))
+       evdev = evdev_table[i];
+
+       if (!evdev || !evdev->exist)
+               return -ENODEV;
+
+       client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL);
+       if (!client)
                return -ENOMEM;
 
-       list->evdev = evdev_table[i];
-       list_add_tail(&list->node, &evdev_table[i]->list);
-       file->private_data = list;
+       client->evdev = evdev;
+       list_add_tail(&client->node, &evdev->client_list);
 
-       if (!list->evdev->open++)
-               if (list->evdev->exist)
-                       input_open_device(&list->evdev->handle);
+       if (!evdev->open++ && evdev->exist) {
+               error = input_open_device(&evdev->handle);
+               if (error) {
+                       list_del(&client->node);
+                       kfree(client);
+                       return error;
+               }
+       }
 
+       file->private_data = client;
        return 0;
 }
 
@@ -243,54 +258,55 @@ static int evdev_event_to_user(char __user *buffer, const struct input_event *ev
 
 #endif /* CONFIG_COMPAT */
 
-static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
+static ssize_t evdev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
-       struct evdev_list *list = file->private_data;
+       struct evdev_client *client = file->private_data;
+       struct evdev *evdev = client->evdev;
        struct input_event event;
        int retval = 0;
 
-       if (!list->evdev->exist)
+       if (!evdev->exist)
                return -ENODEV;
 
        while (retval < count) {
 
                if (evdev_event_from_user(buffer + retval, &event))
                        return -EFAULT;
-               input_inject_event(&list->evdev->handle, event.type, event.code, event.value);
+               input_inject_event(&evdev->handle, event.type, event.code, event.value);
                retval += evdev_event_size();
        }
 
        return retval;
 }
 
-static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
+static ssize_t evdev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
-       struct evdev_list *list = file->private_data;
+       struct evdev_client *client = file->private_data;
+       struct evdev *evdev = client->evdev;
        int retval;
 
        if (count < evdev_event_size())
                return -EINVAL;
 
-       if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK))
+       if (client->head == client->tail && evdev->exist && (file->f_flags & O_NONBLOCK))
                return -EAGAIN;
 
-       retval = wait_event_interruptible(list->evdev->wait,
-               list->head != list->tail || (!list->evdev->exist));
-
+       retval = wait_event_interruptible(evdev->wait,
+               client->head != client->tail || !evdev->exist);
        if (retval)
                return retval;
 
-       if (!list->evdev->exist)
+       if (!evdev->exist)
                return -ENODEV;
 
-       while (list->head != list->tail && retval + evdev_event_size() <= count) {
+       while (client->head != client->tail && retval + evdev_event_size() <= count) {
 
-               struct input_event *event = (struct input_event *) list->buffer + list->tail;
+               struct input_event *event = (struct input_event *) client->buffer + client->tail;
 
                if (evdev_event_to_user(buffer + retval, event))
                        return -EFAULT;
 
-               list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
+               client->tail = (client->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
                retval += evdev_event_size();
        }
 
@@ -300,11 +316,12 @@ static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count
 /* No kernel lock - fine */
 static unsigned int evdev_poll(struct file *file, poll_table *wait)
 {
-       struct evdev_list *list = file->private_data;
+       struct evdev_client *client = file->private_data;
+       struct evdev *evdev = client->evdev;
 
-       poll_wait(file, &list->evdev->wait, wait);
-       return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
-               (list->evdev->exist ? 0 : (POLLHUP | POLLERR));
+       poll_wait(file, &evdev->wait, wait);
+       return ((client->head == client->tail) ? 0 : (POLLIN | POLLRDNORM)) |
+               (evdev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
 #ifdef CONFIG_COMPAT
@@ -387,8 +404,8 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p)
 static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
                                void __user *p, int compat_mode)
 {
-       struct evdev_list *list = file->private_data;
-       struct evdev *evdev = list->evdev;
+       struct evdev_client *client = file->private_data;
+       struct evdev *evdev = client->evdev;
        struct input_dev *dev = evdev->handle.dev;
        struct input_absinfo abs;
        struct ff_effect effect;
@@ -434,32 +451,21 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
                case EVIOCGKEYCODE:
                        if (get_user(t, ip))
                                return -EFAULT;
-                       if (t < 0 || t >= dev->keycodemax || !dev->keycodesize)
-                               return -EINVAL;
-                       if (put_user(INPUT_KEYCODE(dev, t), ip + 1))
+
+                       error = dev->getkeycode(dev, t, &v);
+                       if (error)
+                               return error;
+
+                       if (put_user(v, ip + 1))
                                return -EFAULT;
+
                        return 0;
 
                case EVIOCSKEYCODE:
-                       if (get_user(t, ip))
+                       if (get_user(t, ip) || get_user(v, ip + 1))
                                return -EFAULT;
-                       if (t < 0 || t >= dev->keycodemax || !dev->keycodesize)
-                               return -EINVAL;
-                       if (get_user(v, ip + 1))
-                               return -EFAULT;
-                       if (v < 0 || v > KEY_MAX)
-                               return -EINVAL;
-                       if (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8)))
-                               return -EINVAL;
-
-                       u = SET_INPUT_KEYCODE(dev, t, v);
-                       clear_bit(u, dev->keybit);
-                       set_bit(v, dev->keybit);
-                       for (i = 0; i < dev->keycodemax; i++)
-                               if (INPUT_KEYCODE(dev, i) == u)
-                                       set_bit(u, dev->keybit);
 
-                       return 0;
+                       return dev->setkeycode(dev, t, v);
 
                case EVIOCSFF:
                        if (copy_from_user(&effect, p, sizeof(effect)))
@@ -487,10 +493,10 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
                                        return -EBUSY;
                                if (input_grab_device(&evdev->handle))
                                        return -EBUSY;
-                               evdev->grab = list;
+                               evdev->grab = client;
                                return 0;
                        } else {
-                               if (evdev->grab != list)
+                               if (evdev->grab != client)
                                        return -EINVAL;
                                input_release_device(&evdev->handle);
                                evdev->grab = NULL;
@@ -616,23 +622,26 @@ static const struct file_operations evdev_fops = {
        .flush =        evdev_flush
 };
 
-static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev,
-                                         const struct input_device_id *id)
+static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
+                        const struct input_device_id *id)
 {
        struct evdev *evdev;
        struct class_device *cdev;
+       dev_t devt;
        int minor;
+       int error;
 
        for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++);
        if (minor == EVDEV_MINORS) {
                printk(KERN_ERR "evdev: no more free evdev devices\n");
-               return NULL;
+               return -ENFILE;
        }
 
-       if (!(evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL)))
-               return NULL;
+       evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);
+       if (!evdev)
+               return -ENOMEM;
 
-       INIT_LIST_HEAD(&evdev->list);
+       INIT_LIST_HEAD(&evdev->client_list);
        init_waitqueue_head(&evdev->wait);
 
        evdev->exist = 1;
@@ -645,23 +654,45 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct
 
        evdev_table[minor] = evdev;
 
-       cdev = class_device_create(&input_class, &dev->cdev,
-                       MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
-                       dev->cdev.dev, evdev->name);
+       devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
+
+       cdev = class_device_create(&input_class, &dev->cdev, devt,
+                                  dev->cdev.dev, evdev->name);
+       if (IS_ERR(cdev)) {
+               error = PTR_ERR(cdev);
+               goto err_free_evdev;
+       }
 
        /* temporary symlink to keep userspace happy */
-       sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
-                         evdev->name);
+       error = sysfs_create_link(&input_class.subsys.kobj,
+                                 &cdev->kobj, evdev->name);
+       if (error)
+               goto err_cdev_destroy;
+
+       error = input_register_handle(&evdev->handle);
+       if (error)
+               goto err_remove_link;
 
-       return &evdev->handle;
+       return 0;
+
+ err_remove_link:
+       sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
+ err_cdev_destroy:
+       class_device_destroy(&input_class, devt);
+ err_free_evdev:
+       kfree(evdev);
+       evdev_table[minor] = NULL;
+       return error;
 }
 
 static void evdev_disconnect(struct input_handle *handle)
 {
        struct evdev *evdev = handle->private;
-       struct evdev_list *list;
+       struct evdev_client *client;
+
+       input_unregister_handle(handle);
 
-       sysfs_remove_link(&input_class.subsys.kset.kobj, evdev->name);
+       sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
        class_device_destroy(&input_class,
                        MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
        evdev->exist = 0;
@@ -670,8 +701,8 @@ static void evdev_disconnect(struct input_handle *handle)
                input_flush_device(handle, NULL);
                input_close_device(handle);
                wake_up_interruptible(&evdev->wait);
-               list_for_each_entry(list, &evdev->list, node)
-                       kill_fasync(&list->fasync, SIGIO, POLL_HUP);
+               list_for_each_entry(client, &evdev->client_list, node)
+                       kill_fasync(&client->fasync, SIGIO, POLL_HUP);
        } else
                evdev_free(evdev);
 }
index a9a706f..915e9ab 100644 (file)
@@ -299,12 +299,87 @@ void input_close_device(struct input_handle *handle)
 }
 EXPORT_SYMBOL(input_close_device);
 
-static void input_link_handle(struct input_handle *handle)
+static int input_fetch_keycode(struct input_dev *dev, int scancode)
 {
-       list_add_tail(&handle->d_node, &handle->dev->h_list);
-       list_add_tail(&handle->h_node, &handle->handler->h_list);
+       switch (dev->keycodesize) {
+               case 1:
+                       return ((u8 *)dev->keycode)[scancode];
+
+               case 2:
+                       return ((u16 *)dev->keycode)[scancode];
+
+               default:
+                       return ((u32 *)dev->keycode)[scancode];
+       }
+}
+
+static int input_default_getkeycode(struct input_dev *dev,
+                                   int scancode, int *keycode)
+{
+       if (!dev->keycodesize)
+               return -EINVAL;
+
+       if (scancode < 0 || scancode >= dev->keycodemax)
+               return -EINVAL;
+
+       *keycode = input_fetch_keycode(dev, scancode);
+
+       return 0;
+}
+
+static int input_default_setkeycode(struct input_dev *dev,
+                                   int scancode, int keycode)
+{
+       int old_keycode;
+       int i;
+
+       if (scancode < 0 || scancode >= dev->keycodemax)
+               return -EINVAL;
+
+       if (keycode < 0 || keycode > KEY_MAX)
+               return -EINVAL;
+
+       if (!dev->keycodesize)
+               return -EINVAL;
+
+       if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
+               return -EINVAL;
+
+       switch (dev->keycodesize) {
+               case 1: {
+                       u8 *k = (u8 *)dev->keycode;
+                       old_keycode = k[scancode];
+                       k[scancode] = keycode;
+                       break;
+               }
+               case 2: {
+                       u16 *k = (u16 *)dev->keycode;
+                       old_keycode = k[scancode];
+                       k[scancode] = keycode;
+                       break;
+               }
+               default: {
+                       u32 *k = (u32 *)dev->keycode;
+                       old_keycode = k[scancode];
+                       k[scancode] = keycode;
+                       break;
+               }
+       }
+
+       clear_bit(old_keycode, dev->keybit);
+       set_bit(keycode, dev->keybit);
+
+       for (i = 0; i < dev->keycodemax; i++) {
+               if (input_fetch_keycode(dev, i) == old_keycode) {
+                       set_bit(old_keycode, dev->keybit);
+                       break; /* Setting the bit twice is useless, so break */
+               }
+       }
+
+       return 0;
 }
 
+
 #define MATCH_BIT(bit, max) \
                for (i = 0; i < NBITS(max); i++) \
                        if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
@@ -351,6 +426,29 @@ static const struct input_device_id *input_match_device(const struct input_devic
        return NULL;
 }
 
+static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
+{
+       const struct input_device_id *id;
+       int error;
+
+       if (handler->blacklist && input_match_device(handler->blacklist, dev))
+               return -ENODEV;
+
+       id = input_match_device(handler->id_table, dev);
+       if (!id)
+               return -ENODEV;
+
+       error = handler->connect(handler, dev, id);
+       if (error && error != -ENODEV)
+               printk(KERN_ERR
+                       "input: failed to attach handler %s to device %s, "
+                       "error: %d\n",
+                       handler->name, kobject_name(&dev->cdev.kobj), error);
+
+       return error;
+}
+
+
 #ifdef CONFIG_PROC_FS
 
 static struct proc_dir_entry *proc_bus_input_dir;
@@ -439,6 +537,7 @@ static int input_devices_seq_show(struct seq_file *seq, void *v)
        seq_printf(seq, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
        seq_printf(seq, "P: Phys=%s\n", dev->phys ? dev->phys : "");
        seq_printf(seq, "S: Sysfs=%s\n", path ? path : "");
+       seq_printf(seq, "U: Uniq=%s\n", dev->uniq ? dev->uniq : "");
        seq_printf(seq, "H: Handlers=");
 
        list_for_each_entry(handle, &dev->h_list, d_node)
@@ -753,6 +852,13 @@ static struct attribute_group input_dev_caps_attr_group = {
        .attrs  = input_dev_caps_attrs,
 };
 
+static struct attribute_group *input_dev_attr_groups[] = {
+       &input_dev_attr_group,
+       &input_dev_id_attr_group,
+       &input_dev_caps_attr_group,
+       NULL
+};
+
 static void input_dev_release(struct class_device *class_dev)
 {
        struct input_dev *dev = to_input_dev(class_dev);
@@ -906,6 +1012,7 @@ struct input_dev *input_allocate_device(void)
        dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
        if (dev) {
                dev->cdev.class = &input_class;
+               dev->cdev.groups = input_dev_attr_groups;
                class_device_initialize(&dev->cdev);
                mutex_init(&dev->mutex);
                INIT_LIST_HEAD(&dev->h_list);
@@ -934,23 +1041,71 @@ EXPORT_SYMBOL(input_allocate_device);
  */
 void input_free_device(struct input_dev *dev)
 {
-       if (dev) {
-
-               mutex_lock(&dev->mutex);
-               dev->name = dev->phys = dev->uniq = NULL;
-               mutex_unlock(&dev->mutex);
-
+       if (dev)
                input_put_device(dev);
-       }
 }
 EXPORT_SYMBOL(input_free_device);
 
+/**
+ * input_set_capability - mark device as capable of a certain event
+ * @dev: device that is capable of emitting or accepting event
+ * @type: type of the event (EV_KEY, EV_REL, etc...)
+ * @code: event code
+ *
+ * In addition to setting up corresponding bit in appropriate capability
+ * bitmap the function also adjusts dev->evbit.
+ */
+void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code)
+{
+       switch (type) {
+       case EV_KEY:
+               __set_bit(code, dev->keybit);
+               break;
+
+       case EV_REL:
+               __set_bit(code, dev->relbit);
+               break;
+
+       case EV_ABS:
+               __set_bit(code, dev->absbit);
+               break;
+
+       case EV_MSC:
+               __set_bit(code, dev->mscbit);
+               break;
+
+       case EV_SW:
+               __set_bit(code, dev->swbit);
+               break;
+
+       case EV_LED:
+               __set_bit(code, dev->ledbit);
+               break;
+
+       case EV_SND:
+               __set_bit(code, dev->sndbit);
+               break;
+
+       case EV_FF:
+               __set_bit(code, dev->ffbit);
+               break;
+
+       default:
+               printk(KERN_ERR
+                       "input_set_capability: unknown type %u (code %u)\n",
+                       type, code);
+               dump_stack();
+               return;
+       }
+
+       __set_bit(type, dev->evbit);
+}
+EXPORT_SYMBOL(input_set_capability);
+
 int input_register_device(struct input_dev *dev)
 {
        static atomic_t input_no = ATOMIC_INIT(0);
-       struct input_handle *handle;
        struct input_handler *handler;
-       const struct input_device_id *id;
        const char *path;
        int error;
 
@@ -969,55 +1124,41 @@ int input_register_device(struct input_dev *dev)
                dev->rep[REP_PERIOD] = 33;
        }
 
+       if (!dev->getkeycode)
+               dev->getkeycode = input_default_getkeycode;
+
+       if (!dev->setkeycode)
+               dev->setkeycode = input_default_setkeycode;
+
        list_add_tail(&dev->node, &input_dev_list);
 
        snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),
                 "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
 
+       if (!dev->cdev.dev)
+               dev->cdev.dev = dev->dev.parent;
+
        error = class_device_add(&dev->cdev);
        if (error)
                return error;
 
-       error = sysfs_create_group(&dev->cdev.kobj, &input_dev_attr_group);
-       if (error)
-               goto fail1;
-
-       error = sysfs_create_group(&dev->cdev.kobj, &input_dev_id_attr_group);
-       if (error)
-               goto fail2;
-
-       error = sysfs_create_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
-       if (error)
-               goto fail3;
-
        path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
        printk(KERN_INFO "input: %s as %s\n",
                dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
        kfree(path);
 
        list_for_each_entry(handler, &input_handler_list, node)
-               if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
-                       if ((id = input_match_device(handler->id_table, dev)))
-                               if ((handle = handler->connect(handler, dev, id))) {
-                                       input_link_handle(handle);
-                                       if (handler->start)
-                                               handler->start(handle);
-                               }
+               input_attach_handler(dev, handler);
 
        input_wakeup_procfs_readers();
 
        return 0;
-
- fail3:        sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);
- fail2:        sysfs_remove_group(&dev->cdev.kobj, &input_dev_attr_group);
- fail1:        class_device_del(&dev->cdev);
-       return error;
 }
 EXPORT_SYMBOL(input_register_device);
 
 void input_unregister_device(struct input_dev *dev)
 {
-       struct list_head *node, *next;
+       struct input_handle *handle, *next;
        int code;
 
        for (code = 0; code <= KEY_MAX; code++)
@@ -1027,19 +1168,12 @@ void input_unregister_device(struct input_dev *dev)
 
        del_timer_sync(&dev->timer);
 
-       list_for_each_safe(node, next, &dev->h_list) {
-               struct input_handle * handle = to_handle(node);
-               list_del_init(&handle->d_node);
-               list_del_init(&handle->h_node);
+       list_for_each_entry_safe(handle, next, &dev->h_list, d_node)
                handle->handler->disconnect(handle);
-       }
+       WARN_ON(!list_empty(&dev->h_list));
 
        list_del_init(&dev->node);
 
-       sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
-       sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);
-       sysfs_remove_group(&dev->cdev.kobj, &input_dev_attr_group);
-
        class_device_unregister(&dev->cdev);
 
        input_wakeup_procfs_readers();
@@ -1049,8 +1183,6 @@ EXPORT_SYMBOL(input_unregister_device);
 int input_register_handler(struct input_handler *handler)
 {
        struct input_dev *dev;
-       struct input_handle *handle;
-       const struct input_device_id *id;
 
        INIT_LIST_HEAD(&handler->h_list);
 
@@ -1064,13 +1196,7 @@ int input_register_handler(struct input_handler *handler)
        list_add_tail(&handler->node, &input_handler_list);
 
        list_for_each_entry(dev, &input_dev_list, node)
-               if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
-                       if ((id = input_match_device(handler->id_table, dev)))
-                               if ((handle = handler->connect(handler, dev, id))) {
-                                       input_link_handle(handle);
-                                       if (handler->start)
-                                               handler->start(handle);
-                               }
+               input_attach_handler(dev, handler);
 
        input_wakeup_procfs_readers();
        return 0;
@@ -1079,14 +1205,11 @@ EXPORT_SYMBOL(input_register_handler);
 
 void input_unregister_handler(struct input_handler *handler)
 {
-       struct list_head *node, *next;
+       struct input_handle *handle, *next;
 
-       list_for_each_safe(node, next, &handler->h_list) {
-               struct input_handle * handle = to_handle_h(node);
-               list_del_init(&handle->h_node);
-               list_del_init(&handle->d_node);
+       list_for_each_entry_safe(handle, next, &handler->h_list, h_node)
                handler->disconnect(handle);
-       }
+       WARN_ON(!list_empty(&handler->h_list));
 
        list_del_init(&handler->node);
 
@@ -1097,6 +1220,27 @@ void input_unregister_handler(struct input_handler *handler)
 }
 EXPORT_SYMBOL(input_unregister_handler);
 
+int input_register_handle(struct input_handle *handle)
+{
+       struct input_handler *handler = handle->handler;
+
+       list_add_tail(&handle->d_node, &handle->dev->h_list);
+       list_add_tail(&handle->h_node, &handler->h_list);
+
+       if (handler->start)
+               handler->start(handle);
+
+       return 0;
+}
+EXPORT_SYMBOL(input_register_handle);
+
+void input_unregister_handle(struct input_handle *handle)
+{
+       list_del_init(&handle->h_node);
+       list_del_init(&handle->d_node);
+}
+EXPORT_SYMBOL(input_unregister_handle);
+
 static int input_open_file(struct inode *inode, struct file *file)
 {
        struct input_handler *handler = input_table[iminor(inode) >> 5];
index 9f3529a..9bcc542 100644 (file)
@@ -43,7 +43,7 @@ struct joydev {
        char name[16];
        struct input_handle handle;
        wait_queue_head_t wait;
-       struct list_head list;
+       struct list_head client_list;
        struct js_corr corr[ABS_MAX + 1];
        struct JS_DATA_SAVE_TYPE glue;
        int nabs;
@@ -55,7 +55,7 @@ struct joydev {
        __s16 abs[ABS_MAX + 1];
 };
 
-struct joydev_list {
+struct joydev_client {
        struct js_event buffer[JOYDEV_BUFFER_SIZE];
        int head;
        int tail;
@@ -87,7 +87,7 @@ static int joydev_correct(int value, struct js_corr *corr)
 static void joydev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
 {
        struct joydev *joydev = handle->private;
-       struct joydev_list *list;
+       struct joydev_client *client;
        struct js_event event;
 
        switch (type) {
@@ -115,15 +115,15 @@ static void joydev_event(struct input_handle *handle, unsigned int type, unsigne
 
        event.time = jiffies_to_msecs(jiffies);
 
-       list_for_each_entry(list, &joydev->list, node) {
+       list_for_each_entry(client, &joydev->client_list, node) {
 
-               memcpy(list->buffer + list->head, &event, sizeof(struct js_event));
+               memcpy(client->buffer + client->head, &event, sizeof(struct js_event));
 
-               if (list->startup == joydev->nabs + joydev->nkey)
-                       if (list->tail == (list->head = (list->head + 1) & (JOYDEV_BUFFER_SIZE - 1)))
-                               list->startup = 0;
+               if (client->startup == joydev->nabs + joydev->nkey)
+                       if (client->tail == (client->head = (client->head + 1) & (JOYDEV_BUFFER_SIZE - 1)))
+                               client->startup = 0;
 
-               kill_fasync(&list->fasync, SIGIO, POLL_IN);
+               kill_fasync(&client->fasync, SIGIO, POLL_IN);
        }
 
        wake_up_interruptible(&joydev->wait);
@@ -132,9 +132,9 @@ static void joydev_event(struct input_handle *handle, unsigned int type, unsigne
 static int joydev_fasync(int fd, struct file *file, int on)
 {
        int retval;
-       struct joydev_list *list = file->private_data;
+       struct joydev_client *client = file->private_data;
 
-       retval = fasync_helper(fd, file, on, &list->fasync);
+       retval = fasync_helper(fd, file, on, &client->fasync);
 
        return retval < 0 ? retval : 0;
 }
@@ -145,60 +145,73 @@ static void joydev_free(struct joydev *joydev)
        kfree(joydev);
 }
 
-static int joydev_release(struct inode * inode, struct file * file)
+static int joydev_release(struct inode *inode, struct file *file)
 {
-       struct joydev_list *list = file->private_data;
+       struct joydev_client *client = file->private_data;
+       struct joydev *joydev = client->joydev;
 
        joydev_fasync(-1, file, 0);
 
-       list_del(&list->node);
+       list_del(&client->node);
+       kfree(client);
 
-       if (!--list->joydev->open) {
-               if (list->joydev->exist)
-                       input_close_device(&list->joydev->handle);
+       if (!--joydev->open) {
+               if (joydev->exist)
+                       input_close_device(&joydev->handle);
                else
-                       joydev_free(list->joydev);
+                       joydev_free(joydev);
        }
 
-       kfree(list);
        return 0;
 }
 
 static int joydev_open(struct inode *inode, struct file *file)
 {
-       struct joydev_list *list;
+       struct joydev_client *client;
+       struct joydev *joydev;
        int i = iminor(inode) - JOYDEV_MINOR_BASE;
+       int error;
+
+       if (i >= JOYDEV_MINORS)
+               return -ENODEV;
 
-       if (i >= JOYDEV_MINORS || !joydev_table[i])
+       joydev = joydev_table[i];
+       if (!joydev || !joydev->exist)
                return -ENODEV;
 
-       if (!(list = kzalloc(sizeof(struct joydev_list), GFP_KERNEL)))
+       client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL);
+       if (!client)
                return -ENOMEM;
 
-       list->joydev = joydev_table[i];
-       list_add_tail(&list->node, &joydev_table[i]->list);
-       file->private_data = list;
+       client->joydev = joydev;
+       list_add_tail(&client->node, &joydev->client_list);
 
-       if (!list->joydev->open++)
-               if (list->joydev->exist)
-                       input_open_device(&list->joydev->handle);
+       if (!joydev->open++ && joydev->exist) {
+               error = input_open_device(&joydev->handle);
+               if (error) {
+                       list_del(&client->node);
+                       kfree(client);
+                       return error;
+               }
+       }
 
+       file->private_data = client;
        return 0;
 }
 
-static ssize_t joydev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
+static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
        return -EINVAL;
 }
 
 static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
-       struct joydev_list *list = file->private_data;
-       struct joydev *joydev = list->joydev;
+       struct joydev_client *client = file->private_data;
+       struct joydev *joydev = client->joydev;
        struct input_dev *input = joydev->handle.dev;
        int retval = 0;
 
-       if (!list->joydev->exist)
+       if (!joydev->exist)
                return -ENODEV;
 
        if (count < sizeof(struct js_event))
@@ -217,56 +230,55 @@ static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, lo
                if (copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE)))
                        return -EFAULT;
 
-               list->startup = 0;
-               list->tail = list->head;
+               client->startup = 0;
+               client->tail = client->head;
 
                return sizeof(struct JS_DATA_TYPE);
        }
 
-       if (list->startup == joydev->nabs + joydev->nkey &&
-           list->head == list->tail && (file->f_flags & O_NONBLOCK))
+       if (client->startup == joydev->nabs + joydev->nkey &&
+           client->head == client->tail && (file->f_flags & O_NONBLOCK))
                return -EAGAIN;
 
-       retval = wait_event_interruptible(list->joydev->wait,
-                                         !list->joydev->exist ||
-                                         list->startup < joydev->nabs + joydev->nkey ||
-                                         list->head != list->tail);
-
+       retval = wait_event_interruptible(joydev->wait,
+                                         !joydev->exist ||
+                                         client->startup < joydev->nabs + joydev->nkey ||
+                                         client->head != client->tail);
        if (retval)
                return retval;
 
-       if (!list->joydev->exist)
+       if (!joydev->exist)
                return -ENODEV;
 
-       while (list->startup < joydev->nabs + joydev->nkey && retval + sizeof(struct js_event) <= count) {
+       while (client->startup < joydev->nabs + joydev->nkey && retval + sizeof(struct js_event) <= count) {
 
                struct js_event event;
 
                event.time = jiffies_to_msecs(jiffies);
 
-               if (list->startup < joydev->nkey) {
+               if (client->startup < joydev->nkey) {
                        event.type = JS_EVENT_BUTTON | JS_EVENT_INIT;
-                       event.number = list->startup;
+                       event.number = client->startup;
                        event.value = !!test_bit(joydev->keypam[event.number], input->key);
                } else {
                        event.type = JS_EVENT_AXIS | JS_EVENT_INIT;
-                       event.number = list->startup - joydev->nkey;
+                       event.number = client->startup - joydev->nkey;
                        event.value = joydev->abs[event.number];
                }
 
                if (copy_to_user(buf + retval, &event, sizeof(struct js_event)))
                        return -EFAULT;
 
-               list->startup++;
+               client->startup++;
                retval += sizeof(struct js_event);
        }
 
-       while (list->head != list->tail && retval + sizeof(struct js_event) <= count) {
+       while (client->head != client->tail && retval + sizeof(struct js_event) <= count) {
 
-               if (copy_to_user(buf + retval, list->buffer + list->tail, sizeof(struct js_event)))
+               if (copy_to_user(buf + retval, client->buffer + client->tail, sizeof(struct js_event)))
                        return -EFAULT;
 
-               list->tail = (list->tail + 1) & (JOYDEV_BUFFER_SIZE - 1);
+               client->tail = (client->tail + 1) & (JOYDEV_BUFFER_SIZE - 1);
                retval += sizeof(struct js_event);
        }
 
@@ -276,11 +288,12 @@ static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, lo
 /* No kernel lock - fine */
 static unsigned int joydev_poll(struct file *file, poll_table *wait)
 {
-       struct joydev_list *list = file->private_data;
+       struct joydev_client *client = file->private_data;
+       struct joydev *joydev = client->joydev;
 
-       poll_wait(file, &list->joydev->wait, wait);
-       return ((list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey) ?
-               (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR));
+       poll_wait(file, &joydev->wait, wait);
+       return ((client->head != client->tail || client->startup < joydev->nabs + joydev->nkey) ?
+               (POLLIN | POLLRDNORM) : 0) | (joydev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
 static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __user *argp)
@@ -374,8 +387,8 @@ static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __u
 #ifdef CONFIG_COMPAT
 static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       struct joydev_list *list = file->private_data;
-       struct joydev *joydev = list->joydev;
+       struct joydev_client *client = file->private_data;
+       struct joydev *joydev = client->joydev;
        void __user *argp = (void __user *)arg;
        s32 tmp32;
        struct JS_DATA_SAVE_TYPE_32 ds32;
@@ -428,8 +441,8 @@ static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned lo
 
 static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
-       struct joydev_list *list = file->private_data;
-       struct joydev *joydev = list->joydev;
+       struct joydev_client *client = file->private_data;
+       struct joydev *joydev = client->joydev;
        void __user *argp = (void __user *)arg;
 
        if (!joydev->exist)
@@ -465,23 +478,26 @@ static const struct file_operations joydev_fops = {
        .fasync =       joydev_fasync,
 };
 
-static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev,
-                                          const struct input_device_id *id)
+static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
+                         const struct input_device_id *id)
 {
        struct joydev *joydev;
        struct class_device *cdev;
+       dev_t devt;
        int i, j, t, minor;
+       int error;
 
        for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
        if (minor == JOYDEV_MINORS) {
                printk(KERN_ERR "joydev: no more free joydev devices\n");
-               return NULL;
+               return -ENFILE;
        }
 
-       if (!(joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL)))
-               return NULL;
+       joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL);
+       if (!joydev)
+               return -ENOMEM;
 
-       INIT_LIST_HEAD(&joydev->list);
+       INIT_LIST_HEAD(&joydev->client_list);
        init_waitqueue_head(&joydev->wait);
 
        joydev->minor = minor;
@@ -534,31 +550,54 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
 
        joydev_table[minor] = joydev;
 
-       cdev = class_device_create(&input_class, &dev->cdev,
-                       MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
-                       dev->cdev.dev, joydev->name);
+       devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
+
+       cdev = class_device_create(&input_class, &dev->cdev, devt,
+                                  dev->cdev.dev, joydev->name);
+       if (IS_ERR(cdev)) {
+               error = PTR_ERR(cdev);
+               goto err_free_joydev;
+       }
 
        /* temporary symlink to keep userspace happy */
-       sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
-                         joydev->name);
+       error = sysfs_create_link(&input_class.subsys.kobj,
+                                 &cdev->kobj, joydev->name);
+       if (error)
+               goto err_cdev_destroy;
+
+       error = input_register_handle(&joydev->handle);
+       if (error)
+               goto err_remove_link;
+
+       return 0;
 
-       return &joydev->handle;
+ err_remove_link:
+       sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
+ err_cdev_destroy:
+       class_device_destroy(&input_class, devt);
+ err_free_joydev:
+       joydev_table[minor] = NULL;
+       kfree(joydev);
+       return error;
 }
 
+
 static void joydev_disconnect(struct input_handle *handle)
 {
        struct joydev *joydev = handle->private;
-       struct joydev_list *list;
+       struct joydev_client *client;
+
+       input_unregister_handle(handle);
 
-       sysfs_remove_link(&input_class.subsys.kset.kobj, joydev->name);
+       sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
        class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
        joydev->exist = 0;
 
        if (joydev->open) {
                input_close_device(handle);
                wake_up_interruptible(&joydev->wait);
-               list_for_each_entry(list, &joydev->list, node)
-                       kill_fasync(&list->fasync, SIGIO, POLL_HUP);
+               list_for_each_entry(client, &joydev->client_list, node)
+                       kill_fasync(&client->fasync, SIGIO, POLL_HUP);
        } else
                joydev_free(joydev);
 }
index b11a4bb..ff701ab 100644 (file)
@@ -241,7 +241,7 @@ static void a3d_adc_close(struct gameport *gameport)
 
 static int a3d_open(struct input_dev *dev)
 {
-       struct a3d *a3d = dev->private;
+       struct a3d *a3d = input_get_drvdata(dev);
 
        gameport_start_polling(a3d->gameport);
        return 0;
@@ -253,7 +253,7 @@ static int a3d_open(struct input_dev *dev)
 
 static void a3d_close(struct input_dev *dev)
 {
-       struct a3d *a3d = dev->private;
+       struct a3d *a3d = input_get_drvdata(dev);
 
        gameport_stop_polling(a3d->gameport);
 }
@@ -314,11 +314,12 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
        input_dev->id.vendor = GAMEPORT_ID_VENDOR_MADCATZ;
        input_dev->id.product = a3d->mode;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &gameport->dev;
-       input_dev->private = a3d;
+       input_dev->dev.parent = &gameport->dev;
        input_dev->open = a3d_open;
        input_dev->close = a3d_close;
 
+       input_set_drvdata(input_dev, a3d);
+
        if (a3d->mode == A3D_MODE_PXL) {
 
                int axes[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER };
index 6279ced..28140c4 100644 (file)
@@ -290,7 +290,7 @@ static void adi_poll(struct gameport *gameport)
 
 static int adi_open(struct input_dev *dev)
 {
-       struct adi_port *port = dev->private;
+       struct adi_port *port = input_get_drvdata(dev);
 
        gameport_start_polling(port->gameport);
        return 0;
@@ -302,7 +302,7 @@ static int adi_open(struct input_dev *dev)
 
 static void adi_close(struct input_dev *dev)
 {
-       struct adi_port *port = dev->private;
+       struct adi_port *port = input_get_drvdata(dev);
 
        gameport_stop_polling(port->gameport);
 }
@@ -424,8 +424,9 @@ static int adi_init_input(struct adi *adi, struct adi_port *port, int half)
        input_dev->id.vendor = GAMEPORT_ID_VENDOR_LOGITECH;
        input_dev->id.product = adi->id;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &port->gameport->dev;
-       input_dev->private = port;
+       input_dev->dev.parent = &port->gameport->dev;
+
+       input_set_drvdata(input_dev, port);
 
        input_dev->open = adi_open;
        input_dev->close = adi_close;
index 51f1e4b..1c1afb5 100644 (file)
@@ -343,7 +343,7 @@ static void analog_poll(struct gameport *gameport)
 
 static int analog_open(struct input_dev *dev)
 {
-       struct analog_port *port = dev->private;
+       struct analog_port *port = input_get_drvdata(dev);
 
        gameport_start_polling(port->gameport);
        return 0;
@@ -355,7 +355,7 @@ static int analog_open(struct input_dev *dev)
 
 static void analog_close(struct input_dev *dev)
 {
-       struct analog_port *port = dev->private;
+       struct analog_port *port = input_get_drvdata(dev);
 
        gameport_stop_polling(port->gameport);
 }
@@ -449,10 +449,13 @@ static int analog_init_device(struct analog_port *port, struct analog *analog, i
        input_dev->id.vendor = GAMEPORT_ID_VENDOR_ANALOG;
        input_dev->id.product = analog->mask >> 4;
        input_dev->id.version = 0x0100;
+       input_dev->dev.parent = &port->gameport->dev;
+
+       input_set_drvdata(input_dev, port);
 
        input_dev->open = analog_open;
        input_dev->close = analog_close;
-       input_dev->private = port;
+
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
        for (i = j = 0; i < 4; i++)
index 034ec39..d3352a8 100644 (file)
@@ -142,7 +142,7 @@ static void cobra_poll(struct gameport *gameport)
 
 static int cobra_open(struct input_dev *dev)
 {
-       struct cobra *cobra = dev->private;
+       struct cobra *cobra = input_get_drvdata(dev);
 
        gameport_start_polling(cobra->gameport);
        return 0;
@@ -150,7 +150,7 @@ static int cobra_open(struct input_dev *dev)
 
 static void cobra_close(struct input_dev *dev)
 {
-       struct cobra *cobra = dev->private;
+       struct cobra *cobra = input_get_drvdata(dev);
 
        gameport_stop_polling(cobra->gameport);
 }
@@ -211,8 +211,9 @@ static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
                input_dev->id.vendor = GAMEPORT_ID_VENDOR_CREATIVE;
                input_dev->id.product = 0x0008;
                input_dev->id.version = 0x0100;
-               input_dev->cdev.dev = &gameport->dev;
-               input_dev->private = cobra;
+               input_dev->dev.parent = &gameport->dev;
+
+               input_set_drvdata(input_dev, cobra);
 
                input_dev->open = cobra_open;
                input_dev->close = cobra_close;
index b41bd2e..c27593b 100644 (file)
@@ -518,7 +518,7 @@ static void db9_timer(unsigned long private)
 
 static int db9_open(struct input_dev *dev)
 {
-       struct db9 *db9 = dev->private;
+       struct db9 *db9 = input_get_drvdata(dev);
        struct parport *port = db9->pd->port;
        int err;
 
@@ -542,7 +542,7 @@ static int db9_open(struct input_dev *dev)
 
 static void db9_close(struct input_dev *dev)
 {
-       struct db9 *db9 = dev->private;
+       struct db9 *db9 = input_get_drvdata(dev);
        struct parport *port = db9->pd->port;
 
        mutex_lock(&db9->mutex);
@@ -625,7 +625,8 @@ static struct db9 __init *db9_probe(int parport, int mode)
                input_dev->id.vendor = 0x0002;
                input_dev->id.product = mode;
                input_dev->id.version = 0x0100;
-               input_dev->private = db9;
+
+               input_set_drvdata(input_dev, db9);
 
                input_dev->open = db9_open;
                input_dev->close = db9_close;
index 711e4b3..c71b58f 100644 (file)
@@ -591,7 +591,7 @@ static void gc_timer(unsigned long private)
 
 static int gc_open(struct input_dev *dev)
 {
-       struct gc *gc = dev->private;
+       struct gc *gc = input_get_drvdata(dev);
        int err;
 
        err = mutex_lock_interruptible(&gc->mutex);
@@ -610,7 +610,7 @@ static int gc_open(struct input_dev *dev)
 
 static void gc_close(struct input_dev *dev)
 {
-       struct gc *gc = dev->private;
+       struct gc *gc = input_get_drvdata(dev);
 
        mutex_lock(&gc->mutex);
        if (!--gc->used) {
@@ -646,7 +646,8 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
        input_dev->id.vendor = 0x0001;
        input_dev->id.product = pad_type;
        input_dev->id.version = 0x0100;
-       input_dev->private = gc;
+
+       input_set_drvdata(input_dev, gc);
 
        input_dev->open = gc_open;
        input_dev->close = gc_close;
index bacbab5..d514aeb 100644 (file)
@@ -220,7 +220,7 @@ static void gf2k_poll(struct gameport *gameport)
 
 static int gf2k_open(struct input_dev *dev)
 {
-       struct gf2k *gf2k = dev->private;
+       struct gf2k *gf2k = input_get_drvdata(dev);
 
        gameport_start_polling(gf2k->gameport);
        return 0;
@@ -228,7 +228,7 @@ static int gf2k_open(struct input_dev *dev)
 
 static void gf2k_close(struct input_dev *dev)
 {
-       struct gf2k *gf2k = dev->private;
+       struct gf2k *gf2k = input_get_drvdata(dev);
 
        gameport_stop_polling(gf2k->gameport);
 }
@@ -308,11 +308,13 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
        input_dev->id.vendor = GAMEPORT_ID_VENDOR_GENIUS;
        input_dev->id.product = gf2k->id;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &gameport->dev;
-       input_dev->private = gf2k;
+       input_dev->dev.parent = &gameport->dev;
+
+       input_set_drvdata(input_dev, gf2k);
 
        input_dev->open = gf2k_open;
        input_dev->close = gf2k_close;
+
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
        for (i = 0; i < gf2k_axes[gf2k->id]; i++)
index 17a90c4..73eb5ab 100644 (file)
@@ -285,7 +285,7 @@ static void grip_poll(struct gameport *gameport)
 
 static int grip_open(struct input_dev *dev)
 {
-       struct grip *grip = dev->private;
+       struct grip *grip = input_get_drvdata(dev);
 
        gameport_start_polling(grip->gameport);
        return 0;
@@ -293,7 +293,7 @@ static int grip_open(struct input_dev *dev)
 
 static void grip_close(struct input_dev *dev)
 {
-       struct grip *grip = dev->private;
+       struct grip *grip = input_get_drvdata(dev);
 
        gameport_stop_polling(grip->gameport);
 }
@@ -363,8 +363,9 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
                input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
                input_dev->id.product = grip->mode[i];
                input_dev->id.version = 0x0100;
-               input_dev->cdev.dev = &gameport->dev;
-               input_dev->private = grip;
+               input_dev->dev.parent = &gameport->dev;
+
+               input_set_drvdata(input_dev, grip);
 
                input_dev->open = grip_open;
                input_dev->close = grip_close;
index 8120a9c..555319e 100644 (file)
@@ -562,7 +562,7 @@ static void grip_poll(struct gameport *gameport)
 
 static int grip_open(struct input_dev *dev)
 {
-       struct grip_mp *grip = dev->private;
+       struct grip_mp *grip = input_get_drvdata(dev);
 
        gameport_start_polling(grip->gameport);
        return 0;
@@ -574,9 +574,9 @@ static int grip_open(struct input_dev *dev)
 
 static void grip_close(struct input_dev *dev)
 {
-       struct grip_mp *grip = dev->private;
+       struct grip_mp *grip = input_get_drvdata(dev);
 
-       gameport_start_polling(grip->gameport);
+       gameport_stop_polling(grip->gameport);
 }
 
 /*
@@ -599,8 +599,9 @@ static int register_slot(int slot, struct grip_mp *grip)
        input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
        input_dev->id.product = 0x0100 + port->mode;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &grip->gameport->dev;
-       input_dev->private = grip;
+       input_dev->dev.parent = &grip->gameport->dev;
+
+       input_set_drvdata(input_dev, grip);
 
        input_dev->open = grip_open;
        input_dev->close = grip_close;
index dbc5d92..d4e8073 100644 (file)
@@ -156,7 +156,7 @@ static void guillemot_poll(struct gameport *gameport)
 
 static int guillemot_open(struct input_dev *dev)
 {
-       struct guillemot *guillemot = dev->private;
+       struct guillemot *guillemot = input_get_drvdata(dev);
 
        gameport_start_polling(guillemot->gameport);
        return 0;
@@ -168,7 +168,7 @@ static int guillemot_open(struct input_dev *dev)
 
 static void guillemot_close(struct input_dev *dev)
 {
-       struct guillemot *guillemot = dev->private;
+       struct guillemot *guillemot = input_get_drvdata(dev);
 
        gameport_stop_polling(guillemot->gameport);
 }
@@ -231,8 +231,9 @@ static int guillemot_connect(struct gameport *gameport, struct gameport_driver *
        input_dev->id.vendor = GAMEPORT_ID_VENDOR_GUILLEMOT;
        input_dev->id.product = guillemot_type[i].id;
        input_dev->id.version = (int)data[14] << 8 | data[15];
-       input_dev->cdev.dev = &gameport->dev;
-       input_dev->private = guillemot;
+       input_dev->dev.parent = &gameport->dev;
+
+       input_set_drvdata(input_dev, guillemot);
 
        input_dev->open = guillemot_open;
        input_dev->close = guillemot_close;
index 8fb0c19..f2a4381 100644 (file)
@@ -2,7 +2,7 @@
  * $Id: iforce-ff.c,v 1.9 2002/02/02 19:28:35 jdeneux Exp $
  *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
- *  Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
+ *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
  *  USB/RS232 I-Force joysticks and wheels.
  */
@@ -205,7 +205,7 @@ static int need_condition_modifier(struct ff_effect *old, struct ff_effect *new)
        int i;
 
        if (new->type != FF_SPRING && new->type != FF_FRICTION) {
-               printk(KERN_WARNING "iforce.c: bad effect type in need_condition_modifier\n");
+               warn("bad effect type in need_condition_modifier");
                return 0;
        }
 
@@ -227,7 +227,7 @@ static int need_condition_modifier(struct ff_effect *old, struct ff_effect *new)
 static int need_magnitude_modifier(struct ff_effect *old, struct ff_effect *effect)
 {
        if (effect->type != FF_CONSTANT) {
-               printk(KERN_WARNING "iforce.c: bad effect type in need_envelope_modifier\n");
+               warn("bad effect type in need_envelope_modifier");
                return 0;
        }
 
@@ -258,7 +258,7 @@ static int need_envelope_modifier(struct ff_effect *old, struct ff_effect *effec
                break;
 
        default:
-               printk(KERN_WARNING "iforce.c: bad effect type in need_envelope_modifier\n");
+               warn("bad effect type in need_envelope_modifier");
        }
 
        return 0;
@@ -271,7 +271,7 @@ static int need_envelope_modifier(struct ff_effect *old, struct ff_effect *effec
 static int need_period_modifier(struct ff_effect *old, struct ff_effect *new)
 {
        if (new->type != FF_PERIODIC) {
-               printk(KERN_WARNING "iforce.c: bad effect type in need_period_modifier\n");
+               warn("bad effect type in need_period_modifier");
                return 0;
        }
        return (old->u.periodic.period != new->u.periodic.period
index 3393a37..fb129c4 100644 (file)
@@ -2,7 +2,7 @@
  * $Id: iforce-main.c,v 1.19 2002/07/07 10:22:50 jdeneux Exp $
  *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
- *  Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
+ *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
  *  USB/RS232 I-Force joysticks and wheels.
  */
@@ -29,7 +29,7 @@
 
 #include "iforce.h"
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <deneux@ifrance.com>");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <johann.deneux@gmail.com>");
 MODULE_DESCRIPTION("USB/RS232 I-Force joysticks and wheels driver");
 MODULE_LICENSE("GPL");
 
@@ -220,7 +220,7 @@ static void iforce_release(struct input_dev *dev)
                /* Check: no effects should be present in memory */
                for (i = 0; i < dev->ff->max_effects; i++) {
                        if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags)) {
-                               printk(KERN_WARNING "iforce_release: Device still owns effects\n");
+                               warn("iforce_release: Device still owns effects");
                                break;
                        }
                }
@@ -232,7 +232,7 @@ static void iforce_release(struct input_dev *dev)
        switch (iforce->bus) {
 #ifdef CONFIG_JOYSTICK_IFORCE_USB
                case IFORCE_USB:
-                       usb_unlink_urb(iforce->irq);
+                       usb_kill_urb(iforce->irq);
 
                        /* The device was unplugged before the file
                         * was released */
@@ -287,13 +287,13 @@ int iforce_init_device(struct iforce *iforce)
 #ifdef CONFIG_JOYSTICK_IFORCE_USB
        case IFORCE_USB:
                input_dev->id.bustype = BUS_USB;
-               input_dev->cdev.dev = &iforce->usbdev->dev;
+               input_dev->dev.parent = &iforce->usbdev->dev;
                break;
 #endif
 #ifdef CONFIG_JOYSTICK_IFORCE_232
        case IFORCE_232:
                input_dev->id.bustype = BUS_RS232;
-               input_dev->cdev.dev = &iforce->serio->dev;
+               input_dev->dev.parent = &iforce->serio->dev;
                break;
 #endif
        }
@@ -324,7 +324,7 @@ int iforce_init_device(struct iforce *iforce)
                        break;
 
        if (i == 20) { /* 5 seconds */
-               printk(KERN_ERR "iforce-main.c: Timeout waiting for response from device.\n");
+               err("Timeout waiting for response from device.");
                error = -ENODEV;
                goto fail;
        }
@@ -336,26 +336,26 @@ int iforce_init_device(struct iforce *iforce)
        if (!iforce_get_id_packet(iforce, "M"))
                input_dev->id.vendor = (iforce->edata[2] << 8) | iforce->edata[1];
        else
-               printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet M\n");
+               warn("Device does not respond to id packet M");
 
        if (!iforce_get_id_packet(iforce, "P"))
                input_dev->id.product = (iforce->edata[2] << 8) | iforce->edata[1];
        else
-               printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet P\n");
+               warn("Device does not respond to id packet P");
 
        if (!iforce_get_id_packet(iforce, "B"))
                iforce->device_memory.end = (iforce->edata[2] << 8) | iforce->edata[1];
        else
-               printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet B\n");
+               warn("Device does not respond to id packet B");
 
        if (!iforce_get_id_packet(iforce, "N"))
                ff_effects = iforce->edata[1];
        else
-               printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet N\n");
+               warn("Device does not respond to id packet N");
 
        /* Check if the device can store more effects than the driver can really handle */
        if (ff_effects > IFORCE_EFFECTS_MAX) {
-               printk(KERN_WARNING "iforce: Limiting number of effects to %d (device reports %d)\n",
+               warn("Limiting number of effects to %d (device reports %d)",
                       IFORCE_EFFECTS_MAX, ff_effects);
                ff_effects = IFORCE_EFFECTS_MAX;
        }
@@ -457,8 +457,6 @@ int iforce_init_device(struct iforce *iforce)
        if (error)
                goto fail;
 
-       printk(KERN_DEBUG "iforce->dev->open = %p\n", iforce->dev->open);
-
        return 0;
 
  fail: input_free_device(input_dev);
index 808f059..21c4e13 100644 (file)
@@ -2,7 +2,7 @@
  * $Id: iforce-packets.c,v 1.16 2002/07/07 10:22:50 jdeneux Exp $
  *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
- *  Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
+ *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
  *  USB/RS232 I-Force joysticks and wheels.
  */
@@ -39,10 +39,10 @@ void iforce_dump_packet(char *msg, u16 cmd, unsigned char *data)
 {
        int i;
 
-       printk(KERN_DEBUG "iforce.c: %s ( cmd = %04x, data = ", msg, cmd);
+       printk(KERN_DEBUG __FILE__ ": %s cmd = %04x, data = ", msg, cmd);
        for (i = 0; i < LO(cmd); i++)
                printk("%02x ", data[i]);
-       printk(")\n");
+       printk("\n");
 }
 
 /*
@@ -65,8 +65,9 @@ int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data)
        head = iforce->xmit.head;
        tail = iforce->xmit.tail;
 
+
        if (CIRC_SPACE(head, tail, XMIT_SIZE) < n+2) {
-               printk(KERN_WARNING "iforce.c: not enough space in xmit buffer to send new packet\n");
+               warn("not enough space in xmit buffer to send new packet");
                spin_unlock_irqrestore(&iforce->xmit_lock, flags);
                return -1;
        }
@@ -126,8 +127,6 @@ int iforce_control_playback(struct iforce* iforce, u16 id, unsigned int value)
 {
        unsigned char data[3];
 
-printk(KERN_DEBUG "iforce-packets.c: control_playback %d %d\n", id, value);
-
        data[0] = LO(id);
        data[1] = (value > 0) ? ((value > 1) ? 0x41 : 0x01) : 0;
        data[2] = LO(value);
@@ -151,7 +150,7 @@ static int mark_core_as_ready(struct iforce *iforce, unsigned short addr)
                        return 0;
                }
        }
-       printk(KERN_WARNING "iforce-packets.c: unused effect %04x updated !!!\n", addr);
+       warn("unused effect %04x updated !!!", addr);
        return -1;
 }
 
@@ -162,7 +161,7 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data)
        static int being_used = 0;
 
        if (being_used)
-               printk(KERN_WARNING "iforce-packets.c: re-entrant call to iforce_process %d\n", being_used);
+               warn("re-entrant call to iforce_process %d", being_used);
        being_used++;
 
 #ifdef CONFIG_JOYSTICK_IFORCE_232
@@ -266,7 +265,7 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
                        return -1;
                }
 #else
-               printk(KERN_ERR "iforce_get_id_packet: iforce->bus = USB!\n");
+               err("iforce_get_id_packet: iforce->bus = USB!");
 #endif
                break;
 
@@ -284,13 +283,12 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
                        return -1;
                }
 #else
-               printk(KERN_ERR "iforce_get_id_packet: iforce->bus = SERIO!\n");
+               err("iforce_get_id_packet: iforce->bus = SERIO!");
 #endif
                break;
 
        default:
-               printk(KERN_ERR "iforce_get_id_packet: iforce->bus = %d\n",
-                      iforce->bus);
+               err("iforce_get_id_packet: iforce->bus = %d", iforce->bus);
                break;
        }
 
index ec4be53..7b4bc19 100644 (file)
@@ -2,7 +2,7 @@
  * $Id: iforce-serio.c,v 1.4 2002/01/28 22:45:00 jdeneux Exp $
  *
  *  Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz>
- *  Copyright (c) 2001 Johann Deneux <deneux@ifrance.com>
+ *  Copyright (c) 2001, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
  *  USB/RS232 I-Force joysticks and wheels.
  */
index 80cdebc..750099d 100644 (file)
@@ -2,7 +2,7 @@
  * $Id: iforce-usb.c,v 1.16 2002/06/09 11:08:04 jdeneux Exp $
  *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
- *  Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
+ *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
  *  USB/RS232 I-Force joysticks and wheels.
  */
@@ -65,7 +65,7 @@ void iforce_usb_xmit(struct iforce *iforce)
        XMIT_INC(iforce->xmit.tail, n);
 
        if ( (n=usb_submit_urb(iforce->out, GFP_ATOMIC)) ) {
-               printk(KERN_WARNING "iforce-usb.c: iforce_usb_xmit: usb_submit_urb failed %d\n", n);
+               warn("usb_submit_urb failed %d\n", n);
        }
 
        /* The IFORCE_XMIT_RUNNING bit is not cleared here. That's intended.
@@ -110,7 +110,7 @@ static void iforce_usb_out(struct urb *urb)
        struct iforce *iforce = urb->context;
 
        if (urb->status) {
-               printk(KERN_DEBUG "iforce_usb_out: urb->status %d, exiting", urb->status);
+               dbg("urb->status %d, exiting", urb->status);
                return;
        }
 
@@ -190,10 +190,9 @@ fail:
 /* Called by iforce_delete() */
 void iforce_usb_delete(struct iforce* iforce)
 {
-       usb_unlink_urb(iforce->irq);
-/* Is it ok to unlink those ? */
-       usb_unlink_urb(iforce->out);
-       usb_unlink_urb(iforce->ctrl);
+       usb_kill_urb(iforce->irq);
+       usb_kill_urb(iforce->out);
+       usb_kill_urb(iforce->ctrl);
 
        usb_free_urb(iforce->irq);
        usb_free_urb(iforce->out);
index ffaeaef..dadcf4f 100644 (file)
@@ -2,7 +2,7 @@
  * $Id: iforce.h,v 1.13 2002/07/07 10:22:50 jdeneux Exp $
  *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
- *  Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
+ *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
  *  USB/RS232 I-Force joysticks and wheels.
  */
index fec8b3d..1aec1e9 100644 (file)
@@ -185,7 +185,7 @@ static void interact_poll(struct gameport *gameport)
 
 static int interact_open(struct input_dev *dev)
 {
-       struct interact *interact = dev->private;
+       struct interact *interact = input_get_drvdata(dev);
 
        gameport_start_polling(interact->gameport);
        return 0;
@@ -197,7 +197,7 @@ static int interact_open(struct input_dev *dev)
 
 static void interact_close(struct input_dev *dev)
 {
-       struct interact *interact = dev->private;
+       struct interact *interact = input_get_drvdata(dev);
 
        gameport_stop_polling(interact->gameport);
 }
@@ -262,7 +262,9 @@ static int interact_connect(struct gameport *gameport, struct gameport_driver *d
        input_dev->id.vendor = GAMEPORT_ID_VENDOR_INTERACT;
        input_dev->id.product = interact_type[i].id;
        input_dev->id.version = 0x0100;
-       input_dev->private = interact;
+       input_dev->dev.parent = &gameport->dev;
+
+       input_set_drvdata(input_dev, interact);
 
        input_dev->open = interact_open;
        input_dev->close = interact_close;
index 4112789..b35604e 100644 (file)
@@ -168,8 +168,7 @@ static int magellan_connect(struct serio *serio, struct serio_driver *drv)
        input_dev->id.vendor = SERIO_MAGELLAN;
        input_dev->id.product = 0x0001;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &serio->dev;
-       input_dev->private = magellan;
+       input_dev->dev.parent = &serio->dev;
 
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
index e58b22c..2adf73f 100644 (file)
@@ -509,7 +509,7 @@ static void sw_poll(struct gameport *gameport)
 
 static int sw_open(struct input_dev *dev)
 {
-       struct sw *sw = dev->private;
+       struct sw *sw = input_get_drvdata(dev);
 
        gameport_start_polling(sw->gameport);
        return 0;
@@ -517,7 +517,7 @@ static int sw_open(struct input_dev *dev)
 
 static void sw_close(struct input_dev *dev)
 {
-       struct sw *sw = dev->private;
+       struct sw *sw = input_get_drvdata(dev);
 
        gameport_stop_polling(sw->gameport);
 }
@@ -751,8 +751,9 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
                input_dev->id.vendor = GAMEPORT_ID_VENDOR_MICROSOFT;
                input_dev->id.product = sw->type;
                input_dev->id.version = 0x0100;
-               input_dev->cdev.dev = &gameport->dev;
-               input_dev->private = sw;
+               input_dev->dev.parent = &gameport->dev;
+
+               input_set_drvdata(input_dev, sw);
 
                input_dev->open = sw_open;
                input_dev->close = sw_close;
index 08bf113..abb7c4c 100644 (file)
@@ -226,8 +226,7 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv)
        input_dev->id.vendor = SERIO_SPACEBALL;
        input_dev->id.product = id;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &serio->dev;
-       input_dev->private = spaceball;
+       input_dev->dev.parent = &serio->dev;
 
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
index c9c7921..c4937f1 100644 (file)
@@ -183,8 +183,7 @@ static int spaceorb_connect(struct serio *serio, struct serio_driver *drv)
        input_dev->id.vendor = SERIO_SPACEORB;
        input_dev->id.product = 0x0001;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &serio->dev;
-       input_dev->private = spaceorb;
+       input_dev->dev.parent = &serio->dev;
 
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
index ecb0916..8581ee9 100644 (file)
@@ -154,8 +154,7 @@ static int stinger_connect(struct serio *serio, struct serio_driver *drv)
        input_dev->id.vendor = SERIO_STINGER;
        input_dev->id.product = 0x0001;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &serio->dev;
-       input_dev->private = stinger;
+       input_dev->dev.parent = &serio->dev;
 
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
        input_dev->keybit[LONG(BTN_A)] = BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_X) |
index bb23ed2..3b36ee0 100644 (file)
@@ -265,7 +265,7 @@ static void tmdc_poll(struct gameport *gameport)
 
 static int tmdc_open(struct input_dev *dev)
 {
-       struct tmdc *tmdc = dev->private;
+       struct tmdc *tmdc = input_get_drvdata(dev);
 
        gameport_start_polling(tmdc->gameport);
        return 0;
@@ -273,7 +273,7 @@ static int tmdc_open(struct input_dev *dev)
 
 static void tmdc_close(struct input_dev *dev)
 {
-       struct tmdc *tmdc = dev->private;
+       struct tmdc *tmdc = input_get_drvdata(dev);
 
        gameport_stop_polling(tmdc->gameport);
 }
@@ -326,8 +326,9 @@ static int tmdc_setup_port(struct tmdc *tmdc, int idx, unsigned char *data)
        input_dev->id.vendor = GAMEPORT_ID_VENDOR_THRUSTMASTER;
        input_dev->id.product = model->id;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &tmdc->gameport->dev;
-       input_dev->private = tmdc;
+       input_dev->dev.parent = &tmdc->gameport->dev;
+
+       input_set_drvdata(input_dev, tmdc);
 
        input_dev->open = tmdc_open;
        input_dev->close = tmdc_close;
index 037d348..0f2c608 100644 (file)
@@ -122,7 +122,7 @@ static void tgfx_timer(unsigned long private)
 
 static int tgfx_open(struct input_dev *dev)
 {
-       struct tgfx *tgfx = dev->private;
+       struct tgfx *tgfx = input_get_drvdata(dev);
        int err;
 
        err = mutex_lock_interruptible(&tgfx->sem);
@@ -141,7 +141,7 @@ static int tgfx_open(struct input_dev *dev)
 
 static void tgfx_close(struct input_dev *dev)
 {
-       struct tgfx *tgfx = dev->private;
+       struct tgfx *tgfx = input_get_drvdata(dev);
 
        mutex_lock(&tgfx->sem);
        if (!--tgfx->used) {
@@ -224,7 +224,8 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
                input_dev->id.product = n_buttons[i];
                input_dev->id.version = 0x0100;
 
-               input_dev->private = tgfx;
+               input_set_drvdata(input_dev, tgfx);
+
                input_dev->open = tgfx_open;
                input_dev->close = tgfx_close;
 
index 9cf17d6..c91504e 100644 (file)
@@ -205,11 +205,9 @@ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv)
        input_dev->id.vendor = SERIO_TWIDJOY;
        input_dev->id.product = 0x0001;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &serio->dev;
-       input_dev->private = twidjoy;
+       input_dev->dev.parent = &serio->dev;
 
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-       input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
        input_set_abs_params(input_dev, ABS_X, -50, 50, 4, 4);
        input_set_abs_params(input_dev, ABS_Y, -50, 50, 4, 4);
 
index 29d339a..4e85f72 100644 (file)
@@ -160,8 +160,7 @@ static int warrior_connect(struct serio *serio, struct serio_driver *drv)
        input_dev->id.vendor = SERIO_WARRIOR;
        input_dev->id.product = 0x0001;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &serio->dev;
-       input_dev->private = warrior;
+       input_dev->dev.parent = &serio->dev;
 
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
        input_dev->keybit[LONG(BTN_TRIGGER)] = BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_TOP2);
index f17e9c7..9f42e4d 100644 (file)
@@ -164,6 +164,17 @@ config KEYBOARD_AMIGA
          To compile this driver as a module, choose M here: the
          module will be called amikbd.
 
+config KEYBOARD_ATARI
+       tristate "Atari keyboard"
+       depends on ATARI
+       select ATARI_KBD_CORE
+       help
+         Say Y here if you are running Linux on any Atari and have a keyboard
+         attached.
+
+         To compile this driver as a module, choose M here: the
+         module will be called atakbd.
+
 config KEYBOARD_HIL_OLD
        tristate "HP HIL keyboard support (simple driver)"
        depends on GSC || HP300
@@ -203,6 +214,15 @@ config KEYBOARD_OMAP
          To compile this driver as a module, choose M here: the
          module will be called omap-keypad.
 
+config KEYBOARD_PXA27x
+       tristate "PXA27x keyboard support"
+       depends on PXA27x
+       help
+         Enable support for PXA27x matrix keyboard controller
+
+         To compile this driver as a module, choose M here: the
+         module will be called pxa27x_keyboard.
+
 config KEYBOARD_AAED2000
        tristate "AAED-2000 keyboard"
        depends on MACH_AAED2000
index 586a0fe..28d211b 100644 (file)
@@ -9,6 +9,7 @@ obj-$(CONFIG_KEYBOARD_SUNKBD)           += sunkbd.o
 obj-$(CONFIG_KEYBOARD_LKKBD)           += lkkbd.o
 obj-$(CONFIG_KEYBOARD_XTKBD)           += xtkbd.o
 obj-$(CONFIG_KEYBOARD_AMIGA)           += amikbd.o
+obj-$(CONFIG_KEYBOARD_ATARI)           += atakbd.o
 obj-$(CONFIG_KEYBOARD_LOCOMO)          += locomokbd.o
 obj-$(CONFIG_KEYBOARD_NEWTON)          += newtonkbd.o
 obj-$(CONFIG_KEYBOARD_STOWAWAY)                += stowaway.o
@@ -17,6 +18,7 @@ obj-$(CONFIG_KEYBOARD_SPITZ)          += spitzkbd.o
 obj-$(CONFIG_KEYBOARD_HIL)             += hil_kbd.o
 obj-$(CONFIG_KEYBOARD_HIL_OLD)         += hilkbd.o
 obj-$(CONFIG_KEYBOARD_OMAP)            += omap-keypad.o
+obj-$(CONFIG_KEYBOARD_PXA27x)          += pxa27x_keyboard.o
 obj-$(CONFIG_KEYBOARD_AAED2000)                += aaed2000_kbd.o
 obj-$(CONFIG_KEYBOARD_GPIO)            += gpio_keys.o
 
index 65fcb6a..3a37505 100644 (file)
@@ -97,7 +97,7 @@ static void aaedkbd_work(void *data)
 
 static int aaedkbd_open(struct input_dev *indev)
 {
-       struct aaedkbd *aaedkbd = indev->private;
+       struct aaedkbd *aaedkbd = input_get_drvdata(indev);
 
        schedule_delayed_work(&aaedkbd->workq, msecs_to_jiffies(SCAN_INTERVAL));
 
@@ -106,7 +106,7 @@ static int aaedkbd_open(struct input_dev *indev)
 
 static void aaedkbd_close(struct input_dev *indev)
 {
-       struct aaedkbd *aaedkbd = indev->private;
+       struct aaedkbd *aaedkbd = input_get_drvdata(indev);
 
        cancel_delayed_work(&aaedkbd->workq);
        flush_scheduled_work();
@@ -141,8 +141,9 @@ static int __devinit aaedkbd_probe(struct platform_device *pdev)
        input_dev->id.vendor = 0x0001;
        input_dev->id.product = 0x0001;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &pdev->dev;
-       input_dev->private = aaedkbd;
+       input_dev->dev.parent = &pdev->dev;
+
+       input_set_drvdata(input_dev, aaedkbd);
 
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
        input_dev->keycode = aaedkbd->keycode;
diff --git a/drivers/input/keyboard/atakbd.c b/drivers/input/keyboard/atakbd.c
new file mode 100644 (file)
index 0000000..ded1d6a
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ *  atakbd.c
+ *
+ *  Copyright (c) 2005 Michael Schmitz
+ *
+ * Based on amikbd.c, which is
+ *
+ *  Copyright (c) 2000-2001 Vojtech Pavlik
+ *
+ *  Based on the work of:
+ *     Hamish Macdonald
+ */
+
+/*
+ * Atari keyboard driver for Linux/m68k
+ *
+ * The low level init and interrupt stuff is handled in arch/mm68k/atari/atakeyb.c
+ * (the keyboard ACIA also handles the mouse and joystick data, and the keyboard
+ * interrupt is shared with the MIDI ACIA so MIDI data also get handled there).
+ * This driver only deals with handing key events off to the input layer.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include <asm/atariints.h>
+#include <asm/atarihw.h>
+#include <asm/atarikb.h>
+#include <asm/irq.h>
+
+MODULE_AUTHOR("Michael Schmitz <schmitz@biophys.uni-duesseldorf.de>");
+MODULE_DESCRIPTION("Atari keyboard driver");
+MODULE_LICENSE("GPL");
+
+static unsigned char atakbd_keycode[0x72];
+
+static struct input_dev *atakbd_dev;
+
+static void atakbd_interrupt(unsigned char scancode, char down)
+{
+
+       if (scancode < 0x72) {          /* scancodes < 0xf2 are keys */
+
+               // report raw events here?
+
+               scancode = atakbd_keycode[scancode];
+
+               if (scancode == KEY_CAPSLOCK) { /* CapsLock is a toggle switch key on Amiga */
+                       input_report_key(atakbd_dev, scancode, 1);
+                       input_report_key(atakbd_dev, scancode, 0);
+                       input_sync(atakbd_dev);
+               } else {
+                       input_report_key(atakbd_dev, scancode, down);
+                       input_sync(atakbd_dev);
+               }
+       } else                          /* scancodes >= 0xf2 are mouse data, most likely */
+               printk(KERN_INFO "atakbd: unhandled scancode %x\n", scancode);
+
+       return;
+}
+
+static int __init atakbd_init(void)
+{
+       int i;
+
+       if (!ATARIHW_PRESENT(ST_MFP))
+               return -EIO;
+
+       // TODO: request_mem_region if not done in arch code
+
+       if (!(atakbd_dev = input_allocate_device()))
+               return -ENOMEM;
+
+       // need to init core driver if not already done so
+       if (atari_keyb_init())
+               return -ENODEV;
+
+       atakbd_dev->name = "Atari Keyboard";
+       atakbd_dev->phys = "atakbd/input0";
+       atakbd_dev->id.bustype = BUS_ATARI;
+       atakbd_dev->id.vendor = 0x0001;
+       atakbd_dev->id.product = 0x0001;
+       atakbd_dev->id.version = 0x0100;
+
+       atakbd_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+       atakbd_dev->keycode = atakbd_keycode;
+       atakbd_dev->keycodesize = sizeof(unsigned char);
+       atakbd_dev->keycodemax = ARRAY_SIZE(atakbd_keycode);
+
+       for (i = 1; i < 0x72; i++) {
+               atakbd_keycode[i] = i;
+               set_bit(atakbd_keycode[i], atakbd_dev->keybit);
+       }
+
+       input_register_device(atakbd_dev);
+
+       atari_input_keyboard_interrupt_hook = atakbd_interrupt;
+
+       printk(KERN_INFO "input: %s at IKBD ACIA\n", atakbd_dev->name);
+
+       return 0;
+}
+
+static void __exit atakbd_exit(void)
+{
+       atari_input_keyboard_interrupt_hook = NULL;
+       input_unregister_device(atakbd_dev);
+}
+
+module_init(atakbd_init);
+module_exit(atakbd_exit);
index 6638770..be1fe46 100644 (file)
@@ -586,7 +586,7 @@ static void atkbd_event_work(struct work_struct *work)
 
 static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-       struct atkbd *atkbd = dev->private;
+       struct atkbd *atkbd = input_get_drvdata(dev);
 
        if (!atkbd->write)
                return -1;
@@ -883,8 +883,9 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd)
        input_dev->id.product = atkbd->translated ? 1 : atkbd->set;
        input_dev->id.version = atkbd->id;
        input_dev->event = atkbd_event;
-       input_dev->private = atkbd;
-       input_dev->cdev.dev = &atkbd->ps2dev.serio->dev;
+       input_dev->dev.parent = &atkbd->ps2dev.serio->dev;
+
+       input_set_drvdata(input_dev, atkbd);
 
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC);
 
index 1016c94..6578bff 100644 (file)
@@ -323,8 +323,7 @@ static int __init corgikbd_probe(struct platform_device *pdev)
        input_dev->id.vendor = 0x0001;
        input_dev->id.product = 0x0001;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &pdev->dev;
-       input_dev->private = corgikbd;
+       input_dev->dev.parent = &pdev->dev;
 
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
        input_dev->keycode = corgikbd->keycode;
index ccf6df3..7392122 100644 (file)
@@ -35,11 +35,14 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
        struct input_dev *input = platform_get_drvdata(pdev);
 
        for (i = 0; i < pdata->nbuttons; i++) {
-               int gpio = pdata->buttons[i].gpio;
+               struct gpio_keys_button *button = &pdata->buttons[i];
+               int gpio = button->gpio;
+
                if (irq == gpio_to_irq(gpio)) {
-                       int state = (gpio_get_value(gpio) ? 1 : 0) ^ (pdata->buttons[i].active_low);
+                       unsigned int type = button->type ?: EV_KEY;
+                       int state = (gpio_get_value(gpio) ? 1 : 0) ^ button->active_low;
 
-                       input_report_key(input, pdata->buttons[i].keycode, state);
+                       input_event(input, type, button->code, !!state);
                        input_sync(input);
                }
        }
@@ -63,8 +66,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
 
        input->name = pdev->name;
        input->phys = "gpio-keys/input0";
-       input->cdev.dev = &pdev->dev;
-       input->private = pdata;
+       input->dev.parent = &pdev->dev;
 
        input->id.bustype = BUS_HOST;
        input->id.vendor = 0x0001;
@@ -72,19 +74,21 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
        input->id.version = 0x0100;
 
        for (i = 0; i < pdata->nbuttons; i++) {
-               int code = pdata->buttons[i].keycode;
-               int irq = gpio_to_irq(pdata->buttons[i].gpio);
+               struct gpio_keys_button *button = &pdata->buttons[i];
+               int irq = gpio_to_irq(button->gpio);
+               unsigned int type = button->type ?: EV_KEY;
 
                set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
                error = request_irq(irq, gpio_keys_isr, IRQF_SAMPLE_RANDOM,
-                                    pdata->buttons[i].desc ? pdata->buttons[i].desc : "gpio_keys",
+                                    button->desc ? button->desc : "gpio_keys",
                                     pdev);
                if (error) {
                        printk(KERN_ERR "gpio-keys: unable to claim irq %d; error %d\n",
                                irq, error);
                        goto fail;
                }
-               set_bit(code, input->keybit);
+
+               input_set_capability(input, type, button->code);
        }
 
        error = input_register_device(input);
index 7cc9728..cdd254f 100644 (file)
@@ -51,7 +51,7 @@ MODULE_LICENSE("Dual BSD/GPL");
 
 #define HIL_KBD_SET1_UPBIT 0x01
 #define HIL_KBD_SET1_SHIFT 1
-static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] 
+static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] __read_mostly =
        { HIL_KEYCODES_SET1 };
 
 #define HIL_KBD_SET2_UPBIT 0x01
@@ -60,10 +60,10 @@ static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] =
 
 #define HIL_KBD_SET3_UPBIT 0x80
 #define HIL_KBD_SET3_SHIFT 0
-static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] =
+static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] __read_mostly =
        { HIL_KEYCODES_SET3 };
 
-static char hil_language[][16] = { HIL_LOCALE_MAP };
+static const char hil_language[][16] = { HIL_LOCALE_MAP };
 
 struct hil_kbd {
        struct input_dev *dev;
@@ -94,10 +94,12 @@ static void hil_kbd_process_record(struct hil_kbd *kbd)
        idx = kbd->idx4/4;
        p = data[idx - 1];
 
-       if ((p & ~HIL_CMDCT_POL) == 
-           (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report;
-       if ((p & ~HIL_CMDCT_RPL) == 
-           (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report;
+       if ((p & ~HIL_CMDCT_POL) ==
+           (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL))
+               goto report;
+       if ((p & ~HIL_CMDCT_RPL) ==
+           (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL))
+               goto report;
 
        /* Not a poll response.  See if we are loading config records. */
        switch (p & HIL_PKT_DATA_MASK) {
@@ -107,27 +109,32 @@ static void hil_kbd_process_record(struct hil_kbd *kbd)
                for (; i < HIL_KBD_MAX_LENGTH; i++)
                        kbd->idd[i] = 0;
                break;
+
        case HIL_CMD_RSC:
                for (i = 0; i < idx; i++)
                        kbd->rsc[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
                for (; i < HIL_KBD_MAX_LENGTH; i++)
                        kbd->rsc[i] = 0;
                break;
+
        case HIL_CMD_EXD:
                for (i = 0; i < idx; i++)
                        kbd->exd[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
                for (; i < HIL_KBD_MAX_LENGTH; i++)
                        kbd->exd[i] = 0;
                break;
+
        case HIL_CMD_RNM:
                for (i = 0; i < idx; i++)
                        kbd->rnm[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
                for (; i < HIL_KBD_MAX_LENGTH + 1; i++)
                        kbd->rnm[i] = '\0';
                break;
+
        default:
                /* These occur when device isn't present */
-               if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break; 
+               if (p == (HIL_ERR_INT | HIL_PKT_CMD))
+                       break;
                /* Anything else we'd like to know about. */
                printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p);
                break;
@@ -139,16 +146,19 @@ static void hil_kbd_process_record(struct hil_kbd *kbd)
        switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) {
        case HIL_POL_CHARTYPE_NONE:
                break;
+
        case HIL_POL_CHARTYPE_ASCII:
                while (cnt < idx - 1)
                        input_report_key(dev, kbd->data[cnt++] & 0x7f, 1);
                break;
+
        case HIL_POL_CHARTYPE_RSVD1:
        case HIL_POL_CHARTYPE_RSVD2:
        case HIL_POL_CHARTYPE_BINARY:
                while (cnt < idx - 1)
                        input_report_key(dev, kbd->data[cnt++], 1);
                break;
+
        case HIL_POL_CHARTYPE_SET1:
                while (cnt < idx - 1) {
                        unsigned int key;
@@ -161,6 +171,7 @@ static void hil_kbd_process_record(struct hil_kbd *kbd)
                                input_report_key(dev, key, !up);
                }
                break;
+
        case HIL_POL_CHARTYPE_SET2:
                while (cnt < idx - 1) {
                        unsigned int key;
@@ -173,6 +184,7 @@ static void hil_kbd_process_record(struct hil_kbd *kbd)
                                input_report_key(dev, key, !up);
                }
                break;
+
        case HIL_POL_CHARTYPE_SET3:
                while (cnt < idx - 1) {
                        unsigned int key;
@@ -191,42 +203,43 @@ static void hil_kbd_process_record(struct hil_kbd *kbd)
        up(&kbd->sem);
 }
 
-static void hil_kbd_process_err(struct hil_kbd *kbd) {
+static void hil_kbd_process_err(struct hil_kbd *kbd)
+{
        printk(KERN_WARNING PREFIX "errored HIL packet\n");
        kbd->idx4 = 0;
        up(&kbd->sem);
 }
 
-static irqreturn_t hil_kbd_interrupt(struct serio *serio, 
-             unsigned char data, unsigned int flags)
+static irqreturn_t hil_kbd_interrupt(struct serio *serio,
+                               unsigned char data, unsigned int flags)
 {
        struct hil_kbd *kbd;
        hil_packet packet;
        int idx;
 
        kbd = serio_get_drvdata(serio);
-       if (kbd == NULL) {
-               BUG();
-               return IRQ_HANDLED;
-       }
+       BUG_ON(kbd == NULL);
 
        if (kbd->idx4 >= (HIL_KBD_MAX_LENGTH * sizeof(hil_packet))) {
                hil_kbd_process_err(kbd);
                return IRQ_HANDLED;
        }
        idx = kbd->idx4/4;
-       if (!(kbd->idx4 % 4)) kbd->data[idx] = 0;
+       if (!(kbd->idx4 % 4))
+               kbd->data[idx] = 0;
        packet = kbd->data[idx];
        packet |= ((hil_packet)data) << ((3 - (kbd->idx4 % 4)) * 8);
        kbd->data[idx] = packet;
 
        /* Records of N 4-byte hil_packets must terminate with a command. */
-       if ((++(kbd->idx4)) % 4) return IRQ_HANDLED;
+       if ((++(kbd->idx4)) % 4)
+               return IRQ_HANDLED;
        if ((packet & 0xffff0000) != HIL_ERR_INT) {
                hil_kbd_process_err(kbd);
                return IRQ_HANDLED;
        }
-       if (packet & HIL_PKT_CMD) hil_kbd_process_record(kbd);
+       if (packet & HIL_PKT_CMD)
+               hil_kbd_process_record(kbd);
        return IRQ_HANDLED;
 }
 
@@ -235,10 +248,7 @@ static void hil_kbd_disconnect(struct serio *serio)
        struct hil_kbd *kbd;
 
        kbd = serio_get_drvdata(serio);
-       if (kbd == NULL) {
-               BUG();
-               return;
-       }
+       BUG_ON(kbd == NULL);
 
        serio_close(serio);
        input_unregister_device(kbd->dev);
@@ -259,42 +269,40 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
        if (!kbd->dev)
                goto bail0;
 
-       kbd->dev->private = kbd;
-
        if (serio_open(serio, drv))
                goto bail1;
 
        serio_set_drvdata(serio, kbd);
        kbd->serio = serio;
 
-       init_MUTEX_LOCKED(&(kbd->sem));
+       init_MUTEX_LOCKED(&kbd->sem);
 
        /* Get device info.  MLC driver supplies devid/status/etc. */
        serio->write(serio, 0);
        serio->write(serio, 0);
        serio->write(serio, HIL_PKT_CMD >> 8);
        serio->write(serio, HIL_CMD_IDD);
-       down(&(kbd->sem));
+       down(&kbd->sem);
 
        serio->write(serio, 0);
        serio->write(serio, 0);
        serio->write(serio, HIL_PKT_CMD >> 8);
        serio->write(serio, HIL_CMD_RSC);
-       down(&(kbd->sem));
+       down(&kbd->sem);
 
        serio->write(serio, 0);
        serio->write(serio, 0);
        serio->write(serio, HIL_PKT_CMD >> 8);
        serio->write(serio, HIL_CMD_RNM);
-       down(&(kbd->sem));
+       down(&kbd->sem);
 
        serio->write(serio, 0);
        serio->write(serio, 0);
        serio->write(serio, HIL_PKT_CMD >> 8);
        serio->write(serio, HIL_CMD_EXD);
-       down(&(kbd->sem));
+       down(&kbd->sem);
 
-       up(&(kbd->sem));
+       up(&kbd->sem);
 
        did = kbd->idd[0];
        idd = kbd->idd + 1;
@@ -310,12 +318,11 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
                goto bail2;
        }
 
-       if(HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) {
+       if (HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) {
                printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n");
                goto bail2;
        }
 
-
        kbd->dev->evbit[0]      = BIT(EV_KEY) | BIT(EV_REP);
        kbd->dev->ledbit[0]     = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
        kbd->dev->keycodemax    = HIL_KEYCODES_SET1_TBLSIZE;
@@ -328,7 +335,7 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
        kbd->dev->id.vendor     = PCI_VENDOR_ID_HP;
        kbd->dev->id.product    = 0x0001; /* TODO: get from kbd->rsc */
        kbd->dev->id.version    = 0x0100; /* TODO: get from kbd->rsc */
-       kbd->dev->cdev.dev      = &serio->dev;
+       kbd->dev->dev.parent    = &serio->dev;
 
        for (i = 0; i < 128; i++) {
                set_bit(hil_kbd_set1[i], kbd->dev->keybit);
@@ -344,8 +351,8 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
        serio->write(serio, 0);
        serio->write(serio, HIL_PKT_CMD >> 8);
        serio->write(serio, HIL_CMD_EK1); /* Enable Keyswitch Autorepeat 1 */
-       down(&(kbd->sem));
-       up(&(kbd->sem));
+       down(&kbd->sem);
+       up(&kbd->sem);
 
        return 0;
  bail2:
@@ -368,26 +375,26 @@ static struct serio_device_id hil_kbd_ids[] = {
        { 0 }
 };
 
-struct serio_driver hil_kbd_serio_drv = {
+static struct serio_driver hil_kbd_serio_drv = {
        .driver         = {
                .name   = "hil_kbd",
        },
        .description    = "HP HIL keyboard driver",
        .id_table       = hil_kbd_ids,
-       .connect        = hil_kbd_connect,
-       .disconnect     = hil_kbd_disconnect,
-       .interrupt      = hil_kbd_interrupt
+       .connect        = hil_kbd_connect,
+       .disconnect     = hil_kbd_disconnect,
+       .interrupt      = hil_kbd_interrupt
 };
 
 static int __init hil_kbd_init(void)
 {
        return serio_register_driver(&hil_kbd_serio_drv);
 }
-                
+
 static void __exit hil_kbd_exit(void)
 {
        serio_unregister_driver(&hil_kbd_serio_drv);
 }
-                        
+
 module_init(hil_kbd_init);
 module_exit(hil_kbd_exit);
index 4de4dc2..499b697 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 1998 Philip Blundell <philb@gnu.org>
  *  Copyright (C) 1999 Matthew Wilcox <willy@bofh.ai>
- *  Copyright (C) 1999-2006 Helge Deller <deller@gmx.de>
+ *  Copyright (C) 1999-2007 Helge Deller <deller@gmx.de>
  *
  *  Very basic HP Human Interface Loop (HIL) driver.
  *  This driver handles the keyboard on HP300 (m68k) and on some
@@ -52,7 +52,7 @@ MODULE_LICENSE("GPL v2");
 
 #elif defined(CONFIG_HP300)
 
- #define HILBASE               0xf0428000 /* HP300 (m86k) port address */
+ #define HILBASE               0xf0428000UL /* HP300 (m68k) port address */
  #define HIL_DATA              0x1
  #define HIL_CMD               0x3
  #define HIL_IRQ               2
@@ -89,7 +89,7 @@ MODULE_LICENSE("GPL v2");
 #define        HIL_READKBDSADR         0xF9
 #define        HIL_WRITEKBDSADR        0xE9
 
-static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] =
+static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] __read_mostly =
        { HIL_KEYCODES_SET1 };
 
 /* HIL structure */
@@ -211,10 +211,10 @@ hil_keyb_init(void)
                return -ENODEV; /* already initialized */
        }
 
+       spin_lock_init(&hil_dev.lock);
        hil_dev.dev = input_allocate_device();
        if (!hil_dev.dev)
                return -ENOMEM;
-       hil_dev.dev->private = &hil_dev;
 
 #if defined(CONFIG_HP300)
        if (!hwreg_present((void *)(HILBASE + HIL_DATA))) {
index 3d4d0a0..1b08f4e 100644 (file)
@@ -515,7 +515,7 @@ static int
 lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code,
                int value)
 {
-       struct lkkbd *lk = dev->private;
+       struct lkkbd *lk = input_get_drvdata (dev);
        unsigned char leds_on = 0;
        unsigned char leds_off = 0;
 
@@ -666,9 +666,10 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv)
        input_dev->id.vendor = SERIO_LKKBD;
        input_dev->id.product = 0;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &serio->dev;
+       input_dev->dev.parent = &serio->dev;
        input_dev->event = lkkbd_event;
-       input_dev->private = lk;
+
+       input_set_drvdata (input_dev, lk);
 
        set_bit (EV_KEY, input_dev->evbit);
        set_bit (EV_LED, input_dev->evbit);
index 2ade518..7a41b27 100644 (file)
@@ -231,7 +231,7 @@ static int locomokbd_probe(struct locomo_dev *dev)
        input_dev->id.vendor = 0x0001;
        input_dev->id.product = 0x0001;
        input_dev->id.version = 0x0100;
-       input_dev->private = locomokbd;
+       input_dev->dev.parent = &dev->dev;
 
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
        input_dev->keycode = locomokbd->keycode;
index aa29b50..b97a41e 100644 (file)
@@ -104,8 +104,7 @@ static int nkbd_connect(struct serio *serio, struct serio_driver *drv)
        input_dev->id.vendor = SERIO_NEWTON;
        input_dev->id.product = 0x0001;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &serio->dev;
-       input_dev->private = nkbd;
+       input_dev->dev.parent = &serio->dev;
 
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
        input_dev->keycode = nkbd->keycode;
index 5680a6d..3a22863 100644 (file)
@@ -370,8 +370,7 @@ static int __init omap_kp_probe(struct platform_device *pdev)
                set_bit(keymap[i] & KEY_MAX, input_dev->keybit);
        input_dev->name = "omap-keypad";
        input_dev->phys = "omap-keypad/input0";
-       input_dev->cdev.dev = &pdev->dev;
-       input_dev->private = omap_kp;
+       input_dev->dev.parent = &pdev->dev;
 
        input_dev->id.bustype = BUS_HOST;
        input_dev->id.vendor = 0x0001;
diff --git a/drivers/input/keyboard/pxa27x_keyboard.c b/drivers/input/keyboard/pxa27x_keyboard.c
new file mode 100644 (file)
index 0000000..06eaf76
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * linux/drivers/input/keyboard/pxa27x_keyboard.c
+ *
+ * Driver for the pxa27x matrix keyboard controller.
+ *
+ * Created:    Feb 22, 2007
+ * Author:     Rodolfo Giometti <giometti@linux.it>
+ *
+ * Based on a previous implementations by Kevin O'Connor
+ * <kevin_at_koconnor.net> and Alex Osborne <bobofdoom@gmail.com> and
+ * on some suggestions by Nicolas Pitre <nico@cam.org>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/pxa27x_keyboard.h>
+
+#define DRIVER_NAME            "pxa27x-keyboard"
+
+#define KPASMKP(col)           (col/2 == 0 ? KPASMKP0 : \
+                                col/2 == 1 ? KPASMKP1 : \
+                                col/2 == 2 ? KPASMKP2 : KPASMKP3)
+#define KPASMKPx_MKC(row, col) (1 << (row + 16 * (col % 2)))
+
+static irqreturn_t pxakbd_irq_handler(int irq, void *dev_id)
+{
+       struct platform_device *pdev = dev_id;
+       struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+       struct input_dev *input_dev = platform_get_drvdata(pdev);
+       unsigned long kpc = KPC;
+       int p, row, col, rel;
+
+       if (kpc & KPC_DI) {
+               unsigned long kpdk = KPDK;
+
+               if (!(kpdk & KPDK_DKP)) {
+                       /* better luck next time */
+               } else if (kpc & KPC_REE0) {
+                       unsigned long kprec = KPREC;
+                       KPREC = 0x7f;
+
+                       if (kprec & KPREC_OF0)
+                               rel = (kprec & 0xff) + 0x7f;
+                       else if (kprec & KPREC_UF0)
+                               rel = (kprec & 0xff) - 0x7f - 0xff;
+                       else
+                               rel = (kprec & 0xff) - 0x7f;
+
+                       if (rel) {
+                               input_report_rel(input_dev, REL_WHEEL, rel);
+                               input_sync(input_dev);
+                       }
+               }
+       }
+
+       if (kpc & KPC_MI) {
+               /* report the status of every button */
+               for (row = 0; row < pdata->nr_rows; row++) {
+                       for (col = 0; col < pdata->nr_cols; col++) {
+                               p = KPASMKP(col) & KPASMKPx_MKC(row, col) ?
+                                       1 : 0;
+                               pr_debug("keycode %x - pressed %x\n",
+                                               pdata->keycodes[row][col], p);
+                               input_report_key(input_dev,
+                                               pdata->keycodes[row][col], p);
+                       }
+               }
+               input_sync(input_dev);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int pxakbd_open(struct input_dev *dev)
+{
+       /* Set keypad control register */
+       KPC |= (KPC_ASACT |
+               KPC_MS_ALL |
+               (2 << 6) | KPC_REE0 | KPC_DK_DEB_SEL |
+               KPC_ME | KPC_MIE | KPC_DE | KPC_DIE);
+
+       KPC &= ~KPC_AS;         /* disable automatic scan */
+       KPC &= ~KPC_IMKP;       /* do not ignore multiple keypresses */
+
+       /* Set rotary count to mid-point value */
+       KPREC = 0x7F;
+
+       /* Enable unit clock */
+       pxa_set_cken(CKEN19_KEYPAD, 1);
+
+       return 0;
+}
+
+static void pxakbd_close(struct input_dev *dev)
+{
+       /* Disable clock unit */
+       pxa_set_cken(CKEN19_KEYPAD, 0);
+}
+
+#ifdef CONFIG_PM
+static int pxakbd_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+
+       /* Save controller status */
+       pdata->reg_kpc = KPC;
+       pdata->reg_kprec = KPREC;
+
+       return 0;
+}
+
+static int pxakbd_resume(struct platform_device *pdev)
+{
+       struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+       struct input_dev *input_dev = platform_get_drvdata(pdev);
+
+       mutex_lock(&input_dev->mutex);
+
+       if (input_dev->users) {
+               /* Restore controller status */
+               KPC = pdata->reg_kpc;
+               KPREC = pdata->reg_kprec;
+
+               /* Enable unit clock */
+               pxa_set_cken(CKEN19_KEYPAD, 1);
+       }
+
+       mutex_unlock(&input_dev->mutex);
+
+       return 0;
+}
+#else
+#define pxakbd_suspend NULL
+#define pxakbd_resume  NULL
+#endif
+
+static int __devinit pxakbd_probe(struct platform_device *pdev)
+{
+       struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+       struct input_dev *input_dev;
+       int i, row, col, error;
+
+       /* Create and register the input driver. */
+       input_dev = input_allocate_device();
+       if (!input_dev) {
+               printk(KERN_ERR "Cannot request keypad device\n");
+               return -ENOMEM;
+       }
+
+       input_dev->name = DRIVER_NAME;
+       input_dev->id.bustype = BUS_HOST;
+       input_dev->open = pxakbd_open;
+       input_dev->close = pxakbd_close;
+       input_dev->dev.parent = &pdev->dev;
+
+       input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL);
+       input_dev->relbit[LONG(REL_WHEEL)] = BIT(REL_WHEEL);
+       for (row = 0; row < pdata->nr_rows; row++) {
+               for (col = 0; col < pdata->nr_cols; col++) {
+                       int code = pdata->keycodes[row][col];
+                       if (code > 0)
+                               set_bit(code, input_dev->keybit);
+               }
+       }
+
+       error = request_irq(IRQ_KEYPAD, pxakbd_irq_handler, IRQF_DISABLED,
+                           DRIVER_NAME, pdev);
+       if (error) {
+               printk(KERN_ERR "Cannot request keypad IRQ\n");
+               pxa_set_cken(CKEN19_KEYPAD, 0);
+               goto err_free_dev;
+       }
+
+       platform_set_drvdata(pdev, input_dev);
+
+       /* Register the input device */
+       error = input_register_device(input_dev);
+       if (error)
+               goto err_free_irq;
+
+       /* Setup GPIOs. */
+       for (i = 0; i < pdata->nr_rows + pdata->nr_cols; i++)
+               pxa_gpio_mode(pdata->gpio_modes[i]);
+
+       /*
+        * Store rows/cols info into keyboard registers.
+        */
+
+       KPC |= (pdata->nr_rows - 1) << 26;
+       KPC |= (pdata->nr_cols - 1) << 23;
+
+       for (col = 0; col < pdata->nr_cols; col++)
+               KPC |= KPC_MS0 << col;
+
+       return 0;
+
+ err_free_irq:
+       platform_set_drvdata(pdev, NULL);
+       free_irq(IRQ_KEYPAD, pdev);
+ err_free_dev:
+       input_free_device(input_dev);
+       return error;
+}
+
+static int __devexit pxakbd_remove(struct platform_device *pdev)
+{
+       struct input_dev *input_dev = platform_get_drvdata(pdev);
+
+       input_unregister_device(input_dev);
+       free_irq(IRQ_KEYPAD, pdev);
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver pxakbd_driver = {
+       .probe          = pxakbd_probe,
+       .remove         = __devexit_p(pxakbd_remove),
+       .suspend        = pxakbd_suspend,
+       .resume         = pxakbd_resume,
+       .driver         = {
+               .name   = DRIVER_NAME,
+       },
+};
+
+static int __init pxakbd_init(void)
+{
+       return platform_driver_register(&pxakbd_driver);
+}
+
+static void __exit pxakbd_exit(void)
+{
+       platform_driver_unregister(&pxakbd_driver);
+}
+
+module_init(pxakbd_init);
+module_exit(pxakbd_exit);
+
+MODULE_DESCRIPTION("PXA27x Matrix Keyboard Driver");
+MODULE_LICENSE("GPL");
index 8a2166c..41b8038 100644 (file)
@@ -372,10 +372,9 @@ static int __init spitzkbd_probe(struct platform_device *dev)
 
        spitzkbd->input = input_dev;
 
-       input_dev->private = spitzkbd;
        input_dev->name = "Spitz Keyboard";
        input_dev->phys = spitzkbd->phys;
-       input_dev->cdev.dev = &dev->dev;
+       input_dev->dev.parent = &dev->dev;
 
        input_dev->id.bustype = BUS_HOST;
        input_dev->id.vendor = 0x0001;
index f7b5c5b..b44b068 100644 (file)
@@ -108,8 +108,7 @@ static int skbd_connect(struct serio *serio, struct serio_driver *drv)
        input_dev->id.vendor = SERIO_STOWAWAY;
        input_dev->id.product = 0x0001;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &serio->dev;
-       input_dev->private = skbd;
+       input_dev->dev.parent = &serio->dev;
 
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
        input_dev->keycode = skbd->keycode;
index cc02383..1d4e396 100644 (file)
@@ -146,7 +146,7 @@ out:
 
 static int sunkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-       struct sunkbd *sunkbd = dev->private;
+       struct sunkbd *sunkbd = input_get_drvdata(dev);
 
        switch (type) {
 
@@ -271,8 +271,10 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
        input_dev->id.vendor  = SERIO_SUNKBD;
        input_dev->id.product = sunkbd->type;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &serio->dev;
-       input_dev->private = sunkbd;
+       input_dev->dev.parent = &serio->dev;
+
+       input_set_drvdata(input_dev, sunkbd);
+
        input_dev->event = sunkbd_event;
 
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP);
index a820934..f3a56eb 100644 (file)
@@ -108,8 +108,7 @@ static int xtkbd_connect(struct serio *serio, struct serio_driver *drv)
        input_dev->id.vendor  = 0x0001;
        input_dev->id.product = 0x0001;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &serio->dev;
-       input_dev->private = xtkbd;
+       input_dev->dev.parent = &serio->dev;
 
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
        input_dev->keycode = xtkbd->keycode;
index 41b4258..1d0d3e7 100644 (file)
@@ -40,6 +40,16 @@ config INPUT_M68K_BEEP
        tristate "M68k Beeper support"
        depends on M68K
 
+config INPUT_COBALT_BTNS
+       tristate "Cobalt button interface"
+       depends on MIPS_COBALT
+       select INPUT_POLLDEV
+       help
+         Say Y here if you want to support MIPS Cobalt button interface.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cobalt_btns.
+
 config INPUT_WISTRON_BTNS
        tristate "x86 Wistron laptop button interface"
        depends on X86 && !X86_64
@@ -81,8 +91,19 @@ config INPUT_UINPUT
          To compile this driver as a module, choose M here: the
          module will be called uinput.
 
+config INPUT_POLLDEV
+       tristate "Polled input device skeleton"
+       help
+         Say Y here if you are using a driver for an input
+         device that periodically polls hardware state. This
+         option is only useful for out-of-tree drivers since
+         in-tree drivers select it automatically.
+
+         To compile this driver as a module, choose M here: the
+         module will be called input-polldev.
+
 config HP_SDC_RTC
-       tristate "HP SDC Real Time Clock"       
+       tristate "HP SDC Real Time Clock"
        depends on GSC || HP300
        select HP_SDC
        help
index e0a8d58..21e3cca 100644 (file)
@@ -4,10 +4,12 @@
 
 # Each configuration option enables a list of files.
 
+obj-$(CONFIG_INPUT_POLLDEV)            += input-polldev.o
 obj-$(CONFIG_INPUT_SPARCSPKR)          += sparcspkr.o
 obj-$(CONFIG_INPUT_PCSPKR)             += pcspkr.o
 obj-$(CONFIG_INPUT_M68K_BEEP)          += m68kspkr.o
 obj-$(CONFIG_INPUT_UINPUT)             += uinput.o
+obj-$(CONFIG_INPUT_COBALT_BTNS)                += cobalt_btns.o
 obj-$(CONFIG_INPUT_WISTRON_BTNS)       += wistron_btns.o
 obj-$(CONFIG_INPUT_ATLAS_BTNS)         += atlas_btns.o
 obj-$(CONFIG_HP_SDC_RTC)               += hp_sdc_rtc.o
diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c
new file mode 100644 (file)
index 0000000..064b079
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ *  Cobalt button interface driver.
+ *
+ *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/init.h>
+#include <linux/input-polldev.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#define BUTTONS_POLL_INTERVAL  30      /* msec */
+#define BUTTONS_COUNT_THRESHOLD        3
+#define BUTTONS_STATUS_MASK    0xfe000000
+
+struct buttons_dev {
+       struct input_polled_dev *poll_dev;
+       void __iomem *reg;
+};
+
+struct buttons_map {
+       uint32_t mask;
+       int keycode;
+       int count;
+};
+
+static struct buttons_map buttons_map[] = {
+       { 0x02000000, KEY_RESTART, },
+       { 0x04000000, KEY_LEFT, },
+       { 0x08000000, KEY_UP, },
+       { 0x10000000, KEY_DOWN, },
+       { 0x20000000, KEY_RIGHT, },
+       { 0x40000000, KEY_ENTER, },
+       { 0x80000000, KEY_SELECT, },
+};
+
+static void handle_buttons(struct input_polled_dev *dev)
+{
+       struct buttons_map *button = buttons_map;
+       struct buttons_dev *bdev = dev->private;
+       struct input_dev *input = dev->input;
+       uint32_t status;
+       int i;
+
+       status = readl(bdev->reg);
+       status = ~status & BUTTONS_STATUS_MASK;
+
+       for (i = 0; i < ARRAY_SIZE(buttons_map); i++) {
+               if (status & button->mask) {
+                       button->count++;
+               } else {
+                       if (button->count >= BUTTONS_COUNT_THRESHOLD) {
+                               input_report_key(input, button->keycode, 0);
+                               input_sync(input);
+                       }
+                       button->count = 0;
+               }
+
+               if (button->count == BUTTONS_COUNT_THRESHOLD) {
+                       input_report_key(input, button->keycode, 1);
+                       input_sync(input);
+               }
+
+               button++;
+       }
+}
+
+static int __devinit cobalt_buttons_probe(struct platform_device *pdev)
+{
+       struct buttons_dev *bdev;
+       struct input_polled_dev *poll_dev;
+       struct input_dev *input;
+       struct resource *res;
+       int error, i;
+
+       bdev = kzalloc(sizeof(struct buttons_dev), GFP_KERNEL);
+       poll_dev = input_allocate_polled_device();
+       if (!bdev || !poll_dev) {
+               error = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       poll_dev->private = bdev;
+       poll_dev->poll = handle_buttons;
+       poll_dev->poll_interval = BUTTONS_POLL_INTERVAL;
+
+       input = poll_dev->input;
+       input->name = "Cobalt buttons";
+       input->phys = "cobalt/input0";
+       input->id.bustype = BUS_HOST;
+       input->cdev.dev = &pdev->dev;
+
+       input->evbit[0] = BIT(EV_KEY);
+       for (i = 0; i < ARRAY_SIZE(buttons_map); i++) {
+               set_bit(buttons_map[i].keycode, input->keybit);
+               buttons_map[i].count = 0;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               error = -EBUSY;
+               goto err_free_mem;
+       }
+
+       bdev->poll_dev = poll_dev;
+       bdev->reg = ioremap(res->start, res->end - res->start + 1);
+       dev_set_drvdata(&pdev->dev, bdev);
+
+       error = input_register_polled_device(poll_dev);
+       if (error)
+               goto err_iounmap;
+
+       return 0;
+
+ err_iounmap:
+       iounmap(bdev->reg);
+ err_free_mem:
+       input_free_polled_device(poll_dev);
+       kfree(bdev);
+       dev_set_drvdata(&pdev->dev, NULL);
+       return error;
+}
+
+static int __devexit cobalt_buttons_remove(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct buttons_dev *bdev = dev_get_drvdata(dev);
+
+       input_unregister_polled_device(bdev->poll_dev);
+       input_free_polled_device(bdev->poll_dev);
+       iounmap(bdev->reg);
+       kfree(bdev);
+       dev_set_drvdata(dev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver cobalt_buttons_driver = {
+       .probe  = cobalt_buttons_probe,
+       .remove = __devexit_p(cobalt_buttons_remove),
+       .driver = {
+               .name   = "Cobalt buttons",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init cobalt_buttons_init(void)
+{
+       return platform_driver_register(&cobalt_buttons_driver);
+}
+
+static void __exit cobalt_buttons_exit(void)
+{
+       platform_driver_unregister(&cobalt_buttons_driver);
+}
+
+module_init(cobalt_buttons_init);
+module_exit(cobalt_buttons_exit);
diff --git a/drivers/input/misc/input-polldev.c b/drivers/input/misc/input-polldev.c
new file mode 100644 (file)
index 0000000..1b2b9c9
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Generic implementation of a polled input device
+
+ * Copyright (c) 2007 Dmitry Torokhov
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/jiffies.h>
+#include <linux/mutex.h>
+#include <linux/input-polldev.h>
+
+static DEFINE_MUTEX(polldev_mutex);
+static int polldev_users;
+static struct workqueue_struct *polldev_wq;
+
+static int input_polldev_start_workqueue(void)
+{
+       int retval;
+
+       retval = mutex_lock_interruptible(&polldev_mutex);
+       if (retval)
+               return retval;
+
+       if (!polldev_users) {
+               polldev_wq = create_singlethread_workqueue("ipolldevd");
+               if (!polldev_wq) {
+                       printk(KERN_ERR "input-polldev: failed to create "
+                               "ipolldevd workqueue\n");
+                       retval = -ENOMEM;
+                       goto out;
+               }
+       }
+
+       polldev_users++;
+
+ out:
+       mutex_unlock(&polldev_mutex);
+       return retval;
+}
+
+static void input_polldev_stop_workqueue(void)
+{
+       mutex_lock(&polldev_mutex);
+
+       if (!--polldev_users)
+               destroy_workqueue(polldev_wq);
+
+       mutex_unlock(&polldev_mutex);
+}
+
+static void input_polled_device_work(struct work_struct *work)
+{
+       struct input_polled_dev *dev =
+               container_of(work, struct input_polled_dev, work.work);
+
+       dev->poll(dev);
+       queue_delayed_work(polldev_wq, &dev->work,
+                          msecs_to_jiffies(dev->poll_interval));
+}
+
+static int input_open_polled_device(struct input_dev *input)
+{
+       struct input_polled_dev *dev = input->private;
+       int error;
+
+       error = input_polldev_start_workqueue();
+       if (error)
+               return error;
+
+       if (dev->flush)
+               dev->flush(dev);
+
+       queue_delayed_work(polldev_wq, &dev->work,
+                          msecs_to_jiffies(dev->poll_interval));
+
+       return 0;
+}
+
+static void input_close_polled_device(struct input_dev *input)
+{
+       struct input_polled_dev *dev = input->private;
+
+       cancel_rearming_delayed_workqueue(polldev_wq, &dev->work);
+       input_polldev_stop_workqueue();
+}
+
+/**
+ * input_allocate_polled_device - allocated memory polled device
+ *
+ * The function allocates memory for a polled device and also
+ * for an input device associated with this polled device.
+ */
+struct input_polled_dev *input_allocate_polled_device(void)
+{
+       struct input_polled_dev *dev;
+
+       dev = kzalloc(sizeof(struct input_polled_dev), GFP_KERNEL);
+       if (!dev)
+               return NULL;
+
+       dev->input = input_allocate_device();
+       if (!dev->input) {
+               kfree(dev);
+               return NULL;
+       }
+
+       return dev;
+}
+EXPORT_SYMBOL(input_allocate_polled_device);
+
+/**
+ * input_free_polled_device - free memory allocated for polled device
+ * @dev: device to free
+ *
+ * The function frees memory allocated for polling device and drops
+ * reference to the associated input device (if present).
+ */
+void input_free_polled_device(struct input_polled_dev *dev)
+{
+       if (dev) {
+               input_free_device(dev->input);
+               kfree(dev);
+       }
+}
+EXPORT_SYMBOL(input_free_polled_device);
+
+/**
+ * input_register_polled_device - register polled device
+ * @dev: device to register
+ *
+ * The function registers previously initialized polled input device
+ * with input layer. The device should be allocated with call to
+ * input_allocate_polled_device(). Callers should also set up poll()
+ * method and set up capabilities (id, name, phys, bits) of the
+ * corresponing input_dev structure.
+ */
+int input_register_polled_device(struct input_polled_dev *dev)
+{
+       struct input_dev *input = dev->input;
+
+       INIT_DELAYED_WORK(&dev->work, input_polled_device_work);
+       if (!dev->poll_interval)
+               dev->poll_interval = 500;
+       input->private = dev;
+       input->open = input_open_polled_device;
+       input->close = input_close_polled_device;
+
+       return input_register_device(input);
+}
+EXPORT_SYMBOL(input_register_polled_device);
+
+/**
+ * input_unregister_polled_device - unregister polled device
+ * @dev: device to unregister
+ *
+ * The function unregisters previously registered polled input
+ * device from input layer. Polling is stopped and device is
+ * ready to be freed with call to input_free_polled_device().
+ * Callers should not attempt to access dev->input pointer
+ * after calling this function.
+ */
+void input_unregister_polled_device(struct input_polled_dev *dev)
+{
+       input_unregister_device(dev->input);
+       dev->input = NULL;
+}
+EXPORT_SYMBOL(input_unregister_polled_device);
+
index 105c6fc..3d4b619 100644 (file)
@@ -51,7 +51,7 @@ static void ixp4xx_spkr_control(unsigned int pin, unsigned int count)
 
 static int ixp4xx_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-       unsigned int pin = (unsigned int) dev->private;
+       unsigned int pin = (unsigned int) input_get_drvdata(input_dev);
        unsigned int count = 0;
 
        if (type != EV_SND)
@@ -99,14 +99,15 @@ static int __devinit ixp4xx_spkr_probe(struct platform_device *dev)
        if (!input_dev)
                return -ENOMEM;
 
-       input_dev->private = (void *) dev->id;
+       input_set_drvdata(input_dev, (void *) dev->id);
+
        input_dev->name = "ixp4xx beeper",
        input_dev->phys = "ixp4xx/gpio";
        input_dev->id.bustype = BUS_HOST;
        input_dev->id.vendor  = 0x001f;
        input_dev->id.product = 0x0001;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &dev->dev;
+       input_dev->dev.parent = &dev->dev;
 
        input_dev->evbit[0] = BIT(EV_SND);
        input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
@@ -136,7 +137,7 @@ static int __devinit ixp4xx_spkr_probe(struct platform_device *dev)
 static int __devexit ixp4xx_spkr_remove(struct platform_device *dev)
 {
        struct input_dev *input_dev = platform_get_drvdata(dev);
-       unsigned int pin = (unsigned int) input_dev->private;
+       unsigned int pin = (unsigned int) input_get_drvdata(input_dev);
 
        input_unregister_device(input_dev);
        platform_set_drvdata(dev, NULL);
@@ -153,7 +154,7 @@ static int __devexit ixp4xx_spkr_remove(struct platform_device *dev)
 static void ixp4xx_spkr_shutdown(struct platform_device *dev)
 {
        struct input_dev *input_dev = platform_get_drvdata(dev);
-       unsigned int pin = (unsigned int) input_dev->private;
+       unsigned int pin = (unsigned int) input_get_drvdata(input_dev);
 
        /* turn off the speaker */
        disable_irq(IRQ_IXP4XX_TIMER2);
index 8d6c383..e9f26e7 100644 (file)
@@ -63,7 +63,7 @@ static int __devinit m68kspkr_probe(struct platform_device *dev)
        input_dev->id.vendor  = 0x001f;
        input_dev->id.product = 0x0001;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &dev->dev;
+       input_dev->dev.parent = &dev->dev;
 
        input_dev->evbit[0] = BIT(EV_SND);
        input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
index afd3221..31989dc 100644 (file)
@@ -78,7 +78,7 @@ static int __devinit pcspkr_probe(struct platform_device *dev)
        pcspkr_dev->id.vendor = 0x001f;
        pcspkr_dev->id.product = 0x0001;
        pcspkr_dev->id.version = 0x0100;
-       pcspkr_dev->cdev.dev = &dev->dev;
+       pcspkr_dev->dev.parent = &dev->dev;
 
        pcspkr_dev->evbit[0] = BIT(EV_SND);
        pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
index 106c94f..e36ec1d 100644 (file)
@@ -28,7 +28,7 @@ struct sparcspkr_state {
 
 static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-       struct sparcspkr_state *state = dev_get_drvdata(dev->cdev.dev);
+       struct sparcspkr_state *state = dev_get_drvdata(dev->dev.parent);
        unsigned int count = 0;
        unsigned long flags;
 
@@ -61,7 +61,7 @@ static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned in
 
 static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-       struct sparcspkr_state *state = dev_get_drvdata(dev->cdev.dev);
+       struct sparcspkr_state *state = dev_get_drvdata(dev->dev.parent);
        unsigned int count = 0;
        unsigned long flags;
 
@@ -113,7 +113,7 @@ static int __devinit sparcspkr_probe(struct device *dev)
        input_dev->id.vendor = 0x001f;
        input_dev->id.product = 0x0001;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = dev;
+       input_dev->dev.parent = dev;
 
        input_dev->evbit[0] = BIT(EV_SND);
        input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
index 4255623..031467e 100644 (file)
@@ -41,9 +41,7 @@
 
 static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-       struct uinput_device    *udev;
-
-       udev = dev->private;
+       struct uinput_device    *udev = input_get_drvdata(dev);
 
        udev->buff[udev->head].type = type;
        udev->buff[udev->head].code = code;
@@ -136,7 +134,7 @@ static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *eff
        request.u.upload.effect = effect;
        request.u.upload.old = old;
 
-       retval = uinput_request_reserve_slot(dev->private, &request);
+       retval = uinput_request_reserve_slot(input_get_drvdata(dev), &request);
        if (!retval)
                retval = uinput_request_submit(dev, &request);
 
@@ -156,7 +154,7 @@ static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id)
        request.code = UI_FF_ERASE;
        request.u.effect_id = effect_id;
 
-       retval = uinput_request_reserve_slot(dev->private, &request);
+       retval = uinput_request_reserve_slot(input_get_drvdata(dev), &request);
        if (!retval)
                retval = uinput_request_submit(dev, &request);
 
@@ -274,7 +272,7 @@ static int uinput_allocate_device(struct uinput_device *udev)
                return -ENOMEM;
 
        udev->dev->event = uinput_dev_event;
-       udev->dev->private = udev;
+       input_set_drvdata(udev->dev, udev);
 
        return 0;
 }
index e1183ae..961aad7 100644 (file)
@@ -50,7 +50,7 @@
 MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>");
 MODULE_DESCRIPTION("Wistron laptop button driver");
 MODULE_LICENSE("GPL v2");
-MODULE_VERSION("0.1");
+MODULE_VERSION("0.2");
 
 static int force; /* = 0; */
 module_param(force, bool, 0);
@@ -58,7 +58,7 @@ MODULE_PARM_DESC(force, "Load even if computer is not in database");
 
 static char *keymap_name; /* = NULL; */
 module_param_named(keymap, keymap_name, charp, 0);
-MODULE_PARM_DESC(keymap, "Keymap name, if it can't be autodetected");
+MODULE_PARM_DESC(keymap, "Keymap name, if it can't be autodetected [generic, 1557/MS2141]");
 
 static struct platform_device *wistron_device;
 
@@ -233,10 +233,20 @@ static void bios_set_state(u8 subsys, int enable)
 struct key_entry {
        char type;              /* See KE_* below */
        u8 code;
-       unsigned keycode;       /* For KE_KEY */
+       union {
+               u16 keycode;            /* For KE_KEY */
+               struct {                /* For KE_SW */
+                       u8 code;
+                       u8 value;
+               } sw;
+       };
 };
 
-enum { KE_END, KE_KEY, KE_WIFI, KE_BLUETOOTH };
+enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH };
+
+#define FE_MAIL_LED 0x01
+#define FE_WIFI_LED 0x02
+#define FE_UNTESTED 0x80
 
 static const struct key_entry *keymap; /* = NULL; Current key map */
 static int have_wifi;
@@ -256,93 +266,341 @@ static int __init dmi_matched(struct dmi_system_id *dmi)
        return 1;
 }
 
-static struct key_entry keymap_empty[] = {
+static struct key_entry keymap_empty[] __initdata = {
        { KE_END, 0 }
 };
 
-static struct key_entry keymap_fs_amilo_pro_v2000[] = {
-       { KE_KEY,  0x01, KEY_HELP },
-       { KE_KEY,  0x11, KEY_PROG1 },
-       { KE_KEY,  0x12, KEY_PROG2 },
-       { KE_WIFI, 0x30, 0 },
-       { KE_KEY,  0x31, KEY_MAIL },
-       { KE_KEY,  0x36, KEY_WWW },
+static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = {
+       { KE_KEY,  0x01, {KEY_HELP} },
+       { KE_KEY,  0x11, {KEY_PROG1} },
+       { KE_KEY,  0x12, {KEY_PROG2} },
+       { KE_WIFI, 0x30 },
+       { KE_KEY,  0x31, {KEY_MAIL} },
+       { KE_KEY,  0x36, {KEY_WWW} },
        { KE_END,  0 }
 };
 
-static struct key_entry keymap_fujitsu_n3510[] = {
-       { KE_KEY, 0x11, KEY_PROG1 },
-       { KE_KEY, 0x12, KEY_PROG2 },
-       { KE_KEY, 0x36, KEY_WWW },
-       { KE_KEY, 0x31, KEY_MAIL },
-       { KE_KEY, 0x71, KEY_STOPCD },
-       { KE_KEY, 0x72, KEY_PLAYPAUSE },
-       { KE_KEY, 0x74, KEY_REWIND },
-       { KE_KEY, 0x78, KEY_FORWARD },
+static struct key_entry keymap_fujitsu_n3510[] __initdata = {
+       { KE_KEY, 0x11, {KEY_PROG1} },
+       { KE_KEY, 0x12, {KEY_PROG2} },
+       { KE_KEY, 0x36, {KEY_WWW} },
+       { KE_KEY, 0x31, {KEY_MAIL} },
+       { KE_KEY, 0x71, {KEY_STOPCD} },
+       { KE_KEY, 0x72, {KEY_PLAYPAUSE} },
+       { KE_KEY, 0x74, {KEY_REWIND} },
+       { KE_KEY, 0x78, {KEY_FORWARD} },
        { KE_END, 0 }
 };
 
-static struct key_entry keymap_wistron_ms2111[] = {
-       { KE_KEY,  0x11, KEY_PROG1 },
-       { KE_KEY,  0x12, KEY_PROG2 },
-       { KE_KEY,  0x13, KEY_PROG3 },
-       { KE_KEY,  0x31, KEY_MAIL },
-       { KE_KEY,  0x36, KEY_WWW },
-       { KE_END,  0 }
+static struct key_entry keymap_wistron_ms2111[] __initdata = {
+       { KE_KEY,  0x11, {KEY_PROG1} },
+       { KE_KEY,  0x12, {KEY_PROG2} },
+       { KE_KEY,  0x13, {KEY_PROG3} },
+       { KE_KEY,  0x31, {KEY_MAIL} },
+       { KE_KEY,  0x36, {KEY_WWW} },
+       { KE_END, FE_MAIL_LED }
+};
+
+static struct key_entry keymap_wistron_md40100[] __initdata = {
+       { KE_KEY, 0x01, {KEY_HELP} },
+       { KE_KEY, 0x02, {KEY_CONFIG} },
+       { KE_KEY, 0x31, {KEY_MAIL} },
+       { KE_KEY, 0x36, {KEY_WWW} },
+       { KE_KEY, 0x37, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
+       { KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED }
 };
 
-static struct key_entry keymap_wistron_ms2141[] = {
-       { KE_KEY,  0x11, KEY_PROG1 },
-       { KE_KEY,  0x12, KEY_PROG2 },
-       { KE_WIFI, 0x30, 0 },
-       { KE_KEY,  0x22, KEY_REWIND },
-       { KE_KEY,  0x23, KEY_FORWARD },
-       { KE_KEY,  0x24, KEY_PLAYPAUSE },
-       { KE_KEY,  0x25, KEY_STOPCD },
-       { KE_KEY,  0x31, KEY_MAIL },
-       { KE_KEY,  0x36, KEY_WWW },
+static struct key_entry keymap_wistron_ms2141[] __initdata = {
+       { KE_KEY,  0x11, {KEY_PROG1} },
+       { KE_KEY,  0x12, {KEY_PROG2} },
+       { KE_WIFI, 0x30 },
+       { KE_KEY,  0x22, {KEY_REWIND} },
+       { KE_KEY,  0x23, {KEY_FORWARD} },
+       { KE_KEY,  0x24, {KEY_PLAYPAUSE} },
+       { KE_KEY,  0x25, {KEY_STOPCD} },
+       { KE_KEY,  0x31, {KEY_MAIL} },
+       { KE_KEY,  0x36, {KEY_WWW} },
        { KE_END,  0 }
 };
 
-static struct key_entry keymap_acer_aspire_1500[] = {
-       { KE_KEY, 0x11, KEY_PROG1 },
-       { KE_KEY, 0x12, KEY_PROG2 },
-       { KE_WIFI, 0x30, 0 },
-       { KE_KEY, 0x31, KEY_MAIL },
-       { KE_KEY, 0x36, KEY_WWW },
-       { KE_BLUETOOTH, 0x44, 0 },
-       { KE_END, 0 }
+static struct key_entry keymap_acer_aspire_1500[] __initdata = {
+       { KE_KEY, 0x01, {KEY_HELP} },
+       { KE_KEY, 0x03, {KEY_POWER} },
+       { KE_KEY, 0x11, {KEY_PROG1} },
+       { KE_KEY, 0x12, {KEY_PROG2} },
+       { KE_WIFI, 0x30 },
+       { KE_KEY, 0x31, {KEY_MAIL} },
+       { KE_KEY, 0x36, {KEY_WWW} },
+       { KE_KEY, 0x49, {KEY_CONFIG} },
+       { KE_BLUETOOTH, 0x44 },
+       { KE_END, FE_UNTESTED }
 };
 
-static struct key_entry keymap_acer_travelmate_240[] = {
-       { KE_KEY, 0x31, KEY_MAIL },
-       { KE_KEY, 0x36, KEY_WWW },
-       { KE_KEY, 0x11, KEY_PROG1 },
-       { KE_KEY, 0x12, KEY_PROG2 },
-       { KE_BLUETOOTH, 0x44, 0 },
-       { KE_WIFI, 0x30, 0 },
-       { KE_END, 0 }
+static struct key_entry keymap_acer_aspire_1600[] __initdata = {
+       { KE_KEY, 0x01, {KEY_HELP} },
+       { KE_KEY, 0x03, {KEY_POWER} },
+       { KE_KEY, 0x08, {KEY_MUTE} },
+       { KE_KEY, 0x11, {KEY_PROG1} },
+       { KE_KEY, 0x12, {KEY_PROG2} },
+       { KE_KEY, 0x13, {KEY_PROG3} },
+       { KE_KEY, 0x31, {KEY_MAIL} },
+       { KE_KEY, 0x36, {KEY_WWW} },
+       { KE_KEY, 0x49, {KEY_CONFIG} },
+       { KE_WIFI, 0x30 },
+       { KE_BLUETOOTH, 0x44 },
+       { KE_END, FE_MAIL_LED | FE_UNTESTED }
+};
+
+/* 3020 has been tested */
+static struct key_entry keymap_acer_aspire_5020[] __initdata = {
+       { KE_KEY, 0x01, {KEY_HELP} },
+       { KE_KEY, 0x03, {KEY_POWER} },
+       { KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */
+       { KE_KEY, 0x11, {KEY_PROG1} },
+       { KE_KEY, 0x12, {KEY_PROG2} },
+       { KE_KEY, 0x31, {KEY_MAIL} },
+       { KE_KEY, 0x36, {KEY_WWW} },
+       { KE_KEY, 0x6a, {KEY_CONFIG} },
+       { KE_WIFI, 0x30 },
+       { KE_BLUETOOTH, 0x44 },
+       { KE_END, FE_MAIL_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_2410[] __initdata = {
+       { KE_KEY, 0x01, {KEY_HELP} },
+       { KE_KEY, 0x6d, {KEY_POWER} },
+       { KE_KEY, 0x11, {KEY_PROG1} },
+       { KE_KEY, 0x12, {KEY_PROG2} },
+       { KE_KEY, 0x31, {KEY_MAIL} },
+       { KE_KEY, 0x36, {KEY_WWW} },
+       { KE_KEY, 0x6a, {KEY_CONFIG} },
+       { KE_WIFI, 0x30 },
+       { KE_BLUETOOTH, 0x44 },
+       { KE_END, FE_MAIL_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_110[] __initdata = {
+       { KE_KEY, 0x01, {KEY_HELP} },
+       { KE_KEY, 0x02, {KEY_CONFIG} },
+       { KE_KEY, 0x03, {KEY_POWER} },
+       { KE_KEY, 0x08, {KEY_MUTE} },
+       { KE_KEY, 0x11, {KEY_PROG1} },
+       { KE_KEY, 0x12, {KEY_PROG2} },
+       { KE_KEY, 0x20, {KEY_VOLUMEUP} },
+       { KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
+       { KE_KEY, 0x31, {KEY_MAIL} },
+       { KE_KEY, 0x36, {KEY_WWW} },
+       { KE_SW, 0x4a, {.sw = {SW_LID, 1}} }, /* lid close */
+       { KE_SW, 0x4b, {.sw = {SW_LID, 0}} }, /* lid open */
+       { KE_WIFI, 0x30 },
+       { KE_END, FE_MAIL_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_300[] __initdata = {
+       { KE_KEY, 0x01, {KEY_HELP} },
+       { KE_KEY, 0x02, {KEY_CONFIG} },
+       { KE_KEY, 0x03, {KEY_POWER} },
+       { KE_KEY, 0x08, {KEY_MUTE} },
+       { KE_KEY, 0x11, {KEY_PROG1} },
+       { KE_KEY, 0x12, {KEY_PROG2} },
+       { KE_KEY, 0x20, {KEY_VOLUMEUP} },
+       { KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
+       { KE_KEY, 0x31, {KEY_MAIL} },
+       { KE_KEY, 0x36, {KEY_WWW} },
+       { KE_WIFI, 0x30 },
+       { KE_BLUETOOTH, 0x44 },
+       { KE_END, FE_MAIL_LED | FE_UNTESTED }
 };
 
-static struct key_entry keymap_aopen_1559as[] = {
-       { KE_KEY,  0x01, KEY_HELP },
-       { KE_KEY,  0x06, KEY_PROG3 },
-       { KE_KEY,  0x11, KEY_PROG1 },
-       { KE_KEY,  0x12, KEY_PROG2 },
-       { KE_WIFI, 0x30, 0 },
-       { KE_KEY,  0x31, KEY_MAIL },
-       { KE_KEY,  0x36, KEY_WWW },
+static struct key_entry keymap_acer_travelmate_380[] __initdata = {
+       { KE_KEY, 0x01, {KEY_HELP} },
+       { KE_KEY, 0x02, {KEY_CONFIG} },
+       { KE_KEY, 0x03, {KEY_POWER} }, /* not 370 */
+       { KE_KEY, 0x11, {KEY_PROG1} },
+       { KE_KEY, 0x12, {KEY_PROG2} },
+       { KE_KEY, 0x13, {KEY_PROG3} },
+       { KE_KEY, 0x31, {KEY_MAIL} },
+       { KE_KEY, 0x36, {KEY_WWW} },
+       { KE_WIFI, 0x30 },
+       { KE_END, FE_MAIL_LED | FE_UNTESTED }
+};
+
+/* unusual map */
+static struct key_entry keymap_acer_travelmate_220[] __initdata = {
+       { KE_KEY, 0x01, {KEY_HELP} },
+       { KE_KEY, 0x02, {KEY_CONFIG} },
+       { KE_KEY, 0x11, {KEY_MAIL} },
+       { KE_KEY, 0x12, {KEY_WWW} },
+       { KE_KEY, 0x13, {KEY_PROG2} },
+       { KE_KEY, 0x31, {KEY_PROG1} },
+       { KE_END, FE_WIFI_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_230[] __initdata = {
+       { KE_KEY, 0x01, {KEY_HELP} },
+       { KE_KEY, 0x02, {KEY_CONFIG} },
+       { KE_KEY, 0x11, {KEY_PROG1} },
+       { KE_KEY, 0x12, {KEY_PROG2} },
+       { KE_KEY, 0x31, {KEY_MAIL} },
+       { KE_KEY, 0x36, {KEY_WWW} },
+       { KE_END, FE_WIFI_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_240[] __initdata = {
+       { KE_KEY, 0x01, {KEY_HELP} },
+       { KE_KEY, 0x02, {KEY_CONFIG} },
+       { KE_KEY, 0x03, {KEY_POWER} },
+       { KE_KEY, 0x08, {KEY_MUTE} },
+       { KE_KEY, 0x31, {KEY_MAIL} },
+       { KE_KEY, 0x36, {KEY_WWW} },
+       { KE_KEY, 0x11, {KEY_PROG1} },
+       { KE_KEY, 0x12, {KEY_PROG2} },
+       { KE_BLUETOOTH, 0x44 },
+       { KE_WIFI, 0x30 },
+       { KE_END, FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_350[] __initdata = {
+       { KE_KEY, 0x01, {KEY_HELP} },
+       { KE_KEY, 0x02, {KEY_CONFIG} },
+       { KE_KEY, 0x11, {KEY_PROG1} },
+       { KE_KEY, 0x12, {KEY_PROG2} },
+       { KE_KEY, 0x13, {KEY_MAIL} },
+       { KE_KEY, 0x14, {KEY_PROG3} },
+       { KE_KEY, 0x15, {KEY_WWW} },
+       { KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_acer_travelmate_360[] __initdata = {
+       { KE_KEY, 0x01, {KEY_HELP} },
+       { KE_KEY, 0x02, {KEY_CONFIG} },
+       { KE_KEY, 0x11, {KEY_PROG1} },
+       { KE_KEY, 0x12, {KEY_PROG2} },
+       { KE_KEY, 0x13, {KEY_MAIL} },
+       { KE_KEY, 0x14, {KEY_PROG3} },
+       { KE_KEY, 0x15, {KEY_WWW} },
+       { KE_KEY, 0x40, {KEY_WLAN} },
+       { KE_END, FE_WIFI_LED | FE_UNTESTED } /* no mail led */
+};
+
+/* Wifi subsystem only activates the led. Therefore we need to pass
+ * wifi event as a normal key, then userspace can really change the wifi state.
+ * TODO we need to export led state to userspace (wifi and mail) */
+static struct key_entry keymap_acer_travelmate_610[] __initdata = {
+       { KE_KEY, 0x01, {KEY_HELP} },
+       { KE_KEY, 0x02, {KEY_CONFIG} },
+       { KE_KEY, 0x11, {KEY_PROG1} },
+       { KE_KEY, 0x12, {KEY_PROG2} },
+       { KE_KEY, 0x13, {KEY_PROG3} },
+       { KE_KEY, 0x14, {KEY_MAIL} },
+       { KE_KEY, 0x15, {KEY_WWW} },
+       { KE_KEY, 0x40, {KEY_WLAN} },
+       { KE_END, FE_MAIL_LED | FE_WIFI_LED }
+};
+
+static struct key_entry keymap_acer_travelmate_630[] __initdata = {
+       { KE_KEY, 0x01, {KEY_HELP} },
+       { KE_KEY, 0x02, {KEY_CONFIG} },
+       { KE_KEY, 0x03, {KEY_POWER} },
+       { KE_KEY, 0x08, {KEY_MUTE} }, /* not 620 */
+       { KE_KEY, 0x11, {KEY_PROG1} },
+       { KE_KEY, 0x12, {KEY_PROG2} },
+       { KE_KEY, 0x13, {KEY_PROG3} },
+       { KE_KEY, 0x20, {KEY_VOLUMEUP} },
+       { KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
+       { KE_KEY, 0x31, {KEY_MAIL} },
+       { KE_KEY, 0x36, {KEY_WWW} },
+       { KE_WIFI, 0x30 },
+       { KE_END, FE_MAIL_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_aopen_1559as[] __initdata = {
+       { KE_KEY,  0x01, {KEY_HELP} },
+       { KE_KEY,  0x06, {KEY_PROG3} },
+       { KE_KEY,  0x11, {KEY_PROG1} },
+       { KE_KEY,  0x12, {KEY_PROG2} },
+       { KE_WIFI, 0x30 },
+       { KE_KEY,  0x31, {KEY_MAIL} },
+       { KE_KEY,  0x36, {KEY_WWW} },
        { KE_END,  0 },
 };
 
-static struct key_entry keymap_fs_amilo_d88x0[] = {
-       { KE_KEY, 0x01, KEY_HELP },
-       { KE_KEY, 0x08, KEY_MUTE },
-       { KE_KEY, 0x31, KEY_MAIL },
-       { KE_KEY, 0x36, KEY_WWW },
-       { KE_KEY, 0x11, KEY_PROG1 },
-       { KE_KEY, 0x12, KEY_PROG2 },
-       { KE_KEY, 0x13, KEY_PROG3 },
+static struct key_entry keymap_fs_amilo_d88x0[] __initdata = {
+       { KE_KEY, 0x01, {KEY_HELP} },
+       { KE_KEY, 0x08, {KEY_MUTE} },
+       { KE_KEY, 0x31, {KEY_MAIL} },
+       { KE_KEY, 0x36, {KEY_WWW} },
+       { KE_KEY, 0x11, {KEY_PROG1} },
+       { KE_KEY, 0x12, {KEY_PROG2} },
+       { KE_KEY, 0x13, {KEY_PROG3} },
+       { KE_END, FE_MAIL_LED | FE_WIFI_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_wistron_md2900[] __initdata = {
+       { KE_KEY, 0x01, {KEY_HELP} },
+       { KE_KEY, 0x02, {KEY_CONFIG} },
+       { KE_KEY, 0x11, {KEY_PROG1} },
+       { KE_KEY, 0x12, {KEY_PROG2} },
+       { KE_KEY, 0x31, {KEY_MAIL} },
+       { KE_KEY, 0x36, {KEY_WWW} },
+       { KE_WIFI, 0x30 },
+       { KE_END, FE_MAIL_LED | FE_UNTESTED }
+};
+
+static struct key_entry keymap_wistron_md96500[] __initdata = {
+       { KE_KEY, 0x01, {KEY_HELP} },
+       { KE_KEY, 0x02, {KEY_CONFIG} },
+       { KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */
+       { KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
+       { KE_KEY, 0x08, {KEY_MUTE} },
+       { KE_KEY, 0x11, {KEY_PROG1} },
+       { KE_KEY, 0x12, {KEY_PROG2} },
+       { KE_KEY, 0x20, {KEY_VOLUMEUP} },
+       { KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
+       { KE_KEY, 0x22, {KEY_REWIND} },
+       { KE_KEY, 0x23, {KEY_FORWARD} },
+       { KE_KEY, 0x24, {KEY_PLAYPAUSE} },
+       { KE_KEY, 0x25, {KEY_STOPCD} },
+       { KE_KEY, 0x31, {KEY_MAIL} },
+       { KE_KEY, 0x36, {KEY_WWW} },
+       { KE_WIFI, 0x30 },
+       { KE_BLUETOOTH, 0x44 },
+       { KE_END, FE_UNTESTED }
+};
+
+static struct key_entry keymap_wistron_generic[] __initdata = {
+       { KE_KEY, 0x01, {KEY_HELP} },
+       { KE_KEY, 0x02, {KEY_CONFIG} },
+       { KE_KEY, 0x03, {KEY_POWER} },
+       { KE_KEY, 0x05, {KEY_SWITCHVIDEOMODE} }, /* Display selection */
+       { KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
+       { KE_KEY, 0x08, {KEY_MUTE} },
+       { KE_KEY, 0x11, {KEY_PROG1} },
+       { KE_KEY, 0x12, {KEY_PROG2} },
+       { KE_KEY, 0x13, {KEY_PROG3} },
+       { KE_KEY, 0x14, {KEY_MAIL} },
+       { KE_KEY, 0x15, {KEY_WWW} },
+       { KE_KEY, 0x20, {KEY_VOLUMEUP} },
+       { KE_KEY, 0x21, {KEY_VOLUMEDOWN} },
+       { KE_KEY, 0x22, {KEY_REWIND} },
+       { KE_KEY, 0x23, {KEY_FORWARD} },
+       { KE_KEY, 0x24, {KEY_PLAYPAUSE} },
+       { KE_KEY, 0x25, {KEY_STOPCD} },
+       { KE_KEY, 0x31, {KEY_MAIL} },
+       { KE_KEY, 0x36, {KEY_WWW} },
+       { KE_KEY, 0x37, {KEY_DISPLAYTOGGLE} }, /* Display on/off */
+       { KE_KEY, 0x40, {KEY_WLAN} },
+       { KE_KEY, 0x49, {KEY_CONFIG} },
+       { KE_SW, 0x4a, {.sw = {SW_LID, 1}} }, /* lid close */
+       { KE_SW, 0x4b, {.sw = {SW_LID, 0}} }, /* lid open */
+       { KE_KEY, 0x6a, {KEY_CONFIG} },
+       { KE_KEY, 0x6d, {KEY_POWER} },
+       { KE_KEY, 0x71, {KEY_STOPCD} },
+       { KE_KEY, 0x72, {KEY_PLAYPAUSE} },
+       { KE_KEY, 0x74, {KEY_REWIND} },
+       { KE_KEY, 0x78, {KEY_FORWARD} },
+       { KE_WIFI, 0x30 },
+       { KE_BLUETOOTH, 0x44 },
        { KE_END, 0 }
 };
 
@@ -390,6 +648,133 @@ static struct dmi_system_id dmi_ids[] __initdata = {
        },
        {
                .callback = dmi_matched,
+               .ident = "Acer Aspire 1600",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1600"),
+               },
+               .driver_data = keymap_acer_aspire_1600
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Acer Aspire 3020",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3020"),
+               },
+               .driver_data = keymap_acer_aspire_5020
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Acer Aspire 5020",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5020"),
+               },
+               .driver_data = keymap_acer_aspire_5020
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Acer TravelMate 2100",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2100"),
+               },
+               .driver_data = keymap_acer_aspire_5020
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Acer TravelMate 2410",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2410"),
+               },
+               .driver_data = keymap_acer_travelmate_2410
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Acer TravelMate C300",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C300"),
+               },
+               .driver_data = keymap_acer_travelmate_300
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Acer TravelMate C100",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C100"),
+               },
+               .driver_data = keymap_acer_travelmate_300
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Acer TravelMate C110",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C110"),
+               },
+               .driver_data = keymap_acer_travelmate_110
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Acer TravelMate 380",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 380"),
+               },
+               .driver_data = keymap_acer_travelmate_380
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Acer TravelMate 370",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 370"),
+               },
+               .driver_data = keymap_acer_travelmate_380 /* keyboard minus 1 key */
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Acer TravelMate 220",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 220"),
+               },
+               .driver_data = keymap_acer_travelmate_220
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Acer TravelMate 260",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 260"),
+               },
+               .driver_data = keymap_acer_travelmate_220
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Acer TravelMate 230",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 230"),
+                       /* acerhk looks for "TravelMate F4..." ?! */
+               },
+               .driver_data = keymap_acer_travelmate_230
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Acer TravelMate 280",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 280"),
+               },
+               .driver_data = keymap_acer_travelmate_230
+       },
+       {
+               .callback = dmi_matched,
                .ident = "Acer TravelMate 240",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -399,6 +784,15 @@ static struct dmi_system_id dmi_ids[] __initdata = {
        },
        {
                .callback = dmi_matched,
+               .ident = "Acer TravelMate 250",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 250"),
+               },
+               .driver_data = keymap_acer_travelmate_240
+       },
+       {
+               .callback = dmi_matched,
                .ident = "Acer TravelMate 2424NWXCi",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -408,6 +802,51 @@ static struct dmi_system_id dmi_ids[] __initdata = {
        },
        {
                .callback = dmi_matched,
+               .ident = "Acer TravelMate 350",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 350"),
+               },
+               .driver_data = keymap_acer_travelmate_350
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Acer TravelMate 360",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
+               },
+               .driver_data = keymap_acer_travelmate_360
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Acer TravelMate 610",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 610"),
+               },
+               .driver_data = keymap_acer_travelmate_610
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Acer TravelMate 620",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 620"),
+               },
+               .driver_data = keymap_acer_travelmate_630
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Acer TravelMate 630",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 630"),
+               },
+               .driver_data = keymap_acer_travelmate_630
+       },
+       {
+               .callback = dmi_matched,
                .ident = "AOpen 1559AS",
                .matches = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "E2U"),
@@ -426,6 +865,51 @@ static struct dmi_system_id dmi_ids[] __initdata = {
        },
        {
                .callback = dmi_matched,
+               .ident = "Medion MD 40100",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "WID2000"),
+               },
+               .driver_data = keymap_wistron_md40100
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Medion MD 2900",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2000"),
+               },
+               .driver_data = keymap_wistron_md2900
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Medion MD 96500",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2040"),
+               },
+               .driver_data = keymap_wistron_md96500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Medion MD 95400",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2050"),
+               },
+               .driver_data = keymap_wistron_md96500
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "Fujitsu Siemens Amilo D7820",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), /* not sure */
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Amilo D"),
+               },
+               .driver_data = keymap_fs_amilo_d88x0
+       },
+       {
+               .callback = dmi_matched,
                .ident = "Fujitsu Siemens Amilo D88x0",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
@@ -436,17 +920,39 @@ static struct dmi_system_id dmi_ids[] __initdata = {
        { NULL, }
 };
 
+/* Copy the good keymap, as the original ones are free'd */
+static int __init copy_keymap(void)
+{
+       const struct key_entry *key;
+       struct key_entry *new_keymap;
+       unsigned int length = 1;
+
+       for (key = keymap; key->type != KE_END; key++)
+               length++;
+
+       new_keymap = kmalloc(length * sizeof(struct key_entry), GFP_KERNEL);
+       if (!new_keymap)
+               return -ENOMEM;
+
+       memcpy(new_keymap, keymap, length * sizeof(struct key_entry));
+       keymap = new_keymap;
+
+       return 0;
+}
+
 static int __init select_keymap(void)
 {
+       dmi_check_system(dmi_ids);
        if (keymap_name != NULL) {
                if (strcmp (keymap_name, "1557/MS2141") == 0)
                        keymap = keymap_wistron_ms2141;
+               else if (strcmp (keymap_name, "generic") == 0)
+                       keymap = keymap_wistron_generic;
                else {
                        printk(KERN_ERR "wistron_btns: Keymap unknown\n");
                        return -EINVAL;
                }
        }
-       dmi_check_system(dmi_ids);
        if (keymap == NULL) {
                if (!force) {
                        printk(KERN_ERR "wistron_btns: System unknown\n");
@@ -454,7 +960,8 @@ static int __init select_keymap(void)
                }
                keymap = keymap_empty;
        }
-       return 0;
+
+       return copy_keymap();
 }
 
  /* Input layer interface */
@@ -476,12 +983,28 @@ static int __devinit setup_input_dev(void)
        input_dev->cdev.dev = &wistron_device->dev;
 
        for (key = keymap; key->type != KE_END; key++) {
-               if (key->type == KE_KEY) {
-                       input_dev->evbit[LONG(EV_KEY)] = BIT(EV_KEY);
-                       set_bit(key->keycode, input_dev->keybit);
+               switch (key->type) {
+                       case KE_KEY:
+                               set_bit(EV_KEY, input_dev->evbit);
+                               set_bit(key->keycode, input_dev->keybit);
+                               break;
+
+                       case KE_SW:
+                               set_bit(EV_SW, input_dev->evbit);
+                               set_bit(key->sw.code, input_dev->swbit);
+                               break;
+
+                       default:
+                               ;
                }
        }
 
+       /* reads information flags on KE_END */
+       if (key->code & FE_UNTESTED)
+               printk(KERN_WARNING "Untested laptop multimedia keys, "
+                       "please report success or failure to eric.piel"
+                       "@tremplin-utc.net\n");
+
        error = input_register_device(input_dev);
        if (error) {
                input_free_device(input_dev);
@@ -499,6 +1022,12 @@ static void report_key(unsigned keycode)
        input_sync(input_dev);
 }
 
+static void report_switch(unsigned code, int value)
+{
+       input_report_switch(input_dev, code, value);
+       input_sync(input_dev);
+}
+
  /* Driver core */
 
 static int wifi_enabled;
@@ -519,6 +1048,10 @@ static void handle_key(u8 code)
                                report_key(key->keycode);
                                break;
 
+                       case KE_SW:
+                               report_switch(key->sw.code, key->sw.value);
+                               break;
+
                        case KE_WIFI:
                                if (have_wifi) {
                                        wifi_enabled = !wifi_enabled;
@@ -534,6 +1067,7 @@ static void handle_key(u8 code)
                                break;
 
                        case KE_END:
+                               break;
                        default:
                                BUG();
                        }
@@ -690,6 +1224,7 @@ static void __exit wb_module_exit(void)
        platform_device_unregister(wistron_device);
        platform_driver_unregister(&wistron_driver);
        unmap_bios();
+       kfree(keymap);
 }
 
 module_init(wb_module_init);
index 35d998c..81dd8c7 100644 (file)
@@ -37,6 +37,65 @@ config MOUSE_PS2
          To compile this driver as a module, choose M here: the
          module will be called psmouse.
 
+config MOUSE_PS2_ALPS
+       bool "ALPS PS/2 mouse protocol extension" if EMBEDDED
+       default y
+       depends on MOUSE_PS2
+       ---help---
+         Say Y here if you have an ALPS PS/2 touchpad connected to
+         your system.
+
+         If unsure, say Y.
+
+config MOUSE_PS2_LOGIPS2PP
+       bool "Logictech PS/2++ mouse protocol extension" if EMBEDDED
+       default y
+       depends on MOUSE_PS2
+       ---help---
+         Say Y here if you have a Logictech PS/2++ mouse connected to
+         your system.
+
+         If unsure, say Y.
+
+config MOUSE_PS2_SYNAPTICS
+       bool "Synaptics PS/2 mouse protocol extension" if EMBEDDED
+       default y
+       depends on MOUSE_PS2
+       ---help---
+         Say Y here if you have a Synaptics PS/2 TouchPad connected to
+         your system.
+
+         If unsure, say Y.
+
+config MOUSE_PS2_LIFEBOOK
+       bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED
+       default y
+       depends on MOUSE_PS2
+       ---help---
+         Say Y here if you have a Fujitsu B-series Lifebook PS/2
+         TouchScreen connected to your system.
+
+         If unsure, say Y.
+
+config MOUSE_PS2_TRACKPOINT
+       bool "IBM Trackpoint PS/2 mouse protocol extension" if EMBEDDED
+       default y
+       depends on MOUSE_PS2
+       ---help---
+         Say Y here if you have an IBM Trackpoint PS/2 mouse connected
+         to your system.
+
+         If unsure, say Y.
+
+config MOUSE_PS2_TOUCHKIT
+       bool "eGalax TouchKit PS/2 protocol extension"
+       depends on MOUSE_PS2
+       ---help---
+         Say Y here if you have an eGalax TouchKit PS/2 touchscreen
+         connected to your system.
+
+         If unsure, say N.
+
 config MOUSE_SERIAL
        tristate "Serial mouse"
        select SERIO
@@ -96,6 +155,17 @@ config MOUSE_AMIGA
          To compile this driver as a module, choose M here: the
          module will be called amimouse.
 
+config MOUSE_ATARI
+       tristate "Atari mouse"
+       depends on ATARI
+       select ATARI_KBD_CORE
+       help
+         Say Y here if you have an Atari and want its native mouse
+         supported by the kernel.
+
+         To compile this driver as a module, choose M here: the
+         module will be called atarimouse.
+
 config MOUSE_RISCPC
        tristate "Acorn RiscPC mouse"
        depends on ARCH_ACORN
@@ -118,7 +188,7 @@ config MOUSE_VSXXXAA
          digitizer (VSXXX-AB) DEC produced.
 
 config MOUSE_HIL
-       tristate "HIL pointers (mice etc)."     
+       tristate "HIL pointers (mice etc)."
        depends on GSC || HP300
        select HP_SDC
        select HIL_MLC
index 21a1de6..6a8f622 100644 (file)
@@ -5,6 +5,7 @@
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_MOUSE_AMIGA)      += amimouse.o
+obj-$(CONFIG_MOUSE_ATARI)      += atarimouse.o
 obj-$(CONFIG_MOUSE_RISCPC)     += rpcmouse.o
 obj-$(CONFIG_MOUSE_INPORT)     += inport.o
 obj-$(CONFIG_MOUSE_LOGIBM)     += logibm.o
@@ -14,4 +15,10 @@ obj-$(CONFIG_MOUSE_SERIAL)   += sermouse.o
 obj-$(CONFIG_MOUSE_HIL)                += hil_ptr.o
 obj-$(CONFIG_MOUSE_VSXXXAA)    += vsxxxaa.o
 
-psmouse-objs  := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o trackpoint.o
+psmouse-objs := psmouse-base.o synaptics.o
+
+psmouse-$(CONFIG_MOUSE_PS2_ALPS)       += alps.o
+psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP)  += logips2pp.o
+psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK)   += lifebook.o
+psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o
+psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT)   += touchkit_ps2.o
index 4e71a66..cf3e466 100644 (file)
@@ -424,14 +424,15 @@ int alps_init(struct psmouse *psmouse)
        struct input_dev *dev1 = psmouse->dev, *dev2;
        int version;
 
-       psmouse->private = priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
+       priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
        dev2 = input_allocate_device();
        if (!priv || !dev2)
                goto init_fail;
 
        priv->dev2 = dev2;
 
-       if (!(priv->i = alps_get_model(psmouse, &version)))
+       priv->i = alps_get_model(psmouse, &version);
+       if (!priv->i)
                goto init_fail;
 
        if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 1))
@@ -480,7 +481,8 @@ int alps_init(struct psmouse *psmouse)
        dev2->relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
        dev2->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
 
-       input_register_device(priv->dev2);
+       if (input_register_device(priv->dev2))
+               goto init_fail;
 
        psmouse->protocol_handler = alps_process_byte;
        psmouse->poll = alps_poll;
@@ -491,9 +493,11 @@ int alps_init(struct psmouse *psmouse)
        /* We are having trouble resyncing ALPS touchpads so disable it for now */
        psmouse->resync_time = 0;
 
+       psmouse->private = priv;
        return 0;
 
 init_fail:
+       psmouse_reset(psmouse);
        input_free_device(dev2);
        kfree(priv);
        return -1;
@@ -504,7 +508,8 @@ int alps_detect(struct psmouse *psmouse, int set_properties)
        int version;
        const struct alps_model_info *model;
 
-       if (!(model = alps_get_model(psmouse, &version)))
+       model = alps_get_model(psmouse, &version);
+       if (!model)
                return -1;
 
        if (set_properties) {
index 69db732..4bbddc9 100644 (file)
@@ -12,9 +12,6 @@
 #ifndef _ALPS_H
 #define _ALPS_H
 
-int alps_detect(struct psmouse *psmouse, int set_properties);
-int alps_init(struct psmouse *psmouse);
-
 struct alps_model_info {
         unsigned char signature[3];
         unsigned char byte0, mask0;
@@ -23,10 +20,23 @@ struct alps_model_info {
 
 struct alps_data {
        struct input_dev *dev2;         /* Relative device */
-       char name[32];                  /* Name */
        char phys[32];                  /* Phys */
        const struct alps_model_info *i;/* Info */
        int prev_fin;                   /* Finger bit from previous packet */
 };
 
+#ifdef CONFIG_MOUSE_PS2_ALPS
+int alps_detect(struct psmouse *psmouse, int set_properties);
+int alps_init(struct psmouse *psmouse);
+#else
+inline int alps_detect(struct psmouse *psmouse, int set_properties)
+{
+       return -ENOSYS;
+}
+inline int alps_init(struct psmouse *psmouse)
+{
+       return -ENOSYS;
+}
+#endif /* CONFIG_MOUSE_PS2_ALPS */
+
 #endif
diff --git a/drivers/input/mouse/atarimouse.c b/drivers/input/mouse/atarimouse.c
new file mode 100644 (file)
index 0000000..43ab656
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ *  Atari mouse driver for Linux/m68k
+ *
+ *  Copyright (c) 2005 Michael Schmitz
+ *
+ *  Based on:
+ *  Amiga mouse driver for Linux/m68k
+ *
+ *  Copyright (c) 2000-2002 Vojtech Pavlik
+ *
+ */
+/*
+ * The low level init and interrupt stuff is handled in arch/mm68k/atari/atakeyb.c
+ * (the keyboard ACIA also handles the mouse and joystick data, and the keyboard
+ * interrupt is shared with the MIDI ACIA so MIDI data also get handled there).
+ * This driver only deals with handing key events off to the input layer.
+ *
+ * Largely based on the old:
+ *
+ * Atari Mouse Driver for Linux
+ * by Robert de Vries (robert@and.nl) 19Jul93
+ *
+ * 16 Nov 1994 Andreas Schwab
+ * Compatibility with busmouse
+ * Support for three button mouse (shamelessly stolen from MiNT)
+ * third button wired to one of the joystick directions on joystick 1
+ *
+ * 1996/02/11 Andreas Schwab
+ * Module support
+ * Allow multiple open's
+ *
+ * Converted to use new generic busmouse code.  5 Apr 1998
+ *   Russell King <rmk@arm.uk.linux.org>
+ */
+
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/atarihw.h>
+#include <asm/atarikb.h>
+#include <asm/atariints.h>
+
+MODULE_AUTHOR("Michael Schmitz <schmitz@biophys.uni-duesseldorf.de>");
+MODULE_DESCRIPTION("Atari mouse driver");
+MODULE_LICENSE("GPL");
+
+static int mouse_threshold[2] = {2,2};
+
+#ifdef __MODULE__
+MODULE_PARM(mouse_threshold, "2i");
+#endif
+#ifdef FIXED_ATARI_JOYSTICK
+extern int atari_mouse_buttons;
+#endif
+static int atamouse_used = 0;
+
+static struct input_dev *atamouse_dev;
+
+static void atamouse_interrupt(char *buf)
+{
+       int buttons, dx, dy;
+
+/*     ikbd_mouse_disable(); */
+
+       buttons = (buf[0] & 1) | ((buf[0] & 2) << 1);
+#ifdef FIXED_ATARI_JOYSTICK
+       buttons |= atari_mouse_buttons & 2;
+       atari_mouse_buttons = buttons;
+#endif
+/*     ikbd_mouse_rel_pos(); */
+
+       /* only relative events get here */
+       dx =  buf[1];
+       dy = -buf[2];
+
+       input_report_rel(atamouse_dev, REL_X, dx);
+       input_report_rel(atamouse_dev, REL_Y, dy);
+
+       input_report_key(atamouse_dev, BTN_LEFT,   buttons & 0x1);
+       input_report_key(atamouse_dev, BTN_MIDDLE, buttons & 0x2);
+       input_report_key(atamouse_dev, BTN_RIGHT,  buttons & 0x4);
+
+       input_sync(atamouse_dev);
+
+       return;
+}
+
+static int atamouse_open(struct input_dev *dev)
+{
+       if (atamouse_used++)
+               return 0;
+
+#ifdef FIXED_ATARI_JOYSTICK
+       atari_mouse_buttons = 0;
+#endif
+       ikbd_mouse_y0_top();
+       ikbd_mouse_thresh(mouse_threshold[0], mouse_threshold[1]);
+       ikbd_mouse_rel_pos();
+       atari_input_mouse_interrupt_hook = atamouse_interrupt;
+       return 0;
+}
+
+static void atamouse_close(struct input_dev *dev)
+{
+       if (!--atamouse_used) {
+               ikbd_mouse_disable();
+               atari_mouse_interrupt_hook = NULL;
+       }
+}
+
+static int __init atamouse_init(void)
+{
+       if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP))
+               return -ENODEV;
+
+       if (!(atamouse_dev = input_allocate_device()))
+               return -ENOMEM;
+
+       if (!(atari_keyb_init()))
+               return -ENODEV;
+
+       atamouse_dev->name = "Atari mouse";
+       atamouse_dev->phys = "atamouse/input0";
+       atamouse_dev->id.bustype = BUS_ATARI;
+       atamouse_dev->id.vendor = 0x0001;
+       atamouse_dev->id.product = 0x0002;
+       atamouse_dev->id.version = 0x0100;
+
+       atamouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+       atamouse_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+       atamouse_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+       atamouse_dev->open = atamouse_open;
+       atamouse_dev->close = atamouse_close;
+
+       input_register_device(atamouse_dev);
+
+       printk(KERN_INFO "input: %s at keyboard ACIA\n", atamouse_dev->name);
+       return 0;
+}
+
+static void __exit atamouse_exit(void)
+{
+       input_unregister_device(atamouse_dev);
+}
+
+module_init(atamouse_init);
+module_exit(atamouse_exit);
index bfb174f..449bf4d 100644 (file)
@@ -88,10 +88,12 @@ static void hil_ptr_process_record(struct hil_ptr *ptr)
        idx = ptr->idx4/4;
        p = data[idx - 1];
 
-       if ((p & ~HIL_CMDCT_POL) == 
-           (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report;
-       if ((p & ~HIL_CMDCT_RPL) == 
-           (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report;
+       if ((p & ~HIL_CMDCT_POL) ==
+           (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL))
+               goto report;
+       if ((p & ~HIL_CMDCT_RPL) ==
+           (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL))
+               goto report;
 
        /* Not a poll response.  See if we are loading config records. */
        switch (p & HIL_PKT_DATA_MASK) {
@@ -101,27 +103,32 @@ static void hil_ptr_process_record(struct hil_ptr *ptr)
                for (; i < HIL_PTR_MAX_LENGTH; i++)
                        ptr->idd[i] = 0;
                break;
+
        case HIL_CMD_RSC:
                for (i = 0; i < idx; i++)
                        ptr->rsc[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
                for (; i < HIL_PTR_MAX_LENGTH; i++)
                        ptr->rsc[i] = 0;
                break;
+
        case HIL_CMD_EXD:
                for (i = 0; i < idx; i++)
                        ptr->exd[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
                for (; i < HIL_PTR_MAX_LENGTH; i++)
                        ptr->exd[i] = 0;
                break;
+
        case HIL_CMD_RNM:
                for (i = 0; i < idx; i++)
                        ptr->rnm[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
                for (; i < HIL_PTR_MAX_LENGTH + 1; i++)
-                       ptr->rnm[i] = '\0';
+                       ptr->rnm[i] = 0;
                break;
+
        default:
                /* These occur when device isn't present */
-               if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break; 
+               if (p == (HIL_ERR_INT | HIL_PKT_CMD))
+                       break;
                /* Anything else we'd like to know about. */
                printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p);
                break;
@@ -130,7 +137,8 @@ static void hil_ptr_process_record(struct hil_ptr *ptr)
 
  report:
        if ((p & HIL_CMDCT_POL) != idx - 1) {
-               printk(KERN_WARNING PREFIX "Malformed poll packet %x (idx = %i)\n", p, idx);
+               printk(KERN_WARNING PREFIX
+                       "Malformed poll packet %x (idx = %i)\n", p, idx);
                goto out;
        }
 
@@ -139,7 +147,7 @@ static void hil_ptr_process_record(struct hil_ptr *ptr)
        laxis += i;
 
        ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */
-       absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; 
+       absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS;
 
        for (cnt = 1; i < laxis; i++) {
                unsigned int lo,hi,val;
@@ -157,7 +165,8 @@ static void hil_ptr_process_record(struct hil_ptr *ptr)
                        input_report_abs(dev, ABS_X + i, val);
                } else {
                        val = (int) (((int8_t)lo) | ((int8_t)hi<<8));
-                       if (i%3) val *= -1;
+                       if (i%3)
+                               val *= -1;
                        input_report_rel(dev, REL_X + i, val);
                }
        }
@@ -168,10 +177,11 @@ static void hil_ptr_process_record(struct hil_ptr *ptr)
                btn = ptr->data[cnt++];
                up = btn & 1;
                btn &= 0xfe;
-               if (btn == 0x8e) {
+               if (btn == 0x8e)
                        continue; /* TODO: proximity == touch? */
-               }
-               else if ((btn > 0x8c) || (btn < 0x80)) continue;
+               else
+                       if ((btn > 0x8c) || (btn < 0x80))
+                               continue;
                btn = (btn - 0x80) >> 1;
                btn = ptr->btnmap[btn];
                input_report_key(dev, btn, !up);
@@ -182,14 +192,14 @@ static void hil_ptr_process_record(struct hil_ptr *ptr)
        up(&ptr->sem);
 }
 
-static void hil_ptr_process_err(struct hil_ptr *ptr) {
+static void hil_ptr_process_err(struct hil_ptr *ptr)
+{
        printk(KERN_WARNING PREFIX "errored HIL packet\n");
        ptr->idx4 = 0;
        up(&ptr->sem);
-       return;
 }
 
-static irqreturn_t hil_ptr_interrupt(struct serio *serio, 
+static irqreturn_t hil_ptr_interrupt(struct serio *serio,
         unsigned char data, unsigned int flags)
 {
        struct hil_ptr *ptr;
@@ -197,29 +207,29 @@ static irqreturn_t hil_ptr_interrupt(struct serio *serio,
        int idx;
 
        ptr = serio_get_drvdata(serio);
-       if (ptr == NULL) {
-               BUG();
-               return IRQ_HANDLED;
-       }
+       BUG_ON(ptr == NULL);
 
        if (ptr->idx4 >= (HIL_PTR_MAX_LENGTH * sizeof(hil_packet))) {
                hil_ptr_process_err(ptr);
                return IRQ_HANDLED;
        }
        idx = ptr->idx4/4;
-       if (!(ptr->idx4 % 4)) ptr->data[idx] = 0;
+       if (!(ptr->idx4 % 4))
+               ptr->data[idx] = 0;
        packet = ptr->data[idx];
        packet |= ((hil_packet)data) << ((3 - (ptr->idx4 % 4)) * 8);
        ptr->data[idx] = packet;
 
        /* Records of N 4-byte hil_packets must terminate with a command. */
-       if ((++(ptr->idx4)) % 4) return IRQ_HANDLED;
+       if ((++(ptr->idx4)) % 4)
+               return IRQ_HANDLED;
        if ((packet & 0xffff0000) != HIL_ERR_INT) {
                hil_ptr_process_err(ptr);
                return IRQ_HANDLED;
        }
-       if (packet & HIL_PKT_CMD) 
+       if (packet & HIL_PKT_CMD)
                hil_ptr_process_record(ptr);
+
        return IRQ_HANDLED;
 }
 
@@ -228,10 +238,7 @@ static void hil_ptr_disconnect(struct serio *serio)
        struct hil_ptr *ptr;
 
        ptr = serio_get_drvdata(serio);
-       if (ptr == NULL) {
-               BUG();
-               return;
-       }
+       BUG_ON(ptr == NULL);
 
        serio_close(serio);
        input_unregister_device(ptr->dev);
@@ -241,7 +248,7 @@ static void hil_ptr_disconnect(struct serio *serio)
 static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
 {
        struct hil_ptr   *ptr;
-       char             *txt;
+       const char       *txt;
        unsigned int     i, naxsets, btntype;
        uint8_t          did, *idd;
 
@@ -252,42 +259,40 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
        if (!ptr->dev)
                goto bail0;
 
-       ptr->dev->private = ptr;
-
        if (serio_open(serio, driver))
                goto bail1;
 
        serio_set_drvdata(serio, ptr);
        ptr->serio = serio;
 
-       init_MUTEX_LOCKED(&(ptr->sem));
+       init_MUTEX_LOCKED(&ptr->sem);
 
        /* Get device info.  MLC driver supplies devid/status/etc. */
        serio->write(serio, 0);
        serio->write(serio, 0);
        serio->write(serio, HIL_PKT_CMD >> 8);
        serio->write(serio, HIL_CMD_IDD);
-       down(&(ptr->sem));
+       down(&ptr->sem);
 
        serio->write(serio, 0);
        serio->write(serio, 0);
        serio->write(serio, HIL_PKT_CMD >> 8);
        serio->write(serio, HIL_CMD_RSC);
-       down(&(ptr->sem));
+       down(&ptr->sem);
 
        serio->write(serio, 0);
        serio->write(serio, 0);
        serio->write(serio, HIL_PKT_CMD >> 8);
        serio->write(serio, HIL_CMD_RNM);
-       down(&(ptr->sem));
+       down(&ptr->sem);
 
        serio->write(serio, 0);
        serio->write(serio, 0);
        serio->write(serio, HIL_PKT_CMD >> 8);
        serio->write(serio, HIL_CMD_EXD);
-       down(&(ptr->sem));
+       down(&ptr->sem);
 
-       up(&(ptr->sem));
+       up(&ptr->sem);
 
        did = ptr->idd[0];
        idd = ptr->idd + 1;
@@ -301,12 +306,12 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
                ptr->dev->evbit[0] = BIT(EV_ABS);
                txt = "absolute";
        }
-       if (!ptr->dev->evbit[0]) {
+       if (!ptr->dev->evbit[0])
                goto bail2;
-       }
 
        ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd);
-       if (ptr->nbtn) ptr->dev->evbit[0] |= BIT(EV_KEY);
+       if (ptr->nbtn)
+               ptr->dev->evbit[0] |= BIT(EV_KEY);
 
        naxsets = HIL_IDD_NUM_AXSETS(*idd);
        ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd);
@@ -315,7 +320,7 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
                        did, txt);
        printk(KERN_INFO PREFIX "HIL pointer has %i buttons and %i sets of %i axes\n",
                        ptr->nbtn, naxsets, ptr->naxes);
-       
+
        btntype = BTN_MISC;
        if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET)
 #ifdef TABLET_SIMULATES_MOUSE
@@ -325,7 +330,7 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
 #endif
        if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN)
                btntype = BTN_TOUCH;
-               
+
        if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE)
                btntype = BTN_MOUSE;
 
@@ -341,12 +346,10 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
        }
 
        if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
-               for (i = 0; i < ptr->naxes; i++) {
+               for (i = 0; i < ptr->naxes; i++)
                        set_bit(REL_X + i, ptr->dev->relbit);
-               }
-               for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) {
+               for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++)
                        set_bit(REL_X + i, ptr->dev->relbit);
-               }
        } else {
                for (i = 0; i < ptr->naxes; i++) {
                        set_bit(ABS_X + i, ptr->dev->absbit);
@@ -375,7 +378,7 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
        ptr->dev->id.vendor     = PCI_VENDOR_ID_HP;
        ptr->dev->id.product    = 0x0001; /* TODO: get from ptr->rsc */
        ptr->dev->id.version    = 0x0100; /* TODO: get from ptr->rsc */
-       ptr->dev->cdev.dev      = &serio->dev;
+       ptr->dev->dev.parent    = &serio->dev;
 
        input_register_device(ptr->dev);
        printk(KERN_INFO "input: %s (%s), ID: %d\n",
@@ -419,11 +422,11 @@ static int __init hil_ptr_init(void)
 {
        return serio_register_driver(&hil_ptr_serio_driver);
 }
-                
+
 static void __exit hil_ptr_exit(void)
 {
        serio_unregister_driver(&hil_ptr_serio_driver);
 }
-                        
+
 module_init(hil_ptr_init);
 module_exit(hil_ptr_exit);
index 29542f0..1740cad 100644 (file)
 #include "psmouse.h"
 #include "lifebook.h"
 
+struct lifebook_data {
+       struct input_dev *dev2;         /* Relative device */
+       char phys[32];
+};
+
+static const char *desired_serio_phys;
+
+static int lifebook_set_serio_phys(struct dmi_system_id *d)
+{
+       desired_serio_phys = d->driver_data;
+       return 0;
+}
+
+static unsigned char lifebook_use_6byte_proto;
+
+static int lifebook_set_6byte_proto(struct dmi_system_id *d)
+{
+       lifebook_use_6byte_proto = 1;
+       return 0;
+}
+
 static struct dmi_system_id lifebook_dmi_table[] = {
        {
                .ident = "FLORA-ie 55mi",
@@ -56,6 +77,24 @@ static struct dmi_system_id lifebook_dmi_table[] = {
                .matches = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"),
                },
+               .callback = lifebook_set_serio_phys,
+               .driver_data = "isa0060/serio3",
+       },
+       {
+               .ident = "Panasonic CF-28",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "CF-28"),
+               },
+               .callback = lifebook_set_6byte_proto,
+       },
+       {
+               .ident = "Panasonic CF-29",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"),
+               },
+               .callback = lifebook_set_6byte_proto,
        },
        {
                .ident = "Lifebook B142",
@@ -68,30 +107,70 @@ static struct dmi_system_id lifebook_dmi_table[] = {
 
 static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse)
 {
+       struct lifebook_data *priv = psmouse->private;
+       struct input_dev *dev1 = psmouse->dev;
+       struct input_dev *dev2 = priv->dev2;
        unsigned char *packet = psmouse->packet;
-       struct input_dev *dev = psmouse->dev;
+       int relative_packet = packet[0] & 0x08;
 
-       if (psmouse->pktcnt != 3)
-               return PSMOUSE_GOOD_DATA;
+       if (relative_packet || !lifebook_use_6byte_proto) {
+               if (psmouse->pktcnt != 3)
+                       return PSMOUSE_GOOD_DATA;
+       } else {
+               switch (psmouse->pktcnt) {
+               case 1:
+                       return (packet[0] & 0xf8) == 0x00 ?
+                               PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
+               case 2:
+                       return PSMOUSE_GOOD_DATA;
+               case 3:
+                       return ((packet[2] & 0x30) << 2) == (packet[2] & 0xc0) ?
+                               PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
+               case 4:
+                       return (packet[3] & 0xf8) == 0xc0 ?
+                               PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
+               case 5:
+                       return (packet[4] & 0xc0) == (packet[2] & 0xc0) ?
+                               PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
+               case 6:
+                       if (((packet[5] & 0x30) << 2) != (packet[5] & 0xc0))
+                               return PSMOUSE_BAD_DATA;
+                       if ((packet[5] & 0xc0) != (packet[1] & 0xc0))
+                               return PSMOUSE_BAD_DATA;
+                       break; /* report data */
+               }
+       }
 
-       /* calculate X and Y */
-       if ((packet[0] & 0x08) == 0x00) {
-               input_report_abs(dev, ABS_X,
+       if (relative_packet) {
+               if (!dev2)
+                       printk(KERN_WARNING "lifebook.c: got relative packet "
+                               "but no relative device set up\n");
+       } else if (lifebook_use_6byte_proto) {
+               input_report_abs(dev1, ABS_X,
+                                ((packet[1] & 0x3f) << 6) | (packet[2] & 0x3f));
+               input_report_abs(dev1, ABS_Y,
+                                4096 - (((packet[4] & 0x3f) << 6) | (packet[5] & 0x3f)));
+       } else {
+               input_report_abs(dev1, ABS_X,
                                 (packet[1] | ((packet[0] & 0x30) << 4)));
-               input_report_abs(dev, ABS_Y,
+               input_report_abs(dev1, ABS_Y,
                                 1024 - (packet[2] | ((packet[0] & 0xC0) << 2)));
-       } else {
-               input_report_rel(dev, REL_X,
-                               ((packet[0] & 0x10) ? packet[1] - 256 : packet[1]));
-               input_report_rel(dev, REL_Y,
-                                -(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2]));
        }
 
-       input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
-       input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
-       input_report_key(dev, BTN_TOUCH, packet[0] & 0x04);
+       input_report_key(dev1, BTN_TOUCH, packet[0] & 0x04);
+       input_sync(dev1);
 
-       input_sync(dev);
+       if (dev2) {
+               if (relative_packet) {
+                       input_report_rel(dev2, REL_X,
+                               ((packet[0] & 0x10) ? packet[1] - 256 : packet[1]));
+                       input_report_rel(dev2, REL_Y,
+                                -(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2]));
+               }
+               input_report_key(dev2, BTN_LEFT, packet[0] & 0x01);
+               input_report_key(dev2, BTN_RIGHT, packet[0] & 0x02);
+               input_sync(dev2);
+       }
 
        return PSMOUSE_FULL_PACKET;
 }
@@ -109,12 +188,20 @@ static int lifebook_absolute_mode(struct psmouse *psmouse)
           you leave this call out the touchsreen will never send
           absolute coordinates
        */
-       param = 0x07;
+       param = lifebook_use_6byte_proto ? 0x08 : 0x07;
        ps2_command(ps2dev, &param, PSMOUSE_CMD_SETRES);
 
        return 0;
 }
 
+static void lifebook_relative_mode(struct psmouse *psmouse)
+{
+       struct ps2dev *ps2dev = &psmouse->ps2dev;
+       unsigned char param = 0x06;
+
+       ps2_command(ps2dev, &param, PSMOUSE_CMD_SETRES);
+}
+
 static void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolution)
 {
        static const unsigned char params[] = { 0, 1, 2, 2, 3 };
@@ -131,6 +218,8 @@ static void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolu
 static void lifebook_disconnect(struct psmouse *psmouse)
 {
        psmouse_reset(psmouse);
+       kfree(psmouse->private);
+       psmouse->private = NULL;
 }
 
 int lifebook_detect(struct psmouse *psmouse, int set_properties)
@@ -138,6 +227,10 @@ int lifebook_detect(struct psmouse *psmouse, int set_properties)
         if (!dmi_check_system(lifebook_dmi_table))
                 return -1;
 
+       if (desired_serio_phys &&
+           strcmp(psmouse->ps2dev.serio->phys, desired_serio_phys))
+               return -1;
+
        if (set_properties) {
                psmouse->vendor = "Fujitsu";
                psmouse->name = "Lifebook TouchScreen";
@@ -146,24 +239,78 @@ int lifebook_detect(struct psmouse *psmouse, int set_properties)
         return 0;
 }
 
+static int lifebook_create_relative_device(struct psmouse *psmouse)
+{
+       struct input_dev *dev2;
+       struct lifebook_data *priv;
+       int error = -ENOMEM;
+
+       priv = kzalloc(sizeof(struct lifebook_data), GFP_KERNEL);
+       dev2 = input_allocate_device();
+       if (!priv || !dev2)
+               goto err_out;
+
+       priv->dev2 = dev2;
+       snprintf(priv->phys, sizeof(priv->phys),
+                "%s/input1", psmouse->ps2dev.serio->phys);
+
+       dev2->phys = priv->phys;
+       dev2->name = "PS/2 Touchpad";
+       dev2->id.bustype = BUS_I8042;
+       dev2->id.vendor  = 0x0002;
+       dev2->id.product = PSMOUSE_LIFEBOOK;
+       dev2->id.version = 0x0000;
+       dev2->dev.parent = &psmouse->ps2dev.serio->dev;
+
+       dev2->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+       dev2->relbit[LONG(REL_X)] = BIT(REL_X) | BIT(REL_Y);
+       dev2->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
+
+       error = input_register_device(priv->dev2);
+       if (error)
+               goto err_out;
+
+       psmouse->private = priv;
+       return 0;
+
+ err_out:
+       input_free_device(dev2);
+       kfree(priv);
+       return error;
+}
+
 int lifebook_init(struct psmouse *psmouse)
 {
-       struct input_dev *input_dev = psmouse->dev;
+       struct input_dev *dev1 = psmouse->dev;
+       int max_coord = lifebook_use_6byte_proto ? 1024 : 4096;
 
        if (lifebook_absolute_mode(psmouse))
                return -1;
 
-       input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
-       input_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
-       input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-       input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
-       input_set_abs_params(input_dev, ABS_X, 0, 1024, 0, 0);
-       input_set_abs_params(input_dev, ABS_Y, 0, 1024, 0, 0);
+       dev1->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
+       dev1->relbit[0] = 0;
+       dev1->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+       input_set_abs_params(dev1, ABS_X, 0, max_coord, 0, 0);
+       input_set_abs_params(dev1, ABS_Y, 0, max_coord, 0, 0);
+
+       if (!desired_serio_phys) {
+               if (lifebook_create_relative_device(psmouse)) {
+                       lifebook_relative_mode(psmouse);
+                       return -1;
+               }
+       }
 
        psmouse->protocol_handler = lifebook_process_byte;
        psmouse->set_resolution = lifebook_set_resolution;
        psmouse->disconnect = lifebook_disconnect;
        psmouse->reconnect  = lifebook_absolute_mode;
+
+       psmouse->model = lifebook_use_6byte_proto ? 6 : 3;
+
+       /*
+        * Use packet size = 3 even when using 6-byte protocol because
+        * that's what POLL will return on Lifebooks (according to spec).
+        */
        psmouse->pktsize = 3;
 
        return 0;
index be1c094..c1647cf 100644 (file)
 #ifndef _LIFEBOOK_H
 #define _LIFEBOOK_H
 
+#ifdef CONFIG_MOUSE_PS2_LIFEBOOK
 int lifebook_detect(struct psmouse *psmouse, int set_properties);
 int lifebook_init(struct psmouse *psmouse);
+#else
+inline int lifebook_detect(struct psmouse *psmouse, int set_properties)
+{
+       return -ENOSYS;
+}
+inline int lifebook_init(struct psmouse *psmouse)
+{
+       return -ENOSYS;
+}
+#endif
 
 #endif
index d3ddea2..9df74b7 100644 (file)
@@ -200,6 +200,7 @@ static void ps2pp_disconnect(struct psmouse *psmouse)
 static const struct ps2pp_info *get_model_info(unsigned char model)
 {
        static const struct ps2pp_info ps2pp_list[] = {
+               {  1,   0,                      0 },    /* Simple 2-button mouse */
                { 12,   0,                      PS2PP_SIDE_BTN},
                { 13,   0,                      0 },
                { 15,   PS2PP_KIND_MX,                                  /* MX1000 */
@@ -338,12 +339,12 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
        param[1] = 0;
        ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
 
-       if (!param[1])
-               return -1;
-
        model = ((param[0] >> 4) & 0x07) | ((param[0] << 3) & 0x78);
        buttons = param[1];
 
+       if (!model || !buttons)
+               return -1;
+
        if ((model_info = get_model_info(model)) != NULL) {
 
 /*
index 64a8ec5..6e57125 100644 (file)
 #ifndef _LOGIPS2PP_H
 #define _LOGIPS2PP_H
 
+#ifdef CONFIG_MOUSE_PS2_LOGIPS2PP
 int ps2pp_init(struct psmouse *psmouse, int set_properties);
+#else
+inline int ps2pp_init(struct psmouse *psmouse, int set_properties)
+{
+       return -ENOSYS;
+}
+#endif /* CONFIG_MOUSE_PS2_LOGIPS2PP */
 
 #endif
index 0fe5869..f15f695 100644 (file)
@@ -28,6 +28,7 @@
 #include "alps.h"
 #include "lifebook.h"
 #include "trackpoint.h"
+#include "touchkit_ps2.h"
 
 #define DRIVER_DESC    "PS/2 mouse driver"
 
@@ -569,7 +570,9 @@ static int psmouse_extensions(struct psmouse *psmouse,
                return PSMOUSE_THINKPS;
 
 /*
- * Try Synaptics TouchPad
+ * Try Synaptics TouchPad. Note that probing is done even if Synaptics protocol
+ * support is disabled in config - we need to know if it is synaptics so we
+ * can reset it properly after probing for intellimouse.
  */
        if (max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse, set_properties) == 0) {
                synaptics_hardware = 1;
@@ -605,14 +608,20 @@ static int psmouse_extensions(struct psmouse *psmouse,
                }
        }
 
-       if (max_proto > PSMOUSE_IMEX && genius_detect(psmouse, set_properties) == 0)
-               return PSMOUSE_GENPS;
+       if (max_proto > PSMOUSE_IMEX) {
+
+               if (genius_detect(psmouse, set_properties) == 0)
+                       return PSMOUSE_GENPS;
 
-       if (max_proto > PSMOUSE_IMEX && ps2pp_init(psmouse, set_properties) == 0)
-               return PSMOUSE_PS2PP;
+               if (ps2pp_init(psmouse, set_properties) == 0)
+                       return PSMOUSE_PS2PP;
 
-       if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0)
-               return PSMOUSE_TRACKPOINT;
+               if (trackpoint_detect(psmouse, set_properties) == 0)
+                       return PSMOUSE_TRACKPOINT;
+
+               if (touchkit_ps2_detect(psmouse, set_properties) == 0)
+                       return PSMOUSE_TOUCHKIT_PS2;
+       }
 
 /*
  * Reset to defaults in case the device got confused by extended
@@ -654,12 +663,14 @@ static const struct psmouse_protocol psmouse_protocols[] = {
                .maxproto       = 1,
                .detect         = ps2bare_detect,
        },
+#ifdef CONFIG_MOUSE_PS2_LOGIPS2PP
        {
                .type           = PSMOUSE_PS2PP,
                .name           = "PS2++",
                .alias          = "logitech",
                .detect         = ps2pp_init,
        },
+#endif
        {
                .type           = PSMOUSE_THINKPS,
                .name           = "ThinkPS/2",
@@ -686,6 +697,7 @@ static const struct psmouse_protocol psmouse_protocols[] = {
                .maxproto       = 1,
                .detect         = im_explorer_detect,
        },
+#ifdef CONFIG_MOUSE_PS2_SYNAPTICS
        {
                .type           = PSMOUSE_SYNAPTICS,
                .name           = "SynPS/2",
@@ -693,6 +705,8 @@ static const struct psmouse_protocol psmouse_protocols[] = {
                .detect         = synaptics_detect,
                .init           = synaptics_init,
        },
+#endif
+#ifdef CONFIG_MOUSE_PS2_ALPS
        {
                .type           = PSMOUSE_ALPS,
                .name           = "AlpsPS/2",
@@ -700,18 +714,31 @@ static const struct psmouse_protocol psmouse_protocols[] = {
                .detect         = alps_detect,
                .init           = alps_init,
        },
+#endif
+#ifdef CONFIG_MOUSE_PS2_LIFEBOOK
        {
                .type           = PSMOUSE_LIFEBOOK,
                .name           = "LBPS/2",
                .alias          = "lifebook",
                .init           = lifebook_init,
        },
+#endif
+#ifdef CONFIG_MOUSE_PS2_TRACKPOINT
        {
                .type           = PSMOUSE_TRACKPOINT,
                .name           = "TPPS/2",
                .alias          = "trackpoint",
                .detect         = trackpoint_detect,
        },
+#endif
+#ifdef CONFIG_MOUSE_PS2_TOUCHKIT
+       {
+               .type           = PSMOUSE_TOUCHKIT_PS2,
+               .name           = "touchkitPS/2",
+               .alias          = "touchkit",
+               .detect         = touchkit_ps2_detect,
+       },
+#endif
        {
                .type           = PSMOUSE_AUTO,
                .name           = "auto",
@@ -823,12 +850,6 @@ static void psmouse_set_rate(struct psmouse *psmouse, unsigned int rate)
 static void psmouse_initialize(struct psmouse *psmouse)
 {
 /*
- * We set the mouse into streaming mode.
- */
-
-       ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM);
-
-/*
  * We set the mouse report rate, resolution and scaling.
  */
 
@@ -1062,8 +1083,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, const struct psmouse
 {
        struct input_dev *input_dev = psmouse->dev;
 
-       input_dev->private = psmouse;
-       input_dev->cdev.dev = &psmouse->ps2dev.serio->dev;
+       input_dev->dev.parent = &psmouse->ps2dev.serio->dev;
 
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
        input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
index cf1de95..3964e8a 100644 (file)
@@ -87,6 +87,7 @@ enum psmouse_type {
        PSMOUSE_ALPS,
        PSMOUSE_LIFEBOOK,
        PSMOUSE_TRACKPOINT,
+       PSMOUSE_TOUCHKIT_PS2,
        PSMOUSE_AUTO            /* This one should always be last */
 };
 
index a85d747..77b8ee2 100644 (file)
@@ -69,7 +69,8 @@ static void sermouse_process_msc(struct sermouse *sermouse, signed char data)
        switch (sermouse->count) {
 
                case 0:
-                       if ((data & 0xf8) != 0x80) return;
+                       if ((data & 0xf8) != 0x80)
+                               return;
                        input_report_key(dev, BTN_LEFT,   !(data & 4));
                        input_report_key(dev, BTN_RIGHT,  !(data & 1));
                        input_report_key(dev, BTN_MIDDLE, !(data & 2));
@@ -107,7 +108,10 @@ static void sermouse_process_ms(struct sermouse *sermouse, signed char data)
        struct input_dev *dev = sermouse->dev;
        signed char *buf = sermouse->buf;
 
-       if (data & 0x40) sermouse->count = 0;
+       if (data & 0x40)
+               sermouse->count = 0;
+       else if (sermouse->count == 0)
+               return;
 
        switch (sermouse->count) {
 
@@ -169,7 +173,8 @@ static void sermouse_process_ms(struct sermouse *sermouse, signed char data)
 
                case 5:
                case 7: /* Ignore anything besides MZ++ */
-                       if (sermouse->type != SERIO_MZPP) break;
+                       if (sermouse->type != SERIO_MZPP)
+                               break;
 
                        switch (buf[1]) {
 
@@ -206,13 +211,16 @@ static irqreturn_t sermouse_interrupt(struct serio *serio,
 {
        struct sermouse *sermouse = serio_get_drvdata(serio);
 
-       if (time_after(jiffies, sermouse->last + HZ/10)) sermouse->count = 0;
+       if (time_after(jiffies, sermouse->last + HZ/10))
+               sermouse->count = 0;
+
        sermouse->last = jiffies;
 
        if (sermouse->type > SERIO_SUN)
                sermouse_process_ms(sermouse, data);
        else
                sermouse_process_msc(sermouse, data);
+
        return IRQ_HANDLED;
 }
 
@@ -258,12 +266,11 @@ static int sermouse_connect(struct serio *serio, struct serio_driver *drv)
        input_dev->id.vendor  = sermouse->type;
        input_dev->id.product = c;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &serio->dev;
+       input_dev->dev.parent = &serio->dev;
 
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
        input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
        input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
-       input_dev->private = sermouse;
 
        if (c & 0x01) set_bit(BTN_MIDDLE, input_dev->keybit);
        if (c & 0x02) set_bit(BTN_SIDE, input_dev->keybit);
index f0f9413..c77788b 100644 (file)
 #define YMIN_NOMINAL 1408
 #define YMAX_NOMINAL 4448
 
+
 /*****************************************************************************
- *     Synaptics communications functions
+ *     Stuff we need even when we do not want native Synaptics support
  ****************************************************************************/
 
 /*
- * Send a command to the synpatics touchpad by special commands
+ * Set the synaptics touchpad mode byte by special commands
  */
-static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param)
+static int synaptics_mode_cmd(struct psmouse *psmouse, unsigned char mode)
 {
-       if (psmouse_sliced_command(psmouse, c))
+       unsigned char param[1];
+
+       if (psmouse_sliced_command(psmouse, mode))
                return -1;
-       if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO))
+       param[0] = SYN_PS_SET_MODE2;
+       if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_SETRATE))
                return -1;
        return 0;
 }
 
+int synaptics_detect(struct psmouse *psmouse, int set_properties)
+{
+       struct ps2dev *ps2dev = &psmouse->ps2dev;
+       unsigned char param[4];
+
+       param[0] = 0;
+
+       ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+       ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+       ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+       ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
+       ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
+
+       if (param[1] != 0x47)
+               return -ENODEV;
+
+       if (set_properties) {
+               psmouse->vendor = "Synaptics";
+               psmouse->name = "TouchPad";
+       }
+
+       return 0;
+}
+
+void synaptics_reset(struct psmouse *psmouse)
+{
+       /* reset touchpad back to relative mode, gestures enabled */
+       synaptics_mode_cmd(psmouse, 0);
+}
+
+#ifdef CONFIG_MOUSE_PS2_SYNAPTICS
+
+/*****************************************************************************
+ *     Synaptics communications functions
+ ****************************************************************************/
+
 /*
- * Set the synaptics touchpad mode byte by special commands
+ * Send a command to the synpatics touchpad by special commands
  */
-static int synaptics_mode_cmd(struct psmouse *psmouse, unsigned char mode)
+static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param)
 {
-       unsigned char param[1];
-
-       if (psmouse_sliced_command(psmouse, mode))
+       if (psmouse_sliced_command(psmouse, c))
                return -1;
-       param[0] = SYN_PS_SET_MODE2;
-       if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_SETRATE))
+       if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO))
                return -1;
        return 0;
 }
@@ -529,12 +566,6 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
        clear_bit(REL_Y, dev->relbit);
 }
 
-void synaptics_reset(struct psmouse *psmouse)
-{
-       /* reset touchpad back to relative mode, gestures enabled */
-       synaptics_mode_cmd(psmouse, 0);
-}
-
 static void synaptics_disconnect(struct psmouse *psmouse)
 {
        synaptics_reset(psmouse);
@@ -569,30 +600,6 @@ static int synaptics_reconnect(struct psmouse *psmouse)
        return 0;
 }
 
-int synaptics_detect(struct psmouse *psmouse, int set_properties)
-{
-       struct ps2dev *ps2dev = &psmouse->ps2dev;
-       unsigned char param[4];
-
-       param[0] = 0;
-
-       ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
-       ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
-       ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
-       ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
-       ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
-
-       if (param[1] != 0x47)
-               return -1;
-
-       if (set_properties) {
-               psmouse->vendor = "Synaptics";
-               psmouse->name = "TouchPad";
-       }
-
-       return 0;
-}
-
 #if defined(__i386__)
 #include <linux/dmi.h>
 static struct dmi_system_id toshiba_dmi_table[] = {
@@ -648,6 +655,16 @@ int synaptics_init(struct psmouse *psmouse)
 
        set_input_params(psmouse->dev, priv);
 
+       /*
+        * Encode touchpad model so that it can be used to set
+        * input device->id.version and be visible to userspace.
+        * Because version is __u16 we have to drop something.
+        * Hardware info bits seem to be good candidates as they
+        * are documented to be for Synaptics corp. internal use.
+        */
+       psmouse->model = ((priv->model_id & 0x00ff0000) >> 8) |
+                         (priv->model_id & 0x000000ff);
+
        psmouse->protocol_handler = synaptics_process_byte;
        psmouse->set_rate = synaptics_set_rate;
        psmouse->disconnect = synaptics_disconnect;
@@ -680,4 +697,12 @@ int synaptics_init(struct psmouse *psmouse)
        return -1;
 }
 
+#else /* CONFIG_MOUSE_PS2_SYNAPTICS */
+
+int synaptics_init(struct psmouse *psmouse)
+{
+       return -ENOSYS;
+}
+
+#endif /* CONFIG_MOUSE_PS2_SYNAPTICS */
 
index 68fff1d..02aa4cf 100644 (file)
@@ -9,10 +9,6 @@
 #ifndef _SYNAPTICS_H
 #define _SYNAPTICS_H
 
-extern int synaptics_detect(struct psmouse *psmouse, int set_properties);
-extern int synaptics_init(struct psmouse *psmouse);
-extern void synaptics_reset(struct psmouse *psmouse);
-
 /* synaptics queries */
 #define SYN_QUE_IDENTIFY               0x00
 #define SYN_QUE_MODES                  0x01
@@ -62,9 +58,9 @@ extern void synaptics_reset(struct psmouse *psmouse);
 #define SYN_MODE_WMODE(m)              ((m) & (1 << 0))
 
 /* synaptics identify query bits */
-#define SYN_ID_MODEL(i)                (((i) >> 4) & 0x0f)
-#define SYN_ID_MAJOR(i)                ((i) & 0x0f)
-#define SYN_ID_MINOR(i)                (((i) >> 16) & 0xff)
+#define SYN_ID_MODEL(i)                        (((i) >> 4) & 0x0f)
+#define SYN_ID_MAJOR(i)                        ((i) & 0x0f)
+#define SYN_ID_MINOR(i)                        (((i) >> 16) & 0xff)
 #define SYN_ID_IS_SYNAPTICS(i)         ((((i) >> 8) & 0xff) == 0x47)
 
 /* synaptics special commands */
@@ -98,8 +94,8 @@ struct synaptics_hw_state {
 struct synaptics_data {
        /* Data read from the touchpad */
        unsigned long int model_id;             /* Model-ID */
-       unsigned long int capabilities;         /* Capabilities */
-       unsigned long int ext_cap;              /* Extended Capabilities */
+       unsigned long int capabilities;         /* Capabilities */
+       unsigned long int ext_cap;              /* Extended Capabilities */
        unsigned long int identity;             /* Identification */
 
        unsigned char pkt_type;                 /* packet type - old, new, etc */
@@ -107,4 +103,8 @@ struct synaptics_data {
        int scroll;
 };
 
+int synaptics_detect(struct psmouse *psmouse, int set_properties);
+int synaptics_init(struct psmouse *psmouse);
+void synaptics_reset(struct psmouse *psmouse);
+
 #endif /* _SYNAPTICS_H */
diff --git a/drivers/input/mouse/touchkit_ps2.c b/drivers/input/mouse/touchkit_ps2.c
new file mode 100644 (file)
index 0000000..7b977fd
--- /dev/null
@@ -0,0 +1,100 @@
+/* ----------------------------------------------------------------------------
+ * touchkit_ps2.c  --  Driver for eGalax TouchKit PS/2 Touchscreens
+ *
+ * Copyright (C) 2005 by Stefan Lucke
+ * Copyright (C) 2004 by Daniel Ritz
+ * Copyright (C) by Todd E. Johnson (mtouchusb.c)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Based upon touchkitusb.c
+ *
+ * Vendor documentation is available in support section of:
+ * http://www.egalax.com.tw/
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/libps2.h>
+
+#include "psmouse.h"
+#include "touchkit_ps2.h"
+
+#define TOUCHKIT_MAX_XC                        0x07ff
+#define TOUCHKIT_MAX_YC                        0x07ff
+
+#define TOUCHKIT_CMD                   0x0a
+#define TOUCHKIT_CMD_LENGTH            1
+
+#define TOUCHKIT_CMD_ACTIVE            'A'
+#define TOUCHKIT_CMD_FIRMWARE_VERSION  'D'
+#define TOUCHKIT_CMD_CONTROLLER_TYPE   'E'
+
+#define TOUCHKIT_SEND_PARMS(s, r, c)   ((s) << 12 | (r) << 8 | (c))
+
+#define TOUCHKIT_GET_TOUCHED(packet)   (((packet)[0]) & 0x01)
+#define TOUCHKIT_GET_X(packet)         (((packet)[1] << 7) | (packet)[2])
+#define TOUCHKIT_GET_Y(packet)         (((packet)[3] << 7) | (packet)[4])
+
+static psmouse_ret_t touchkit_ps2_process_byte(struct psmouse *psmouse)
+{
+       unsigned char *packet = psmouse->packet;
+       struct input_dev *dev = psmouse->dev;
+
+       if (psmouse->pktcnt != 5)
+               return PSMOUSE_GOOD_DATA;
+
+       input_report_abs(dev, ABS_X, TOUCHKIT_GET_X(packet));
+       input_report_abs(dev, ABS_Y, TOUCHKIT_GET_Y(packet));
+       input_report_key(dev, BTN_TOUCH, TOUCHKIT_GET_TOUCHED(packet));
+       input_sync(dev);
+
+       return PSMOUSE_FULL_PACKET;
+}
+
+int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties)
+{
+       struct input_dev *dev = psmouse->dev;
+       unsigned char param[3];
+       int command;
+
+       param[0] = TOUCHKIT_CMD_LENGTH;
+       param[1] = TOUCHKIT_CMD_ACTIVE;
+       command = TOUCHKIT_SEND_PARMS(2, 3, TOUCHKIT_CMD);
+
+       if (ps2_command(&psmouse->ps2dev, param, command))
+               return -ENODEV;
+
+       if (param[0] != TOUCHKIT_CMD || param[1] != 0x01 ||
+           param[2] != TOUCHKIT_CMD_ACTIVE)
+               return -ENODEV;
+
+       if (set_properties) {
+               dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+               set_bit(BTN_TOUCH, dev->keybit);
+               input_set_abs_params(dev, ABS_X, 0, TOUCHKIT_MAX_XC, 0, 0);
+               input_set_abs_params(dev, ABS_Y, 0, TOUCHKIT_MAX_YC, 0, 0);
+
+               psmouse->vendor = "eGalax";
+               psmouse->name = "Touchscreen";
+               psmouse->protocol_handler = touchkit_ps2_process_byte;
+               psmouse->pktsize = 5;
+       }
+
+       return 0;
+}
diff --git a/drivers/input/mouse/touchkit_ps2.h b/drivers/input/mouse/touchkit_ps2.h
new file mode 100644 (file)
index 0000000..61e9dfd
--- /dev/null
@@ -0,0 +1,24 @@
+/* ----------------------------------------------------------------------------
+ * touchkit_ps2.h  --  Driver for eGalax TouchKit PS/2 Touchscreens
+ *
+ * Copyright (C) 2005 by Stefan Lucke
+ * Copyright (c) 2005 Vojtech Pavlik
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef _TOUCHKIT_PS2_H
+#define _TOUCHKIT_PS2_H
+
+#ifdef CONFIG_MOUSE_PS2_TOUCHKIT
+int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties);
+#else
+inline int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties)
+{
+       return -ENOSYS;
+}
+#endif /* CONFIG_MOUSE_PS2_TOUCHKIT */
+
+#endif
index 050298b..c10a6e7 100644 (file)
@@ -142,6 +142,13 @@ struct trackpoint_data
        unsigned char ext_dev;
 };
 
-extern int trackpoint_detect(struct psmouse *psmouse, int set_properties);
+#ifdef CONFIG_MOUSE_PS2_TRACKPOINT
+int trackpoint_detect(struct psmouse *psmouse, int set_properties);
+#else
+inline int trackpoint_detect(struct psmouse *psmouse, int set_properties)
+{
+       return -ENOSYS;
+}
+#endif /* CONFIG_MOUSE_PS2_TRACKPOINT */
 
 #endif /* _TRACKPOINT_H */
index c3d64fc..4a32157 100644 (file)
@@ -508,8 +508,7 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
        input_dev->name = mouse->name;
        input_dev->phys = mouse->phys;
        input_dev->id.bustype = BUS_RS232;
-       input_dev->cdev.dev = &serio->dev;
-       input_dev->private = mouse;
+       input_dev->dev.parent = &serio->dev;
 
        set_bit (EV_KEY, input_dev->evbit);             /* We have buttons */
        set_bit (EV_REL, input_dev->evbit);
index 664bcc8..7678e98 100644 (file)
@@ -63,9 +63,12 @@ struct mousedev {
        int minor;
        char name[16];
        wait_queue_head_t wait;
-       struct list_head list;
+       struct list_head client_list;
        struct input_handle handle;
 
+       struct list_head mixdev_node;
+       int mixdev_open;
+
        struct mousedev_hw_data packet;
        unsigned int pkt_count;
        int old_x[4], old_y[4];
@@ -85,7 +88,7 @@ struct mousedev_motion {
 };
 
 #define PACKET_QUEUE_LEN       16
-struct mousedev_list {
+struct mousedev_client {
        struct fasync_struct *fasync;
        struct mousedev *mousedev;
        struct list_head node;
@@ -111,6 +114,7 @@ static struct input_handler mousedev_handler;
 
 static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
 static struct mousedev mousedev_mix;
+static LIST_HEAD(mousedev_mix_list);
 
 #define fx(i)  (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
 #define fy(i)  (mousedev->old_y[(mousedev->pkt_count - (i)) & 03])
@@ -120,32 +124,33 @@ static void mousedev_touchpad_event(struct input_dev *dev, struct mousedev *mous
        int size, tmp;
        enum { FRACTION_DENOM = 128 };
 
-       if (mousedev->touch) {
-               size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
-               if (size == 0)
-                       size = 256 * 2;
-
-               switch (code) {
-                       case ABS_X:
-                               fx(0) = value;
-                               if (mousedev->pkt_count >= 2) {
-                                       tmp = ((value - fx(2)) * (256 * FRACTION_DENOM)) / size;
-                                       tmp += mousedev->frac_dx;
-                                       mousedev->packet.dx = tmp / FRACTION_DENOM;
-                                       mousedev->frac_dx = tmp - mousedev->packet.dx * FRACTION_DENOM;
-                               }
-                               break;
+       switch (code) {
+               case ABS_X:
+                       fx(0) = value;
+                       if (mousedev->touch && mousedev->pkt_count >= 2) {
+                               size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
+                               if (size == 0)
+                                       size = 256 * 2;
+                               tmp = ((value - fx(2)) * (256 * FRACTION_DENOM)) / size;
+                               tmp += mousedev->frac_dx;
+                               mousedev->packet.dx = tmp / FRACTION_DENOM;
+                               mousedev->frac_dx = tmp - mousedev->packet.dx * FRACTION_DENOM;
+                       }
+                       break;
 
-                       case ABS_Y:
-                               fy(0) = value;
-                               if (mousedev->pkt_count >= 2) {
-                                       tmp = -((value - fy(2)) * (256 * FRACTION_DENOM)) / size;
-                                       tmp += mousedev->frac_dy;
-                                       mousedev->packet.dy = tmp / FRACTION_DENOM;
-                                       mousedev->frac_dy = tmp - mousedev->packet.dy * FRACTION_DENOM;
-                               }
-                               break;
-               }
+               case ABS_Y:
+                       fy(0) = value;
+                       if (mousedev->touch && mousedev->pkt_count >= 2) {
+                               /* use X size to keep the same scale */
+                               size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
+                               if (size == 0)
+                                       size = 256 * 2;
+                               tmp = -((value - fy(2)) * (256 * FRACTION_DENOM)) / size;
+                               tmp += mousedev->frac_dy;
+                               mousedev->packet.dy = tmp / FRACTION_DENOM;
+                               mousedev->frac_dy = tmp - mousedev->packet.dy * FRACTION_DENOM;
+                       }
+                       break;
        }
 }
 
@@ -223,47 +228,47 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int
 
 static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_hw_data *packet)
 {
-       struct mousedev_list *list;
+       struct mousedev_client *client;
        struct mousedev_motion *p;
        unsigned long flags;
        int wake_readers = 0;
 
-       list_for_each_entry(list, &mousedev->list, node) {
-               spin_lock_irqsave(&list->packet_lock, flags);
+       list_for_each_entry(client, &mousedev->client_list, node) {
+               spin_lock_irqsave(&client->packet_lock, flags);
 
-               p = &list->packets[list->head];
-               if (list->ready && p->buttons != mousedev->packet.buttons) {
-                       unsigned int new_head = (list->head + 1) % PACKET_QUEUE_LEN;
-                       if (new_head != list->tail) {
-                               p = &list->packets[list->head = new_head];
+               p = &client->packets[client->head];
+               if (client->ready && p->buttons != mousedev->packet.buttons) {
+                       unsigned int new_head = (client->head + 1) % PACKET_QUEUE_LEN;
+                       if (new_head != client->tail) {
+                               p = &client->packets[client->head = new_head];
                                memset(p, 0, sizeof(struct mousedev_motion));
                        }
                }
 
                if (packet->abs_event) {
-                       p->dx += packet->x - list->pos_x;
-                       p->dy += packet->y - list->pos_y;
-                       list->pos_x = packet->x;
-                       list->pos_y = packet->y;
+                       p->dx += packet->x - client->pos_x;
+                       p->dy += packet->y - client->pos_y;
+                       client->pos_x = packet->x;
+                       client->pos_y = packet->y;
                }
 
-               list->pos_x += packet->dx;
-               list->pos_x = list->pos_x < 0 ? 0 : (list->pos_x >= xres ? xres : list->pos_x);
-               list->pos_y += packet->dy;
-               list->pos_y = list->pos_y < 0 ? 0 : (list->pos_y >= yres ? yres : list->pos_y);
+               client->pos_x += packet->dx;
+               client->pos_x = client->pos_x < 0 ? 0 : (client->pos_x >= xres ? xres : client->pos_x);
+               client->pos_y += packet->dy;
+               client->pos_y = client->pos_y < 0 ? 0 : (client->pos_y >= yres ? yres : client->pos_y);
 
                p->dx += packet->dx;
                p->dy += packet->dy;
                p->dz += packet->dz;
                p->buttons = mousedev->packet.buttons;
 
-               if (p->dx || p->dy || p->dz || p->buttons != list->last_buttons)
-                       list->ready = 1;
+               if (p->dx || p->dy || p->dz || p->buttons != client->last_buttons)
+                       client->ready = 1;
 
-               spin_unlock_irqrestore(&list->packet_lock, flags);
+               spin_unlock_irqrestore(&client->packet_lock, flags);
 
-               if (list->ready) {
-                       kill_fasync(&list->fasync, SIGIO, POLL_IN);
+               if (client->ready) {
+                       kill_fasync(&client->fasync, SIGIO, POLL_IN);
                        wake_readers = 1;
                }
        }
@@ -351,9 +356,9 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
 static int mousedev_fasync(int fd, struct file *file, int on)
 {
        int retval;
-       struct mousedev_list *list = file->private_data;
+       struct mousedev_client *client = file->private_data;
 
-       retval = fasync_helper(fd, file, on, &list->fasync);
+       retval = fasync_helper(fd, file, on, &client->fasync);
 
        return retval < 0 ? retval : 0;
 }
@@ -364,50 +369,95 @@ static void mousedev_free(struct mousedev *mousedev)
        kfree(mousedev);
 }
 
-static void mixdev_release(void)
+static int mixdev_add_device(struct mousedev *mousedev)
 {
-       struct input_handle *handle;
+       int error;
 
-       list_for_each_entry(handle, &mousedev_handler.h_list, h_node) {
-               struct mousedev *mousedev = handle->private;
+       if (mousedev_mix.open) {
+               error = input_open_device(&mousedev->handle);
+               if (error)
+                       return error;
 
-               if (!mousedev->open) {
-                       if (mousedev->exist)
-                               input_close_device(&mousedev->handle);
-                       else
-                               mousedev_free(mousedev);
+               mousedev->open++;
+               mousedev->mixdev_open++;
+       }
+
+       list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list);
+
+       return 0;
+}
+
+static void mixdev_remove_device(struct mousedev *mousedev)
+{
+       if (mousedev->mixdev_open) {
+               mousedev->mixdev_open = 0;
+               if (!--mousedev->open && mousedev->exist)
+                       input_close_device(&mousedev->handle);
+       }
+
+       list_del_init(&mousedev->mixdev_node);
+}
+
+static void mixdev_open_devices(void)
+{
+       struct mousedev *mousedev;
+
+       list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
+               if (mousedev->exist && !mousedev->open) {
+                       if (input_open_device(&mousedev->handle))
+                               continue;
+
+                       mousedev->open++;
+                       mousedev->mixdev_open++;
+               }
+       }
+}
+
+static void mixdev_close_devices(void)
+{
+       struct mousedev *mousedev, *next;
+
+       list_for_each_entry_safe(mousedev, next, &mousedev_mix_list, mixdev_node) {
+               if (mousedev->mixdev_open) {
+                       mousedev->mixdev_open = 0;
+                       if (!--mousedev->open) {
+                               if (mousedev->exist)
+                                       input_close_device(&mousedev->handle);
+                               else
+                                       mousedev_free(mousedev);
+                       }
                }
        }
 }
 
-static int mousedev_release(struct inode * inode, struct file * file)
+static int mousedev_release(struct inode *inode, struct file *file)
 {
-       struct mousedev_list *list = file->private_data;
+       struct mousedev_client *client = file->private_data;
+       struct mousedev *mousedev = client->mousedev;
 
        mousedev_fasync(-1, file, 0);
 
-       list_del(&list->node);
+       list_del(&client->node);
+       kfree(client);
 
-       if (!--list->mousedev->open) {
-               if (list->mousedev->minor == MOUSEDEV_MIX)
-                       mixdev_release();
-               else if (!mousedev_mix.open) {
-                       if (list->mousedev->exist)
-                               input_close_device(&list->mousedev->handle);
-                       else
-                               mousedev_free(list->mousedev);
-               }
+       if (!--mousedev->open) {
+               if (mousedev->minor == MOUSEDEV_MIX)
+                       mixdev_close_devices();
+               else if (mousedev->exist)
+                       input_close_device(&mousedev->handle);
+               else
+                       mousedev_free(mousedev);
        }
 
-       kfree(list);
        return 0;
 }
 
-static int mousedev_open(struct inode * inode, struct file * file)
+
+static int mousedev_open(struct inode *inode, struct file *file)
 {
-       struct mousedev_list *list;
-       struct input_handle *handle;
+       struct mousedev_client *client;
        struct mousedev *mousedev;
+       int error;
        int i;
 
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
@@ -417,31 +467,37 @@ static int mousedev_open(struct inode * inode, struct file * file)
 #endif
                i = iminor(inode) - MOUSEDEV_MINOR_BASE;
 
-       if (i >= MOUSEDEV_MINORS || !mousedev_table[i])
+       if (i >= MOUSEDEV_MINORS)
+               return -ENODEV;
+
+       mousedev = mousedev_table[i];
+       if (!mousedev)
                return -ENODEV;
 
-       if (!(list = kzalloc(sizeof(struct mousedev_list), GFP_KERNEL)))
+       client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL);
+       if (!client)
                return -ENOMEM;
 
-       spin_lock_init(&list->packet_lock);
-       list->pos_x = xres / 2;
-       list->pos_y = yres / 2;
-       list->mousedev = mousedev_table[i];
-       list_add_tail(&list->node, &mousedev_table[i]->list);
-       file->private_data = list;
-
-       if (!list->mousedev->open++) {
-               if (list->mousedev->minor == MOUSEDEV_MIX) {
-                       list_for_each_entry(handle, &mousedev_handler.h_list, h_node) {
-                               mousedev = handle->private;
-                               if (!mousedev->open && mousedev->exist)
-                                       input_open_device(handle);
+       spin_lock_init(&client->packet_lock);
+       client->pos_x = xres / 2;
+       client->pos_y = yres / 2;
+       client->mousedev = mousedev;
+       list_add_tail(&client->node, &mousedev->client_list);
+
+       if (!mousedev->open++) {
+               if (mousedev->minor == MOUSEDEV_MIX)
+                       mixdev_open_devices();
+               else if (mousedev->exist) {
+                       error = input_open_device(&mousedev->handle);
+                       if (error) {
+                               list_del(&client->node);
+                               kfree(client);
+                               return error;
                        }
-               } else
-                       if (!mousedev_mix.open && list->mousedev->exist)
-                               input_open_device(&list->mousedev->handle);
+               }
        }
 
+       file->private_data = client;
        return 0;
 }
 
@@ -450,13 +506,13 @@ static inline int mousedev_limit_delta(int delta, int limit)
        return delta > limit ? limit : (delta < -limit ? -limit : delta);
 }
 
-static void mousedev_packet(struct mousedev_list *list, signed char *ps2_data)
+static void mousedev_packet(struct mousedev_client *client, signed char *ps2_data)
 {
        struct mousedev_motion *p;
        unsigned long flags;
 
-       spin_lock_irqsave(&list->packet_lock, flags);
-       p = &list->packets[list->tail];
+       spin_lock_irqsave(&client->packet_lock, flags);
+       p = &client->packets[client->tail];
 
        ps2_data[0] = 0x08 | ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07);
        ps2_data[1] = mousedev_limit_delta(p->dx, 127);
@@ -464,44 +520,44 @@ static void mousedev_packet(struct mousedev_list *list, signed char *ps2_data)
        p->dx -= ps2_data[1];
        p->dy -= ps2_data[2];
 
-       switch (list->mode) {
+       switch (client->mode) {
                case MOUSEDEV_EMUL_EXPS:
                        ps2_data[3] = mousedev_limit_delta(p->dz, 7);
                        p->dz -= ps2_data[3];
                        ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1);
-                       list->bufsiz = 4;
+                       client->bufsiz = 4;
                        break;
 
                case MOUSEDEV_EMUL_IMPS:
                        ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
                        ps2_data[3] = mousedev_limit_delta(p->dz, 127);
                        p->dz -= ps2_data[3];
-                       list->bufsiz = 4;
+                       client->bufsiz = 4;
                        break;
 
                case MOUSEDEV_EMUL_PS2:
                default:
                        ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
                        p->dz = 0;
-                       list->bufsiz = 3;
+                       client->bufsiz = 3;
                        break;
        }
 
        if (!p->dx && !p->dy && !p->dz) {
-               if (list->tail == list->head) {
-                       list->ready = 0;
-                       list->last_buttons = p->buttons;
+               if (client->tail == client->head) {
+                       client->ready = 0;
+                       client->last_buttons = p->buttons;
                } else
-                       list->tail = (list->tail + 1) % PACKET_QUEUE_LEN;
+                       client->tail = (client->tail + 1) % PACKET_QUEUE_LEN;
        }
 
-       spin_unlock_irqrestore(&list->packet_lock, flags);
+       spin_unlock_irqrestore(&client->packet_lock, flags);
 }
 
 
-static ssize_t mousedev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
+static ssize_t mousedev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
-       struct mousedev_list *list = file->private_data;
+       struct mousedev_client *client = file->private_data;
        unsigned char c;
        unsigned int i;
 
@@ -510,95 +566,95 @@ static ssize_t mousedev_write(struct file * file, const char __user * buffer, si
                if (get_user(c, buffer + i))
                        return -EFAULT;
 
-               if (c == mousedev_imex_seq[list->imexseq]) {
-                       if (++list->imexseq == MOUSEDEV_SEQ_LEN) {
-                               list->imexseq = 0;
-                               list->mode = MOUSEDEV_EMUL_EXPS;
+               if (c == mousedev_imex_seq[client->imexseq]) {
+                       if (++client->imexseq == MOUSEDEV_SEQ_LEN) {
+                               client->imexseq = 0;
+                               client->mode = MOUSEDEV_EMUL_EXPS;
                        }
                } else
-                       list->imexseq = 0;
+                       client->imexseq = 0;
 
-               if (c == mousedev_imps_seq[list->impsseq]) {
-                       if (++list->impsseq == MOUSEDEV_SEQ_LEN) {
-                               list->impsseq = 0;
-                               list->mode = MOUSEDEV_EMUL_IMPS;
+               if (c == mousedev_imps_seq[client->impsseq]) {
+                       if (++client->impsseq == MOUSEDEV_SEQ_LEN) {
+                               client->impsseq = 0;
+                               client->mode = MOUSEDEV_EMUL_IMPS;
                        }
                } else
-                       list->impsseq = 0;
+                       client->impsseq = 0;
 
-               list->ps2[0] = 0xfa;
+               client->ps2[0] = 0xfa;
 
                switch (c) {
 
                        case 0xeb: /* Poll */
-                               mousedev_packet(list, &list->ps2[1]);
-                               list->bufsiz++; /* account for leading ACK */
+                               mousedev_packet(client, &client->ps2[1]);
+                               client->bufsiz++; /* account for leading ACK */
                                break;
 
                        case 0xf2: /* Get ID */
-                               switch (list->mode) {
-                                       case MOUSEDEV_EMUL_PS2:  list->ps2[1] = 0; break;
-                                       case MOUSEDEV_EMUL_IMPS: list->ps2[1] = 3; break;
-                                       case MOUSEDEV_EMUL_EXPS: list->ps2[1] = 4; break;
+                               switch (client->mode) {
+                                       case MOUSEDEV_EMUL_PS2:  client->ps2[1] = 0; break;
+                                       case MOUSEDEV_EMUL_IMPS: client->ps2[1] = 3; break;
+                                       case MOUSEDEV_EMUL_EXPS: client->ps2[1] = 4; break;
                                }
-                               list->bufsiz = 2;
+                               client->bufsiz = 2;
                                break;
 
                        case 0xe9: /* Get info */
-                               list->ps2[1] = 0x60; list->ps2[2] = 3; list->ps2[3] = 200;
-                               list->bufsiz = 4;
+                               client->ps2[1] = 0x60; client->ps2[2] = 3; client->ps2[3] = 200;
+                               client->bufsiz = 4;
                                break;
 
                        case 0xff: /* Reset */
-                               list->impsseq = list->imexseq = 0;
-                               list->mode = MOUSEDEV_EMUL_PS2;
-                               list->ps2[1] = 0xaa; list->ps2[2] = 0x00;
-                               list->bufsiz = 3;
+                               client->impsseq = client->imexseq = 0;
+                               client->mode = MOUSEDEV_EMUL_PS2;
+                               client->ps2[1] = 0xaa; client->ps2[2] = 0x00;
+                               client->bufsiz = 3;
                                break;
 
                        default:
-                               list->bufsiz = 1;
+                               client->bufsiz = 1;
                                break;
                }
 
-               list->buffer = list->bufsiz;
+               client->buffer = client->bufsiz;
        }
 
-       kill_fasync(&list->fasync, SIGIO, POLL_IN);
+       kill_fasync(&client->fasync, SIGIO, POLL_IN);
 
-       wake_up_interruptible(&list->mousedev->wait);
+       wake_up_interruptible(&client->mousedev->wait);
 
        return count;
 }
 
-static ssize_t mousedev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
+static ssize_t mousedev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
-       struct mousedev_list *list = file->private_data;
+       struct mousedev_client *client = file->private_data;
        int retval = 0;
 
-       if (!list->ready && !list->buffer && (file->f_flags & O_NONBLOCK))
+       if (!client->ready && !client->buffer && (file->f_flags & O_NONBLOCK))
                return -EAGAIN;
 
-       retval = wait_event_interruptible(list->mousedev->wait,
-                                         !list->mousedev->exist || list->ready || list->buffer);
+       retval = wait_event_interruptible(client->mousedev->wait,
+                                         !client->mousedev->exist || client->ready || client->buffer);
 
        if (retval)
                return retval;
 
-       if (!list->mousedev->exist)
+       if (!client->mousedev->exist)
                return -ENODEV;
 
-       if (!list->buffer && list->ready) {
-               mousedev_packet(list, list->ps2);
-               list->buffer = list->bufsiz;
+       if (!client->buffer && client->ready) {
+               mousedev_packet(client, client->ps2);
+               client->buffer = client->bufsiz;
        }
 
-       if (count > list->buffer)
-               count = list->buffer;
+       if (count > client->buffer)
+               count = client->buffer;
 
-       list->buffer -= count;
+       client->buffer -= count;
 
-       if (copy_to_user(buffer, list->ps2 + list->bufsiz - list->buffer - count, count))
+       if (copy_to_user(buffer, client->ps2 + client->bufsiz - client->buffer - count, count))
                return -EFAULT;
 
        return count;
@@ -607,11 +663,12 @@ static ssize_t mousedev_read(struct file * file, char __user * buffer, size_t co
 /* No kernel lock - fine */
 static unsigned int mousedev_poll(struct file *file, poll_table *wait)
 {
-       struct mousedev_list *list = file->private_data;
+       struct mousedev_client *client = file->private_data;
+       struct mousedev *mousedev = client->mousedev;
 
-       poll_wait(file, &list->mousedev->wait, wait);
-       return ((list->ready || list->buffer) ? (POLLIN | POLLRDNORM) : 0) |
-               (list->mousedev->exist ? 0 : (POLLHUP | POLLERR));
+       poll_wait(file, &mousedev->wait, wait);
+       return ((client->ready || client->buffer) ? (POLLIN | POLLRDNORM) : 0) |
+               (mousedev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
 static const struct file_operations mousedev_fops = {
@@ -624,23 +681,27 @@ static const struct file_operations mousedev_fops = {
        .fasync =       mousedev_fasync,
 };
 
-static struct input_handle *mousedev_connect(struct input_handler *handler, struct input_dev *dev,
-                                            const struct input_device_id *id)
+static int mousedev_connect(struct input_handler *handler, struct input_dev *dev,
+                           const struct input_device_id *id)
 {
        struct mousedev *mousedev;
        struct class_device *cdev;
-       int minor = 0;
+       dev_t devt;
+       int minor;
+       int error;
 
        for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
        if (minor == MOUSEDEV_MINORS) {
                printk(KERN_ERR "mousedev: no more free mousedev devices\n");
-               return NULL;
+               return -ENFILE;
        }
 
-       if (!(mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL)))
-               return NULL;
+       mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
+       if (!mousedev)
+               return -ENOMEM;
 
-       INIT_LIST_HEAD(&mousedev->list);
+       INIT_LIST_HEAD(&mousedev->client_list);
+       INIT_LIST_HEAD(&mousedev->mixdev_node);
        init_waitqueue_head(&mousedev->wait);
 
        mousedev->minor = minor;
@@ -651,42 +712,66 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru
        mousedev->handle.private = mousedev;
        sprintf(mousedev->name, "mouse%d", minor);
 
-       if (mousedev_mix.open)
-               input_open_device(&mousedev->handle);
-
        mousedev_table[minor] = mousedev;
 
-       cdev = class_device_create(&input_class, &dev->cdev,
-                       MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
-                       dev->cdev.dev, mousedev->name);
+       devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
+
+       cdev = class_device_create(&input_class, &dev->cdev, devt,
+                                  dev->cdev.dev, mousedev->name);
+       if (IS_ERR(cdev)) {
+               error = PTR_ERR(cdev);
+               goto err_free_mousedev;
+       }
 
        /* temporary symlink to keep userspace happy */
-       sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
-                         mousedev->name);
+       error = sysfs_create_link(&input_class.subsys.kobj,
+                                 &cdev->kobj, mousedev->name);
+       if (error)
+               goto err_cdev_destroy;
+
+       error = input_register_handle(&mousedev->handle);
+       if (error)
+               goto err_remove_link;
+
+       error = mixdev_add_device(mousedev);
+       if (error)
+               goto err_unregister_handle;
+
+       return 0;
 
-       return &mousedev->handle;
+ err_unregister_handle:
+       input_unregister_handle(&mousedev->handle);
+ err_remove_link:
+       sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
+ err_cdev_destroy:
+       class_device_destroy(&input_class, devt);
+ err_free_mousedev:
+       mousedev_table[minor] = NULL;
+       kfree(mousedev);
+       return error;
 }
 
 static void mousedev_disconnect(struct input_handle *handle)
 {
        struct mousedev *mousedev = handle->private;
-       struct mousedev_list *list;
+       struct mousedev_client *client;
 
-       sysfs_remove_link(&input_class.subsys.kset.kobj, mousedev->name);
+       input_unregister_handle(handle);
+
+       sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
        class_device_destroy(&input_class,
                        MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
        mousedev->exist = 0;
 
+       mixdev_remove_device(mousedev);
+
        if (mousedev->open) {
                input_close_device(handle);
                wake_up_interruptible(&mousedev->wait);
-               list_for_each_entry(list, &mousedev->list, node)
-                       kill_fasync(&list->fasync, SIGIO, POLL_HUP);
-       } else {
-               if (mousedev_mix.open)
-                       input_close_device(handle);
+               list_for_each_entry(client, &mousedev->client_list, node)
+                       kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+       } else
                mousedev_free(mousedev);
-       }
 }
 
 static const struct input_device_id mousedev_ids[] = {
@@ -714,7 +799,7 @@ static const struct input_device_id mousedev_ids[] = {
                .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_TOOL_WIDTH) },
        },      /* A touchpad */
 
-       { },    /* Terminating entry */
+       { },    /* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE(input, mousedev_ids);
@@ -746,7 +831,7 @@ static int __init mousedev_init(void)
                return error;
 
        memset(&mousedev_mix, 0, sizeof(struct mousedev));
-       INIT_LIST_HEAD(&mousedev_mix.list);
+       INIT_LIST_HEAD(&mousedev_mix.client_list);
        init_waitqueue_head(&mousedev_mix.wait);
        mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
        mousedev_mix.exist = 1;
diff --git a/drivers/input/power.c b/drivers/input/power.c
deleted file mode 100644 (file)
index ee82464..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * $Id: power.c,v 1.10 2001/09/25 09:17:15 vojtech Exp $
- *
- *  Copyright (c) 2001 "Crazy" James Simmons
- *
- *  Input driver Power Management.
- *
- *  Sponsored by Transvirtual Technology.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so by
- * e-mail - mail your message to <jsimmons@transvirtual.com>.
- */
-
-#include <linux/module.h>
-#include <linux/input.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/tty.h>
-#include <linux/delay.h>
-#include <linux/pm.h>
-
-static struct input_handler power_handler;
-
-/*
- * Power management can't be done in a interrupt context. So we have to
- * use keventd.
- */
-static int suspend_button_pushed = 0;
-static void suspend_button_task_handler(void *data)
-{
-        udelay(200); /* debounce */
-        suspend_button_pushed = 0;
-}
-
-static DECLARE_WORK(suspend_button_task, suspend_button_task_handler, NULL);
-
-static void power_event(struct input_handle *handle, unsigned int type,
-                       unsigned int code, int down)
-{
-       struct input_dev *dev = handle->dev;
-
-       printk("Entering power_event\n");
-
-       if (type == EV_PWR) {
-               switch (code) {
-                       case KEY_SUSPEND:
-                               printk("Powering down entire device\n");
-
-                               if (!suspend_button_pushed) {
-                                       suspend_button_pushed = 1;
-                                       schedule_work(&suspend_button_task);
-                               }
-                               break;
-                       case KEY_POWER:
-                               /* Hum power down the machine. */
-                               break;
-                       default:
-                               return;
-               }
-       }
-
-       if (type == EV_KEY) {
-               switch (code) {
-                       case KEY_SUSPEND:
-                               printk("Powering down input device\n");
-                               /* This is risky. See pm.h for details. */
-                               if (dev->state != PM_RESUME)
-                                       dev->state = PM_RESUME;
-                               else
-                                       dev->state = PM_SUSPEND;
-                               pm_send(dev->pm_dev, dev->state, dev);
-                               break;
-                       case KEY_POWER:
-                               /* Turn the input device off completely ? */
-                               break;
-                       default:
-                               return;
-               }
-       }
-       return;
-}
-
-static struct input_handle *power_connect(struct input_handler *handler,
-                                         struct input_dev *dev,
-                                         const struct input_device_id *id)
-{
-       struct input_handle *handle;
-
-       if (!(handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL)))
-               return NULL;
-
-       handle->dev = dev;
-       handle->handler = handler;
-
-       input_open_device(handle);
-
-       printk(KERN_INFO "power.c: Adding power management to input layer\n");
-       return handle;
-}
-
-static void power_disconnect(struct input_handle *handle)
-{
-       input_close_device(handle);
-       kfree(handle);
-}
-
-static const struct input_device_id power_ids[] = {
-       {
-               .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
-               .evbit = { BIT(EV_KEY) },
-               .keybit = { [LONG(KEY_SUSPEND)] = BIT(KEY_SUSPEND) }
-       },
-       {
-               .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
-               .evbit = { BIT(EV_KEY) },
-               .keybit = { [LONG(KEY_POWER)] = BIT(KEY_POWER) }
-       },
-       {
-               .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
-               .evbit = { BIT(EV_PWR) },
-       },
-       { },    /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(input, power_ids);
-
-static struct input_handler power_handler = {
-       .event =        power_event,
-       .connect =      power_connect,
-       .disconnect =   power_disconnect,
-       .name =         "power",
-       .id_table =     power_ids,
-};
-
-static int __init power_init(void)
-{
-       return input_register_handler(&power_handler);
-}
-
-static void __exit power_exit(void)
-{
-       input_unregister_handler(&power_handler);
-}
-
-module_init(power_init);
-module_exit(power_exit);
-
-MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>");
-MODULE_DESCRIPTION("Input Power Management driver");
-MODULE_LICENSE("GPL");
index 4fa93ff..93a1a6b 100644 (file)
  *
  *     Driver theory of operation:
  *
- *     Some access methods and an ISR is defined by the sub-driver 
- *     (e.g. hp_sdc_mlc.c).  These methods are expected to provide a 
- *     few bits of logic in addition to raw access to the HIL MLC, 
- *     specifically, the ISR, which is entirely registered by the 
- *     sub-driver and invoked directly, must check for record 
+ *     Some access methods and an ISR is defined by the sub-driver
+ *     (e.g. hp_sdc_mlc.c).  These methods are expected to provide a
+ *     few bits of logic in addition to raw access to the HIL MLC,
+ *     specifically, the ISR, which is entirely registered by the
+ *     sub-driver and invoked directly, must check for record
  *     termination or packet match, at which point a semaphore must
  *     be cleared and then the hil_mlcs_tasklet must be scheduled.
  *
@@ -47,7 +47,7 @@
  *     itself if output is pending.  (This rescheduling should be replaced
  *     at some point with a sub-driver-specific mechanism.)
  *
- *     A timer task prods the tasklet once per second to prevent 
+ *     A timer task prods the tasklet once per second to prevent
  *     hangups when attached devices do not return expected data
  *     and to initiate probes of the loop for new devices.
  */
@@ -83,69 +83,85 @@ DECLARE_TASKLET_DISABLED(hil_mlcs_tasklet, hil_mlcs_process, 0);
 
 /********************** Device info/instance management **********************/
 
-static void hil_mlc_clear_di_map (hil_mlc *mlc, int val) {
+static void hil_mlc_clear_di_map(hil_mlc *mlc, int val)
+{
        int j;
-       for (j = val; j < 7 ; j++) {
+
+       for (j = val; j < 7 ; j++)
                mlc->di_map[j] = -1;
-       }
 }
 
-static void hil_mlc_clear_di_scratch (hil_mlc *mlc) {
-       memset(&(mlc->di_scratch), 0, sizeof(mlc->di_scratch));
+static void hil_mlc_clear_di_scratch(hil_mlc *mlc)
+{
+       memset(&mlc->di_scratch, 0, sizeof(mlc->di_scratch));
 }
 
-static void hil_mlc_copy_di_scratch (hil_mlc *mlc, int idx) {
-       memcpy(&(mlc->di[idx]), &(mlc->di_scratch), sizeof(mlc->di_scratch));
+static void hil_mlc_copy_di_scratch(hil_mlc *mlc, int idx)
+{
+       memcpy(&mlc->di[idx], &mlc->di_scratch, sizeof(mlc->di_scratch));
 }
 
-static int hil_mlc_match_di_scratch (hil_mlc *mlc) {
+static int hil_mlc_match_di_scratch(hil_mlc *mlc)
+{
        int idx;
 
        for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
-               int j, found;
+               int j, found = 0;
 
                /* In-use slots are not eligible. */
-               found = 0;
-               for (j = 0; j < 7 ; j++) {
-                       if (mlc->di_map[j] == idx) found++;
-               }
-               if (found) continue;
-               if (!memcmp(mlc->di + idx, 
-                           &(mlc->di_scratch), 
-                           sizeof(mlc->di_scratch))) break;
+               for (j = 0; j < 7 ; j++)
+                       if (mlc->di_map[j] == idx)
+                               found++;
+
+               if (found)
+                       continue;
+
+               if (!memcmp(mlc->di + idx, &mlc->di_scratch,
+                               sizeof(mlc->di_scratch)))
+                       break;
        }
-       return((idx >= HIL_MLC_DEVMEM) ? -1 : idx);
+       return idx >= HIL_MLC_DEVMEM ? -1 : idx;
 }
 
-static int hil_mlc_find_free_di(hil_mlc *mlc) {
+static int hil_mlc_find_free_di(hil_mlc *mlc)
+{
        int idx;
-       /* TODO: Pick all-zero slots first, failing that, 
-        * randomize the slot picked among those eligible. 
+
+       /* TODO: Pick all-zero slots first, failing that,
+        * randomize the slot picked among those eligible.
         */
        for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
-               int j, found;
-               found = 0;
-               for (j = 0; j < 7 ; j++) {
-                       if (mlc->di_map[j] == idx) found++;
-               }
-               if (!found) break;
+               int j, found = 0;
+
+               for (j = 0; j < 7 ; j++)
+                       if (mlc->di_map[j] == idx)
+                               found++;
+
+               if (!found)
+                       break;
        }
-       return(idx); /* Note: It is guaranteed at least one above will match */
+
+       return idx; /* Note: It is guaranteed at least one above will match */
 }
 
-static inline void hil_mlc_clean_serio_map(hil_mlc *mlc) {
+static inline void hil_mlc_clean_serio_map(hil_mlc *mlc)
+{
        int idx;
+
        for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
-               int j, found;
-               found = 0;
-               for (j = 0; j < 7 ; j++) {
-                       if (mlc->di_map[j] == idx) found++;
-               }
-               if (!found) mlc->serio_map[idx].di_revmap = -1;
+               int j, found = 0;
+
+               for (j = 0; j < 7 ; j++)
+                       if (mlc->di_map[j] == idx)
+                               found++;
+
+               if (!found)
+                       mlc->serio_map[idx].di_revmap = -1;
        }
 }
 
-static void hil_mlc_send_polls(hil_mlc *mlc) {
+static void hil_mlc_send_polls(hil_mlc *mlc)
+{
        int did, i, cnt;
        struct serio *serio;
        struct serio_driver *drv;
@@ -157,26 +173,31 @@ static void hil_mlc_send_polls(hil_mlc *mlc) {
 
        while (mlc->icount < 15 - i) {
                hil_packet p;
+
                p = mlc->ipacket[i];
                if (did != (p & HIL_PKT_ADDR_MASK) >> 8) {
-                       if (drv == NULL || drv->interrupt == NULL) goto skip;
+                       if (drv && drv->interrupt) {
+                               drv->interrupt(serio, 0, 0);
+                               drv->interrupt(serio, HIL_ERR_INT >> 16, 0);
+                               drv->interrupt(serio, HIL_PKT_CMD >> 8,  0);
+                               drv->interrupt(serio, HIL_CMD_POL + cnt, 0);
+                       }
 
-                       drv->interrupt(serio, 0, 0);
-                       drv->interrupt(serio, HIL_ERR_INT >> 16, 0);
-                       drv->interrupt(serio, HIL_PKT_CMD >> 8,  0);
-                       drv->interrupt(serio, HIL_CMD_POL + cnt, 0);
-               skip:
                        did = (p & HIL_PKT_ADDR_MASK) >> 8;
                        serio = did ? mlc->serio[mlc->di_map[did-1]] : NULL;
                        drv = (serio != NULL) ? serio->drv : NULL;
                        cnt = 0;
                }
-               cnt++; i++;
-               if (drv == NULL || drv->interrupt == NULL) continue;
-               drv->interrupt(serio, (p >> 24), 0);
-               drv->interrupt(serio, (p >> 16) & 0xff, 0);
-               drv->interrupt(serio, (p >> 8) & ~HIL_PKT_ADDR_MASK, 0);
-               drv->interrupt(serio, p & 0xff, 0);
+
+               cnt++;
+               i++;
+
+               if (drv && drv->interrupt) {
+                       drv->interrupt(serio, (p >> 24), 0);
+                       drv->interrupt(serio, (p >> 16) & 0xff, 0);
+                       drv->interrupt(serio, (p >> 8) & ~HIL_PKT_ADDR_MASK, 0);
+                       drv->interrupt(serio, p & 0xff, 0);
+               }
        }
 }
 
@@ -215,12 +236,16 @@ static void hil_mlc_send_polls(hil_mlc *mlc) {
 #define HILSEN_DOZE    (HILSEN_SAME | HILSEN_SCHED | HILSEN_BREAK)
 #define HILSEN_SLEEP   (HILSEN_SAME | HILSEN_BREAK)
 
-static int hilse_match(hil_mlc *mlc, int unused) {
+static int hilse_match(hil_mlc *mlc, int unused)
+{
        int rc;
+
        rc = hil_mlc_match_di_scratch(mlc);
        if (rc == -1) {
                rc = hil_mlc_find_free_di(mlc);
-               if (rc == -1) goto err;
+               if (rc == -1)
+                       goto err;
+
 #ifdef HIL_MLC_DEBUG
                printk(KERN_DEBUG PREFIX "new in slot %i\n", rc);
 #endif
@@ -231,6 +256,7 @@ static int hilse_match(hil_mlc *mlc, int unused) {
                serio_rescan(mlc->serio[rc]);
                return -1;
        }
+
        mlc->di_map[mlc->ddi] = rc;
 #ifdef HIL_MLC_DEBUG
        printk(KERN_DEBUG PREFIX "same in slot %i\n", rc);
@@ -238,152 +264,177 @@ static int hilse_match(hil_mlc *mlc, int unused) {
        mlc->serio_map[rc].di_revmap = mlc->ddi;
        hil_mlc_clean_serio_map(mlc);
        return 0;
+
  err:
        printk(KERN_ERR PREFIX "Residual device slots exhausted, close some serios!\n");
        return 1;
 }
 
 /* An LCV used to prevent runaway loops, forces 5 second sleep when reset. */
-static int hilse_init_lcv(hil_mlc *mlc, int unused) {
+static int hilse_init_lcv(hil_mlc *mlc, int unused)
+{
        struct timeval tv;
 
        do_gettimeofday(&tv);
 
-       if(mlc->lcv == 0) goto restart;  /* First init, no need to dally */
-       if(tv.tv_sec - mlc->lcv_tv.tv_sec < 5) return -1;
- restart:
+       if (mlc->lcv && (tv.tv_sec - mlc->lcv_tv.tv_sec) < 5)
+               return -1;
+
        mlc->lcv_tv = tv;
        mlc->lcv = 0;
+
        return 0;
 }
 
-static int hilse_inc_lcv(hil_mlc *mlc, int lim) {
-       if (mlc->lcv++ >= lim) return -1;
-       return 0;
+static int hilse_inc_lcv(hil_mlc *mlc, int lim)
+{
+       return mlc->lcv++ >= lim ? -1 : 0;
 }
 
 #if 0
-static int hilse_set_lcv(hil_mlc *mlc, int val) {
+static int hilse_set_lcv(hil_mlc *mlc, int val)
+{
        mlc->lcv = val;
+
        return 0;
 }
 #endif
 
 /* Management of the discovered device index (zero based, -1 means no devs) */
-static int hilse_set_ddi(hil_mlc *mlc, int val) {
+static int hilse_set_ddi(hil_mlc *mlc, int val)
+{
        mlc->ddi = val;
        hil_mlc_clear_di_map(mlc, val + 1);
+
        return 0;
 }
 
-static int hilse_dec_ddi(hil_mlc *mlc, int unused) {
+static int hilse_dec_ddi(hil_mlc *mlc, int unused)
+{
        mlc->ddi--;
-       if (mlc->ddi <= -1) { 
+       if (mlc->ddi <= -1) {
                mlc->ddi = -1;
                hil_mlc_clear_di_map(mlc, 0);
                return -1;
        }
        hil_mlc_clear_di_map(mlc, mlc->ddi + 1);
+
        return 0;
 }
 
-static int hilse_inc_ddi(hil_mlc *mlc, int unused) {
-       if (mlc->ddi >= 6) {
-               BUG();
-               return -1;
-       }
+static int hilse_inc_ddi(hil_mlc *mlc, int unused)
+{
+       BUG_ON(mlc->ddi >= 6);
        mlc->ddi++;
+
        return 0;
 }
 
-static int hilse_take_idd(hil_mlc *mlc, int unused) {
+static int hilse_take_idd(hil_mlc *mlc, int unused)
+{
        int i;
 
-       /* Help the state engine: 
-        * Is this a real IDD response or just an echo? 
+       /* Help the state engine:
+        * Is this a real IDD response or just an echo?
         *
-        * Real IDD response does not start with a command. 
+        * Real IDD response does not start with a command.
         */
-       if (mlc->ipacket[0] & HIL_PKT_CMD) goto bail;
+       if (mlc->ipacket[0] & HIL_PKT_CMD)
+               goto bail;
+
        /* Should have the command echoed further down. */
        for (i = 1; i < 16; i++) {
-               if (((mlc->ipacket[i] & HIL_PKT_ADDR_MASK) == 
+               if (((mlc->ipacket[i] & HIL_PKT_ADDR_MASK) ==
                     (mlc->ipacket[0] & HIL_PKT_ADDR_MASK)) &&
-                   (mlc->ipacket[i] & HIL_PKT_CMD) && 
+                   (mlc->ipacket[i] & HIL_PKT_CMD) &&
                    ((mlc->ipacket[i] & HIL_PKT_DATA_MASK) == HIL_CMD_IDD))
                        break;
        }
-       if (i > 15) goto bail;
+       if (i > 15)
+               goto bail;
+
        /* And the rest of the packets should still be clear. */
-       while (++i < 16) {
-               if (mlc->ipacket[i]) break;
-       }
-       if (i < 16) goto bail;
-       for (i = 0; i < 16; i++) {
-               mlc->di_scratch.idd[i] = 
+       while (++i < 16)
+               if (mlc->ipacket[i])
+                       break;
+
+       if (i < 16)
+               goto bail;
+
+       for (i = 0; i < 16; i++)
+               mlc->di_scratch.idd[i] =
                        mlc->ipacket[i] & HIL_PKT_DATA_MASK;
-       }
+
        /* Next step is to see if RSC supported */
-       if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_RSC) 
+       if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_RSC)
                return HILSEN_NEXT;
-       if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) 
+
+       if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD)
                return HILSEN_DOWN | 4;
+
        return 0;
+
  bail:
        mlc->ddi--;
+
        return -1; /* This should send us off to ACF */
 }
 
-static int hilse_take_rsc(hil_mlc *mlc, int unused) {
+static int hilse_take_rsc(hil_mlc *mlc, int unused)
+{
        int i;
 
-       for (i = 0; i < 16; i++) {
-               mlc->di_scratch.rsc[i] = 
+       for (i = 0; i < 16; i++)
+               mlc->di_scratch.rsc[i] =
                        mlc->ipacket[i] & HIL_PKT_DATA_MASK;
-       }
+
        /* Next step is to see if EXD supported (IDD has already been read) */
-       if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) 
+       if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD)
                return HILSEN_NEXT;
+
        return 0;
 }
 
-static int hilse_take_exd(hil_mlc *mlc, int unused) {
+static int hilse_take_exd(hil_mlc *mlc, int unused)
+{
        int i;
 
-       for (i = 0; i < 16; i++) {
-               mlc->di_scratch.exd[i] = 
+       for (i = 0; i < 16; i++)
+               mlc->di_scratch.exd[i] =
                        mlc->ipacket[i] & HIL_PKT_DATA_MASK;
-       }
+
        /* Next step is to see if RNM supported. */
-       if (mlc->di_scratch.exd[0] & HIL_EXD_HEADER_RNM) 
+       if (mlc->di_scratch.exd[0] & HIL_EXD_HEADER_RNM)
                return HILSEN_NEXT;
+
        return 0;
 }
 
-static int hilse_take_rnm(hil_mlc *mlc, int unused) {
+static int hilse_take_rnm(hil_mlc *mlc, int unused)
+{
        int i;
 
-       for (i = 0; i < 16; i++) {
-               mlc->di_scratch.rnm[i] = 
+       for (i = 0; i < 16; i++)
+               mlc->di_scratch.rnm[i] =
                        mlc->ipacket[i] & HIL_PKT_DATA_MASK;
-       }
-       do {
-         char nam[17];
-         snprintf(nam, 16, "%s", mlc->di_scratch.rnm);
-         nam[16] = '\0';
-         printk(KERN_INFO PREFIX "Device name gotten: %s\n", nam);
-       } while (0);
+
+       printk(KERN_INFO PREFIX "Device name gotten: %16s\n",
+                       mlc->di_scratch.rnm);
+
        return 0;
 }
 
-static int hilse_operate(hil_mlc *mlc, int repoll) { 
+static int hilse_operate(hil_mlc *mlc, int repoll)
+{
 
-       if (mlc->opercnt == 0) hil_mlcs_probe = 0;
+       if (mlc->opercnt == 0)
+               hil_mlcs_probe = 0;
        mlc->opercnt = 1;
 
        hil_mlc_send_polls(mlc);
 
-       if (!hil_mlcs_probe) return 0;
+       if (!hil_mlcs_probe)
+               return 0;
        hil_mlcs_probe = 0;
        mlc->opercnt = 0;
        return 1;
@@ -408,7 +459,7 @@ static int hilse_operate(hil_mlc *mlc, int repoll) {
 #define OUT_LAST(pack) \
 { HILSE_OUT_LAST,      { .packet = pack }, 0, 0, 0, 0 },
 
-struct hilse_node hil_mlc_se[HILSEN_END] = {
+const struct hilse_node hil_mlc_se[HILSEN_END] = {
 
        /* 0  HILSEN_START */
        FUNC(hilse_init_lcv, 0, HILSEN_NEXT,    HILSEN_SLEEP,   0)
@@ -428,7 +479,7 @@ struct hilse_node hil_mlc_se[HILSEN_END] = {
        EXPECT(HIL_ERR_INT | TEST_PACKET(0xa),
               2000,            HILSEN_NEXT,    HILSEN_RESTART, HILSEN_RESTART)
        OUT(HIL_CTRL_ONLY | 0)                  /* Disable test mode */
-       
+
        /* 9  HILSEN_DHR */
        FUNC(hilse_init_lcv, 0, HILSEN_NEXT,    HILSEN_SLEEP,   0)
 
@@ -439,7 +490,7 @@ struct hilse_node hil_mlc_se[HILSEN_END] = {
        IN(300000,              HILSEN_DHR2,    HILSEN_DHR2,    HILSEN_NEXT)
 
        /* 14 HILSEN_IFC */
-       OUT(HIL_PKT_CMD | HIL_CMD_IFC)
+       OUT(HIL_PKT_CMD | HIL_CMD_IFC)
        EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT,
               20000,           HILSEN_DISC,    HILSEN_DHR2,    HILSEN_NEXT )
 
@@ -455,7 +506,7 @@ struct hilse_node hil_mlc_se[HILSEN_END] = {
 
        /* 18 HILSEN_HEAL */
        OUT_LAST(HIL_CMD_ELB)
-       EXPECT_LAST(HIL_CMD_ELB | HIL_ERR_INT, 
+       EXPECT_LAST(HIL_CMD_ELB | HIL_ERR_INT,
                    20000,      HILSEN_REPOLL,  HILSEN_DSR,     HILSEN_NEXT)
        FUNC(hilse_dec_ddi, 0,  HILSEN_HEAL,    HILSEN_NEXT,    0)
 
@@ -503,7 +554,7 @@ struct hilse_node hil_mlc_se[HILSEN_END] = {
 
        /* 44 HILSEN_PROBE */
        OUT_LAST(HIL_PKT_CMD | HIL_CMD_EPT)
-       IN(10000,               HILSEN_DISC,    HILSEN_DSR,     HILSEN_NEXT)
+       IN(10000,               HILSEN_DISC,    HILSEN_DSR,     HILSEN_NEXT)
        OUT_DISC(HIL_PKT_CMD | HIL_CMD_ELB)
        IN(10000,               HILSEN_DISC,    HILSEN_DSR,     HILSEN_NEXT)
        OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1)
@@ -514,7 +565,7 @@ struct hilse_node hil_mlc_se[HILSEN_END] = {
        /* 52 HILSEN_DSR */
        FUNC(hilse_set_ddi, -1, HILSEN_NEXT,    0,              0)
        OUT(HIL_PKT_CMD | HIL_CMD_DSR)
-       IN(20000,               HILSEN_DHR,     HILSEN_DHR,     HILSEN_IFC)
+       IN(20000,               HILSEN_DHR,     HILSEN_DHR,     HILSEN_IFC)
 
        /* 55 HILSEN_REPOLL */
        OUT(HIL_PKT_CMD | HIL_CMD_RPL)
@@ -523,14 +574,15 @@ struct hilse_node hil_mlc_se[HILSEN_END] = {
        FUNC(hilse_operate, 1,  HILSEN_OPERATE, HILSEN_IFC,     HILSEN_PROBE)
 
        /* 58 HILSEN_IFCACF */
-       OUT(HIL_PKT_CMD | HIL_CMD_IFC)
+       OUT(HIL_PKT_CMD | HIL_CMD_IFC)
        EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT,
               20000,           HILSEN_ACF2,    HILSEN_DHR2,    HILSEN_HEAL)
 
        /* 60 HILSEN_END */
 };
 
-static inline void hilse_setup_input(hil_mlc *mlc, struct hilse_node *node) {
+static inline void hilse_setup_input(hil_mlc *mlc, const struct hilse_node *node)
+{
 
        switch (node->act) {
        case HILSE_EXPECT_DISC:
@@ -555,29 +607,27 @@ static inline void hilse_setup_input(hil_mlc *mlc, struct hilse_node *node) {
        do_gettimeofday(&(mlc->instart));
        mlc->icount = 15;
        memset(mlc->ipacket, 0, 16 * sizeof(hil_packet));
-       BUG_ON(down_trylock(&(mlc->isem)));
-
-       return;
+       BUG_ON(down_trylock(&mlc->isem));
 }
 
 #ifdef HIL_MLC_DEBUG
-static int doze = 0;
+static int doze;
 static int seidx; /* For debug */
-static int kick = 1;
 #endif
 
-static int hilse_donode (hil_mlc *mlc) {
-       struct hilse_node *node;
+static int hilse_donode(hil_mlc *mlc)
+{
+       const struct hilse_node *node;
        int nextidx = 0;
        int sched_long = 0;
        unsigned long flags;
 
 #ifdef HIL_MLC_DEBUG
-       if (mlc->seidx && (mlc->seidx != seidx)  && mlc->seidx != 41 && mlc->seidx != 42 && mlc->seidx != 43) {
-         printk(KERN_DEBUG PREFIX "z%i \n%s {%i}", doze, kick ? "K" : "", mlc->seidx);
+       if (mlc->seidx && mlc->seidx != seidx &&
+           mlc->seidx != 41 && mlc->seidx != 42 && mlc->seidx != 43) {
+               printk(KERN_DEBUG PREFIX "z%i \n {%i}", doze, mlc->seidx);
                doze = 0;
        }
-       kick = 0;
 
        seidx = mlc->seidx;
 #endif
@@ -588,52 +638,61 @@ static int hilse_donode (hil_mlc *mlc) {
                hil_packet pack;
 
        case HILSE_FUNC:
-               if (node->object.func == NULL) break;
+               BUG_ON(node->object.func == NULL);
                rc = node->object.func(mlc, node->arg);
-               nextidx = (rc > 0) ? node->ugly : 
+               nextidx = (rc > 0) ? node->ugly :
                        ((rc < 0) ? node->bad : node->good);
-               if (nextidx == HILSEN_FOLLOW) nextidx = rc;
+               if (nextidx == HILSEN_FOLLOW)
+                       nextidx = rc;
                break;
+
        case HILSE_EXPECT_LAST:
        case HILSE_EXPECT_DISC:
        case HILSE_EXPECT:
        case HILSE_IN:
                /* Already set up from previous HILSE_OUT_* */
-               write_lock_irqsave(&(mlc->lock), flags);
+               write_lock_irqsave(&mlc->lock, flags);
                rc = mlc->in(mlc, node->arg);
                if (rc == 2)  {
                        nextidx = HILSEN_DOZE;
                        sched_long = 1;
-                       write_unlock_irqrestore(&(mlc->lock), flags);
+                       write_unlock_irqrestore(&mlc->lock, flags);
                        break;
                }
-               if (rc == 1)            nextidx = node->ugly;
-               else if (rc == 0)       nextidx = node->good;
-               else                    nextidx = node->bad;
+               if (rc == 1)
+                       nextidx = node->ugly;
+               else if (rc == 0)
+                       nextidx = node->good;
+               else
+                       nextidx = node->bad;
                mlc->istarted = 0;
-               write_unlock_irqrestore(&(mlc->lock), flags);
+               write_unlock_irqrestore(&mlc->lock, flags);
                break;
+
        case HILSE_OUT_LAST:
-               write_lock_irqsave(&(mlc->lock), flags);
+               write_lock_irqsave(&mlc->lock, flags);
                pack = node->object.packet;
                pack |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT);
                goto out;
+
        case HILSE_OUT_DISC:
-               write_lock_irqsave(&(mlc->lock), flags);
+               write_lock_irqsave(&mlc->lock, flags);
                pack = node->object.packet;
                pack |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT);
                goto out;
+
        case HILSE_OUT:
-               write_lock_irqsave(&(mlc->lock), flags);
+               write_lock_irqsave(&mlc->lock, flags);
                pack = node->object.packet;
        out:
-               if (mlc->istarted) goto out2;
+               if (mlc->istarted)
+                       goto out2;
                /* Prepare to receive input */
                if ((node + 1)->act & HILSE_IN)
                        hilse_setup_input(mlc, node + 1);
 
        out2:
-               write_unlock_irqrestore(&(mlc->lock), flags);
+               write_unlock_irqrestore(&mlc->lock, flags);
 
                if (down_trylock(&mlc->osem)) {
                        nextidx = HILSEN_DOZE;
@@ -641,60 +700,71 @@ static int hilse_donode (hil_mlc *mlc) {
                }
                up(&mlc->osem);
 
-               write_lock_irqsave(&(mlc->lock), flags);
-               if (!(mlc->ostarted)) {
+               write_lock_irqsave(&mlc->lock, flags);
+               if (!mlc->ostarted) {
                        mlc->ostarted = 1;
                        mlc->opacket = pack;
                        mlc->out(mlc);
                        nextidx = HILSEN_DOZE;
-                       write_unlock_irqrestore(&(mlc->lock), flags);
+                       write_unlock_irqrestore(&mlc->lock, flags);
                        break;
                }
                mlc->ostarted = 0;
                do_gettimeofday(&(mlc->instart));
-               write_unlock_irqrestore(&(mlc->lock), flags);
+               write_unlock_irqrestore(&mlc->lock, flags);
                nextidx = HILSEN_NEXT;
                break;
+
        case HILSE_CTS:
+               write_lock_irqsave(&mlc->lock, flags);
                nextidx = mlc->cts(mlc) ? node->bad : node->good;
+               write_unlock_irqrestore(&mlc->lock, flags);
                break;
+
        default:
                BUG();
-               nextidx = 0;
-               break;
        }
 
 #ifdef HIL_MLC_DEBUG
-       if (nextidx == HILSEN_DOZE) doze++;
+       if (nextidx == HILSEN_DOZE)
+               doze++;
 #endif
 
        while (nextidx & HILSEN_SCHED) {
                struct timeval tv;
 
-               if (!sched_long) goto sched;
+               if (!sched_long)
+                       goto sched;
 
                do_gettimeofday(&tv);
-               tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec);
+               tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec);
                tv.tv_usec -= mlc->instart.tv_usec;
                if (tv.tv_usec >= mlc->intimeout) goto sched;
-               tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / 1000000;
+               tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / USEC_PER_SEC;
                if (!tv.tv_usec) goto sched;
                mod_timer(&hil_mlcs_kicker, jiffies + tv.tv_usec);
                break;
        sched:
                tasklet_schedule(&hil_mlcs_tasklet);
                break;
-       } 
-       if (nextidx & HILSEN_DOWN) mlc->seidx += nextidx & HILSEN_MASK;
-       else if (nextidx & HILSEN_UP) mlc->seidx -= nextidx & HILSEN_MASK;
-       else mlc->seidx = nextidx & HILSEN_MASK;
+       }
+
+       if (nextidx & HILSEN_DOWN)
+               mlc->seidx += nextidx & HILSEN_MASK;
+       else if (nextidx & HILSEN_UP)
+               mlc->seidx -= nextidx & HILSEN_MASK;
+       else
+               mlc->seidx = nextidx & HILSEN_MASK;
+
+       if (nextidx & HILSEN_BREAK)
+               return 1;
 
-       if (nextidx & HILSEN_BREAK)     return 1;
        return 0;
 }
 
 /******************** tasklet context functions **************************/
-static void hil_mlcs_process(unsigned long unused) {
+static void hil_mlcs_process(unsigned long unused)
+{
        struct list_head *tmp;
 
        read_lock(&hil_mlcs_lock);
@@ -702,19 +772,20 @@ static void hil_mlcs_process(unsigned long unused) {
                struct hil_mlc *mlc = list_entry(tmp, hil_mlc, list);
                while (hilse_donode(mlc) == 0) {
 #ifdef HIL_MLC_DEBUG
-                 if (mlc->seidx != 41 && 
-                     mlc->seidx != 42 && 
-                     mlc->seidx != 43) 
-                   printk(KERN_DEBUG PREFIX " + ");
+                       if (mlc->seidx != 41 &&
+                           mlc->seidx != 42 &&
+                           mlc->seidx != 43)
+                               printk(KERN_DEBUG PREFIX " + ");
 #endif
-               };
+               }
        }
        read_unlock(&hil_mlcs_lock);
 }
 
 /************************* Keepalive timer task *********************/
 
-void hil_mlcs_timer (unsigned long data) {
+void hil_mlcs_timer(unsigned long data)
+{
        hil_mlcs_probe = 1;
        tasklet_schedule(&hil_mlcs_tasklet);
        /* Re-insert the periodic task. */
@@ -724,28 +795,25 @@ void hil_mlcs_timer (unsigned long data) {
 
 /******************** user/kernel context functions **********************/
 
-static int hil_mlc_serio_write(struct serio *serio, unsigned char c) {
+static int hil_mlc_serio_write(struct serio *serio, unsigned char c)
+{
        struct hil_mlc_serio_map *map;
        struct hil_mlc *mlc;
        struct serio_driver *drv;
        uint8_t *idx, *last;
 
        map = serio->port_data;
-       if (map == NULL) {
-               BUG();
-               return -EIO;
-       }
+       BUG_ON(map == NULL);
+
        mlc = map->mlc;
-       if (mlc == NULL) {
-               BUG();
-               return -EIO;
-       }
-       mlc->serio_opacket[map->didx] |= 
+       BUG_ON(mlc == NULL);
+
+       mlc->serio_opacket[map->didx] |=
                ((hil_packet)c) << (8 * (3 - mlc->serio_oidx[map->didx]));
 
        if (mlc->serio_oidx[map->didx] >= 3) {
                /* for now only commands */
-               if (!(mlc->serio_opacket[map->didx] & HIL_PKT_CMD)) 
+               if (!(mlc->serio_opacket[map->didx] & HIL_PKT_CMD))
                        return -EIO;
                switch (mlc->serio_opacket[map->didx] & HIL_PKT_DATA_MASK) {
                case HIL_CMD_IDD:
@@ -771,12 +839,11 @@ static int hil_mlc_serio_write(struct serio *serio, unsigned char c) {
        return -EIO;
  emu:
        drv = serio->drv;
-       if (drv == NULL) {
-               BUG();
-               return -EIO;
-       }
+       BUG_ON(drv == NULL);
+
        last = idx + 15;
-       while ((last != idx) && (*last == 0)) last--;
+       while ((last != idx) && (*last == 0))
+               last--;
 
        while (idx != last) {
                drv->interrupt(serio, 0, 0);
@@ -789,14 +856,15 @@ static int hil_mlc_serio_write(struct serio *serio, unsigned char c) {
        drv->interrupt(serio, HIL_ERR_INT >> 16, 0);
        drv->interrupt(serio, HIL_PKT_CMD >> 8, 0);
        drv->interrupt(serio, *idx, 0);
-       
+
        mlc->serio_oidx[map->didx] = 0;
        mlc->serio_opacket[map->didx] = 0;
 
        return 0;
 }
 
-static int hil_mlc_serio_open(struct serio *serio) {
+static int hil_mlc_serio_open(struct serio *serio)
+{
        struct hil_mlc_serio_map *map;
        struct hil_mlc *mlc;
 
@@ -804,67 +872,57 @@ static int hil_mlc_serio_open(struct serio *serio) {
                return -EBUSY;
 
        map = serio->port_data;
-       if (map == NULL) {
-               BUG();
-               return -ENODEV;
-       }
+       BUG_ON(map == NULL);
+
        mlc = map->mlc;
-       if (mlc == NULL) {
-               BUG();
-               return -ENODEV;
-       }
+       BUG_ON(mlc == NULL);
 
        return 0;
 }
 
-static void hil_mlc_serio_close(struct serio *serio) {
+static void hil_mlc_serio_close(struct serio *serio)
+{
        struct hil_mlc_serio_map *map;
        struct hil_mlc *mlc;
 
        map = serio->port_data;
-       if (map == NULL) {
-               BUG();
-               return;
-       }
+       BUG_ON(map == NULL);
+
        mlc = map->mlc;
-       if (mlc == NULL) {
-               BUG();
-               return;
-       }
+       BUG_ON(mlc == NULL);
 
        serio_set_drvdata(serio, NULL);
        serio->drv = NULL;
        /* TODO wake up interruptable */
 }
 
-static struct serio_device_id hil_mlc_serio_id = {
+static const struct serio_device_id hil_mlc_serio_id = {
        .type = SERIO_HIL_MLC,
        .proto = SERIO_HIL,
        .extra = SERIO_ANY,
        .id = SERIO_ANY,
 };
 
-int hil_mlc_register(hil_mlc *mlc) {
+int hil_mlc_register(hil_mlc *mlc)
+{
        int i;
-        unsigned long flags;
+       unsigned long flags;
 
-       if (mlc == NULL) {
-               return -EINVAL;
-       }
+       BUG_ON(mlc == NULL);
 
        mlc->istarted = 0;
-        mlc->ostarted = 0;
+       mlc->ostarted = 0;
 
-        rwlock_init(&mlc->lock);
-        init_MUTEX(&(mlc->osem));
+       rwlock_init(&mlc->lock);
+       init_MUTEX(&mlc->osem);
 
-        init_MUTEX(&(mlc->isem));
-        mlc->icount = -1;
-        mlc->imatch = 0;
+       init_MUTEX(&mlc->isem);
+       mlc->icount = -1;
+       mlc->imatch = 0;
 
        mlc->opercnt = 0;
 
-        init_MUTEX_LOCKED(&(mlc->csem));
+       init_MUTEX_LOCKED(&(mlc->csem));
 
        hil_mlc_clear_di_scratch(mlc);
        hil_mlc_clear_di_map(mlc, 0);
@@ -873,6 +931,8 @@ int hil_mlc_register(hil_mlc *mlc) {
                hil_mlc_copy_di_scratch(mlc, i);
                mlc_serio = kzalloc(sizeof(*mlc_serio), GFP_KERNEL);
                mlc->serio[i] = mlc_serio;
+               snprintf(mlc_serio->name, sizeof(mlc_serio->name)-1, "HIL_SERIO%d", i);
+               snprintf(mlc_serio->phys, sizeof(mlc_serio->phys)-1, "HIL%d", i);
                mlc_serio->id                   = hil_mlc_serio_id;
                mlc_serio->write                = hil_mlc_serio_write;
                mlc_serio->open                 = hil_mlc_serio_open;
@@ -897,19 +957,18 @@ int hil_mlc_register(hil_mlc *mlc) {
        return 0;
 }
 
-int hil_mlc_unregister(hil_mlc *mlc) {
+int hil_mlc_unregister(hil_mlc *mlc)
+{
        struct list_head *tmp;
-        unsigned long flags;
+       unsigned long flags;
        int i;
 
-       if (mlc == NULL)
-               return -EINVAL;
+       BUG_ON(mlc == NULL);
 
        write_lock_irqsave(&hil_mlcs_lock, flags);
-       list_for_each(tmp, &hil_mlcs) {
+       list_for_each(tmp, &hil_mlcs)
                if (list_entry(tmp, hil_mlc, list) == mlc)
                        goto found;
-       }
 
        /* not found in list */
        write_unlock_irqrestore(&hil_mlcs_lock, flags);
@@ -918,7 +977,7 @@ int hil_mlc_unregister(hil_mlc *mlc) {
 
  found:
        list_del(tmp);
-        write_unlock_irqrestore(&hil_mlcs_lock, flags);
+       write_unlock_irqrestore(&hil_mlcs_lock, flags);
 
        for (i = 0; i < HIL_MLC_DEVMEM; i++) {
                serio_unregister_port(mlc->serio[i]);
@@ -942,7 +1001,7 @@ static int __init hil_mlc_init(void)
 
        return 0;
 }
-                
+
 static void __exit hil_mlc_exit(void)
 {
        del_timer(&hil_mlcs_kicker);
@@ -950,6 +1009,6 @@ static void __exit hil_mlc_exit(void)
        tasklet_disable(&hil_mlcs_tasklet);
        tasklet_kill(&hil_mlcs_tasklet);
 }
-                        
+
 module_init(hil_mlc_init);
 module_exit(hil_mlc_exit);
index b57370d..6af1998 100644 (file)
  *
  * Driver theory of operation:
  *
- * hp_sdc_put does all writing to the SDC.  ISR can run on a different 
- * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time 
+ * hp_sdc_put does all writing to the SDC.  ISR can run on a different
+ * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time
  * (it cannot really benefit from SMP anyway.)  A tasket fit this perfectly.
  *
- * All data coming back from the SDC is sent via interrupt and can be read 
- * fully in the ISR, so there are no latency/throughput problems there.  
- * The problem is with output, due to the slow clock speed of the SDC 
- * compared to the CPU.  This should not be too horrible most of the time, 
- * but if used with HIL devices that support the multibyte transfer command, 
- * keeping outbound throughput flowing at the 6500KBps that the HIL is 
+ * All data coming back from the SDC is sent via interrupt and can be read
+ * fully in the ISR, so there are no latency/throughput problems there.
+ * The problem is with output, due to the slow clock speed of the SDC
+ * compared to the CPU.  This should not be too horrible most of the time,
+ * but if used with HIL devices that support the multibyte transfer command,
+ * keeping outbound throughput flowing at the 6500KBps that the HIL is
  * capable of is more than can be done at HZ=100.
  *
- * Busy polling for IBF clear wastes CPU cycles and bus cycles.  hp_sdc.ibf 
- * is set to 0 when the IBF flag in the status register has cleared.  ISR 
- * may do this, and may also access the parts of queued transactions related 
- * to reading data back from the SDC, but otherwise will not touch the 
+ * Busy polling for IBF clear wastes CPU cycles and bus cycles.  hp_sdc.ibf
+ * is set to 0 when the IBF flag in the status register has cleared.  ISR
+ * may do this, and may also access the parts of queued transactions related
+ * to reading data back from the SDC, but otherwise will not touch the
  * hp_sdc state. Whenever a register is written hp_sdc.ibf is set to 1.
  *
  * The i8042 write index and the values in the 4-byte input buffer
  * starting at 0x70 are kept track of in hp_sdc.wi, and .r7[], respectively,
- * to minimize the amount of IO needed to the SDC.  However these values 
+ * to minimize the amount of IO needed to the SDC.  However these values
  * do not need to be locked since they are only ever accessed by hp_sdc_put.
  *
  * A timer task schedules the tasklet once per second just to make
@@ -100,39 +100,46 @@ EXPORT_SYMBOL(hp_sdc_release_timer_irq);
 EXPORT_SYMBOL(hp_sdc_release_hil_irq);
 EXPORT_SYMBOL(hp_sdc_release_cooked_irq);
 
+EXPORT_SYMBOL(__hp_sdc_enqueue_transaction);
 EXPORT_SYMBOL(hp_sdc_enqueue_transaction);
 EXPORT_SYMBOL(hp_sdc_dequeue_transaction);
 
 static hp_i8042_sdc    hp_sdc; /* All driver state is kept in here. */
 
 /*************** primitives for use in any context *********************/
-static inline uint8_t hp_sdc_status_in8 (void) {
+static inline uint8_t hp_sdc_status_in8(void)
+{
        uint8_t status;
        unsigned long flags;
 
        write_lock_irqsave(&hp_sdc.ibf_lock, flags);
        status = sdc_readb(hp_sdc.status_io);
-       if (!(status & HP_SDC_STATUS_IBF)) hp_sdc.ibf = 0;
+       if (!(status & HP_SDC_STATUS_IBF))
+               hp_sdc.ibf = 0;
        write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
 
        return status;
 }
 
-static inline uint8_t hp_sdc_data_in8 (void) {
-       return sdc_readb(hp_sdc.data_io); 
+static inline uint8_t hp_sdc_data_in8(void)
+{
+       return sdc_readb(hp_sdc.data_io);
 }
 
-static inline void hp_sdc_status_out8 (uint8_t val) {
+static inline void hp_sdc_status_out8(uint8_t val)
+{
        unsigned long flags;
 
        write_lock_irqsave(&hp_sdc.ibf_lock, flags);
        hp_sdc.ibf = 1;
-       if ((val & 0xf0) == 0xe0) hp_sdc.wi = 0xff;
+       if ((val & 0xf0) == 0xe0)
+               hp_sdc.wi = 0xff;
        sdc_writeb(val, hp_sdc.status_io);
        write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
 }
 
-static inline void hp_sdc_data_out8 (uint8_t val) {
+static inline void hp_sdc_data_out8(uint8_t val)
+{
        unsigned long flags;
 
        write_lock_irqsave(&hp_sdc.ibf_lock, flags);
@@ -141,11 +148,12 @@ static inline void hp_sdc_data_out8 (uint8_t val) {
        write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
 }
 
-/*     Care must be taken to only invoke hp_sdc_spin_ibf when 
- *     absolutely needed, or in rarely invoked subroutines.  
- *     Not only does it waste CPU cycles, it also wastes bus cycles. 
+/*     Care must be taken to only invoke hp_sdc_spin_ibf when
+ *     absolutely needed, or in rarely invoked subroutines.
+ *     Not only does it waste CPU cycles, it also wastes bus cycles.
  */
-static inline void hp_sdc_spin_ibf(void) {
+static inline void hp_sdc_spin_ibf(void)
+{
        unsigned long flags;
        rwlock_t *lock;
 
@@ -158,19 +166,21 @@ static inline void hp_sdc_spin_ibf(void) {
        }
        read_unlock(lock);
        write_lock(lock);
-       while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF) {};
+       while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF)
+               { }
        hp_sdc.ibf = 0;
        write_unlock_irqrestore(lock, flags);
 }
 
 
 /************************ Interrupt context functions ************************/
-static void hp_sdc_take (int irq, void *dev_id, uint8_t status, uint8_t data) {
+static void hp_sdc_take(int irq, void *dev_id, uint8_t status, uint8_t data)
+{
        hp_sdc_transaction *curr;
 
        read_lock(&hp_sdc.rtq_lock);
        if (hp_sdc.rcurr < 0) {
-               read_unlock(&hp_sdc.rtq_lock);
+               read_unlock(&hp_sdc.rtq_lock);
                return;
        }
        curr = hp_sdc.tq[hp_sdc.rcurr];
@@ -183,25 +193,27 @@ static void hp_sdc_take (int irq, void *dev_id, uint8_t status, uint8_t data) {
 
        if (hp_sdc.rqty <= 0) {
                /* All data has been gathered. */
-               if(curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE) {
-                       if (curr->act.semaphore) up(curr->act.semaphore);
-               }
-               if(curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK) {
+               if (curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE)
+                       if (curr->act.semaphore)
+                               up(curr->act.semaphore);
+
+               if (curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK)
                        if (curr->act.irqhook)
                                curr->act.irqhook(irq, dev_id, status, data);
-               }
+
                curr->actidx = curr->idx;
                curr->idx++;
                /* Return control of this transaction */
                write_lock(&hp_sdc.rtq_lock);
-               hp_sdc.rcurr = -1; 
+               hp_sdc.rcurr = -1;
                hp_sdc.rqty = 0;
                write_unlock(&hp_sdc.rtq_lock);
                tasklet_schedule(&hp_sdc.task);
        }
 }
 
-static irqreturn_t hp_sdc_isr(int irq, void *dev_id) {
+static irqreturn_t hp_sdc_isr(int irq, void *dev_id)
+{
        uint8_t status, data;
 
        status = hp_sdc_status_in8();
@@ -209,67 +221,74 @@ static irqreturn_t hp_sdc_isr(int irq, void *dev_id) {
        data =   hp_sdc_data_in8();
 
        /* For now we are ignoring these until we get the SDC to behave. */
-       if (((status & 0xf1) == 0x51) && data == 0x82) {
-         return IRQ_HANDLED;
-       }
+       if (((status & 0xf1) == 0x51) && data == 0x82)
+               return IRQ_HANDLED;
 
-       switch(status & HP_SDC_STATUS_IRQMASK) {
-             case 0: /* This case is not documented. */
+       switch (status & HP_SDC_STATUS_IRQMASK) {
+       case 0: /* This case is not documented. */
                break;
-             case HP_SDC_STATUS_USERTIMER:
-             case HP_SDC_STATUS_PERIODIC:
-             case HP_SDC_STATUS_TIMER:
+
+       case HP_SDC_STATUS_USERTIMER:
+       case HP_SDC_STATUS_PERIODIC:
+       case HP_SDC_STATUS_TIMER:
                read_lock(&hp_sdc.hook_lock);
-               if (hp_sdc.timer != NULL)
+               if (hp_sdc.timer != NULL)
                        hp_sdc.timer(irq, dev_id, status, data);
                read_unlock(&hp_sdc.hook_lock);
                break;
-             case HP_SDC_STATUS_REG:
+
+       case HP_SDC_STATUS_REG:
                hp_sdc_take(irq, dev_id, status, data);
                break;
-             case HP_SDC_STATUS_HILCMD:
-             case HP_SDC_STATUS_HILDATA:
+
+       case HP_SDC_STATUS_HILCMD:
+       case HP_SDC_STATUS_HILDATA:
                read_lock(&hp_sdc.hook_lock);
                if (hp_sdc.hil != NULL)
                        hp_sdc.hil(irq, dev_id, status, data);
                read_unlock(&hp_sdc.hook_lock);
                break;
-             case HP_SDC_STATUS_PUP:
+
+       case HP_SDC_STATUS_PUP:
                read_lock(&hp_sdc.hook_lock);
                if (hp_sdc.pup != NULL)
                        hp_sdc.pup(irq, dev_id, status, data);
-               else printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n");
+               else
+                       printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n");
                read_unlock(&hp_sdc.hook_lock);
                break;
-             default:
+
+       default:
                read_lock(&hp_sdc.hook_lock);
                if (hp_sdc.cooked != NULL)
                        hp_sdc.cooked(irq, dev_id, status, data);
                read_unlock(&hp_sdc.hook_lock);
                break;
        }
+
        return IRQ_HANDLED;
 }
 
 
-static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id) {
+static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id)
+{
        int status;
-       
+
        status = hp_sdc_status_in8();
        printk(KERN_WARNING PREFIX "NMI !\n");
 
-#if 0  
+#if 0
        if (status & HP_SDC_NMISTATUS_FHS) {
                read_lock(&hp_sdc.hook_lock);
-               if (hp_sdc.timer != NULL)
+               if (hp_sdc.timer != NULL)
                        hp_sdc.timer(irq, dev_id, status, 0);
                read_unlock(&hp_sdc.hook_lock);
-       }
-       else {
+       } else {
                /* TODO: pass this on to the HIL handler, or do SAK here? */
                printk(KERN_WARNING PREFIX "HIL NMI\n");
        }
 #endif
+
        return IRQ_HANDLED;
 }
 
@@ -278,13 +297,17 @@ static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id) {
 
 unsigned long hp_sdc_put(void);
 
-static void hp_sdc_tasklet(unsigned long foo) {
-
+static void hp_sdc_tasklet(unsigned long foo)
+{
        write_lock_irq(&hp_sdc.rtq_lock);
+
        if (hp_sdc.rcurr >= 0) {
                struct timeval tv;
+
                do_gettimeofday(&tv);
-               if (tv.tv_sec > hp_sdc.rtv.tv_sec) tv.tv_usec += 1000000;
+               if (tv.tv_sec > hp_sdc.rtv.tv_sec)
+                       tv.tv_usec += USEC_PER_SEC;
+
                if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) {
                        hp_sdc_transaction *curr;
                        uint8_t tmp;
@@ -300,27 +323,29 @@ static void hp_sdc_tasklet(unsigned long foo) {
                        hp_sdc.rqty = 0;
                        tmp = curr->seq[curr->actidx];
                        curr->seq[curr->actidx] |= HP_SDC_ACT_DEAD;
-                       if(tmp & HP_SDC_ACT_SEMAPHORE) {
-                               if (curr->act.semaphore) 
+                       if (tmp & HP_SDC_ACT_SEMAPHORE)
+                               if (curr->act.semaphore)
                                        up(curr->act.semaphore);
-                       }
-                       if(tmp & HP_SDC_ACT_CALLBACK) {
+
+                       if (tmp & HP_SDC_ACT_CALLBACK) {
                                /* Note this means that irqhooks may be called
                                 * in tasklet/bh context.
                                 */
-                               if (curr->act.irqhook) 
+                               if (curr->act.irqhook)
                                        curr->act.irqhook(0, NULL, 0, 0);
                        }
+
                        curr->actidx = curr->idx;
                        curr->idx++;
-                       hp_sdc.rcurr = -1; 
+                       hp_sdc.rcurr = -1;
                }
        }
        write_unlock_irq(&hp_sdc.rtq_lock);
        hp_sdc_put();
 }
 
-unsigned long hp_sdc_put(void) {
+unsigned long hp_sdc_put(void)
+{
        hp_sdc_transaction *curr;
        uint8_t act;
        int idx, curridx;
@@ -333,19 +358,24 @@ unsigned long hp_sdc_put(void) {
           requires output, so we skip to the administrativa. */
        if (hp_sdc.ibf) {
                hp_sdc_status_in8();
-               if (hp_sdc.ibf) goto finish;
+               if (hp_sdc.ibf)
+                       goto finish;
        }
 
  anew:
        /* See if we are in the middle of a sequence. */
-       if (hp_sdc.wcurr < 0) hp_sdc.wcurr = 0;
+       if (hp_sdc.wcurr < 0)
+               hp_sdc.wcurr = 0;
        read_lock_irq(&hp_sdc.rtq_lock);
-       if (hp_sdc.rcurr == hp_sdc.wcurr) hp_sdc.wcurr++;
+       if (hp_sdc.rcurr == hp_sdc.wcurr)
+               hp_sdc.wcurr++;
        read_unlock_irq(&hp_sdc.rtq_lock);
-       if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
+       if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
+               hp_sdc.wcurr = 0;
        curridx = hp_sdc.wcurr;
 
-       if (hp_sdc.tq[curridx] != NULL) goto start;
+       if (hp_sdc.tq[curridx] != NULL)
+               goto start;
 
        while (++curridx != hp_sdc.wcurr) {
                if (curridx >= HP_SDC_QUEUE_LEN) {
@@ -358,7 +388,8 @@ unsigned long hp_sdc_put(void) {
                        continue;
                }
                read_unlock_irq(&hp_sdc.rtq_lock);
-               if (hp_sdc.tq[curridx] != NULL) break; /* Found one. */
+               if (hp_sdc.tq[curridx] != NULL)
+                       break; /* Found one. */
        }
        if (curridx == hp_sdc.wcurr) { /* There's nothing queued to do. */
                curridx = -1;
@@ -374,7 +405,8 @@ unsigned long hp_sdc_put(void) {
                goto finish;
        }
 
-       if (hp_sdc.wcurr == -1) goto done;
+       if (hp_sdc.wcurr == -1)
+               goto done;
 
        curr = hp_sdc.tq[curridx];
        idx = curr->actidx;
@@ -383,20 +415,23 @@ unsigned long hp_sdc_put(void) {
                hp_sdc.tq[curridx] = NULL;
                /* Interleave outbound data between the transactions. */
                hp_sdc.wcurr++;
-               if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
-               goto finish;    
+               if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
+                       hp_sdc.wcurr = 0;
+               goto finish;
        }
 
        act = curr->seq[idx];
        idx++;
 
        if (curr->idx >= curr->endidx) {
-               if (act & HP_SDC_ACT_DEALLOC) kfree(curr);
+               if (act & HP_SDC_ACT_DEALLOC)
+                       kfree(curr);
                hp_sdc.tq[curridx] = NULL;
                /* Interleave outbound data between the transactions. */
                hp_sdc.wcurr++;
-               if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
-               goto finish;    
+               if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
+                       hp_sdc.wcurr = 0;
+               goto finish;
        }
 
        while (act & HP_SDC_ACT_PRECMD) {
@@ -409,9 +444,10 @@ unsigned long hp_sdc_put(void) {
                curr->idx++;
                /* act finished? */
                if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_PRECMD)
-                 goto actdone;
+                       goto actdone;
                /* skip quantity field if data-out sequence follows. */
-               if (act & HP_SDC_ACT_DATAOUT) curr->idx++;
+               if (act & HP_SDC_ACT_DATAOUT)
+                       curr->idx++;
                goto finish;
        }
        if (act & HP_SDC_ACT_DATAOUT) {
@@ -423,15 +459,15 @@ unsigned long hp_sdc_put(void) {
                        hp_sdc_data_out8(curr->seq[curr->idx]);
                        curr->idx++;
                        /* act finished? */
-                       if ((curr->idx - idx >= qty) && 
-                           ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT))
+                       if (curr->idx - idx >= qty &&
+                           (act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT)
                                goto actdone;
                        goto finish;
                }
                idx += qty;
                act &= ~HP_SDC_ACT_DATAOUT;
-       }
-       else while (act & HP_SDC_ACT_DATAREG) {
+       } else
+           while (act & HP_SDC_ACT_DATAREG) {
                int mask;
                uint8_t w7[4];
 
@@ -445,26 +481,30 @@ unsigned long hp_sdc_put(void) {
                        act &= ~HP_SDC_ACT_DATAREG;
                        break;
                }
-               
+
                w7[0] = (mask & 1) ? curr->seq[++idx] : hp_sdc.r7[0];
                w7[1] = (mask & 2) ? curr->seq[++idx] : hp_sdc.r7[1];
                w7[2] = (mask & 4) ? curr->seq[++idx] : hp_sdc.r7[2];
                w7[3] = (mask & 8) ? curr->seq[++idx] : hp_sdc.r7[3];
-               
+
                if (hp_sdc.wi > 0x73 || hp_sdc.wi < 0x70 ||
-                       w7[hp_sdc.wi-0x70] == hp_sdc.r7[hp_sdc.wi-0x70]) {
+                   w7[hp_sdc.wi - 0x70] == hp_sdc.r7[hp_sdc.wi - 0x70]) {
                        int i = 0;
 
-                       /* Need to point the write index register */    
-                       while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++;
+                       /* Need to point the write index register */
+                       while (i < 4 && w7[i] == hp_sdc.r7[i])
+                               i++;
+
                        if (i < 4) {
                                hp_sdc_status_out8(HP_SDC_CMD_SET_D0 + i);
                                hp_sdc.wi = 0x70 + i;
                                goto finish;
                        }
+
                        idx++;
                        if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG)
                                goto actdone;
+
                        curr->idx = idx;
                        act &= ~HP_SDC_ACT_DATAREG;
                        break;
@@ -476,12 +516,13 @@ unsigned long hp_sdc_put(void) {
                {
                        int i = 0;
 
-                       while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++;
+                       while ((i < 4) && w7[i] == hp_sdc.r7[i])
+                               i++;
                        if (i >= 4) {
                                curr->idx = idx + 1;
-                               if ((act & HP_SDC_ACT_DURING) == 
+                               if ((act & HP_SDC_ACT_DURING) ==
                                    HP_SDC_ACT_DATAREG)
-                                       goto actdone;
+                                       goto actdone;
                        }
                }
                goto finish;
@@ -497,7 +538,7 @@ unsigned long hp_sdc_put(void) {
 
 
        if (act & HP_SDC_ACT_POSTCMD) {
-               uint8_t postcmd;
+               uint8_t postcmd;
 
                /* curr->idx should == idx at this point. */
                postcmd = curr->seq[idx];
@@ -505,12 +546,12 @@ unsigned long hp_sdc_put(void) {
                if (act & HP_SDC_ACT_DATAIN) {
 
                        /* Start a new read */
-                       hp_sdc.rqty = curr->seq[curr->idx];
+                       hp_sdc.rqty = curr->seq[curr->idx];
                        do_gettimeofday(&hp_sdc.rtv);
                        curr->idx++;
                        /* Still need to lock here in case of spurious irq. */
                        write_lock_irq(&hp_sdc.rtq_lock);
-                       hp_sdc.rcurr = curridx; 
+                       hp_sdc.rcurr = curridx;
                        write_unlock_irq(&hp_sdc.rtq_lock);
                        hp_sdc_status_out8(postcmd);
                        goto finish;
@@ -519,75 +560,86 @@ unsigned long hp_sdc_put(void) {
                goto actdone;
        }
 
-actdone:
-       if (act & HP_SDC_ACT_SEMAPHORE) {
+ actdone:
+       if (act & HP_SDC_ACT_SEMAPHORE)
                up(curr->act.semaphore);
-       }
-       else if (act & HP_SDC_ACT_CALLBACK) {
+       else if (act & HP_SDC_ACT_CALLBACK)
                curr->act.irqhook(0,NULL,0,0);
-       }
+
        if (curr->idx >= curr->endidx) { /* This transaction is over. */
-               if (act & HP_SDC_ACT_DEALLOC) kfree(curr);
+               if (act & HP_SDC_ACT_DEALLOC)
+                       kfree(curr);
                hp_sdc.tq[curridx] = NULL;
-       }
-       else {
+       } else {
                curr->actidx = idx + 1;
                curr->idx = idx + 2;
        }
        /* Interleave outbound data between the transactions. */
        hp_sdc.wcurr++;
-       if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
+       if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
+               hp_sdc.wcurr = 0;
 
  finish:
-       /* If by some quirk IBF has cleared and our ISR has run to 
+       /* If by some quirk IBF has cleared and our ISR has run to
           see that that has happened, do it all again. */
-       if (!hp_sdc.ibf && limit++ < 20) goto anew;
+       if (!hp_sdc.ibf && limit++ < 20)
+               goto anew;
 
  done:
-       if (hp_sdc.wcurr >= 0) tasklet_schedule(&hp_sdc.task);
+       if (hp_sdc.wcurr >= 0)
+               tasklet_schedule(&hp_sdc.task);
        write_unlock(&hp_sdc.lock);
+
        return 0;
 }
 
 /******* Functions called in either user or kernel context ****/
-int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) {
-       unsigned long flags;
+int __hp_sdc_enqueue_transaction(hp_sdc_transaction *this)
+{
        int i;
 
        if (this == NULL) {
-               tasklet_schedule(&hp_sdc.task);
+               BUG();
                return -EINVAL;
-       };
-
-       write_lock_irqsave(&hp_sdc.lock, flags);
+       }
 
        /* Can't have same transaction on queue twice */
-       for (i=0; i < HP_SDC_QUEUE_LEN; i++)
-               if (hp_sdc.tq[i] == this) goto fail;
+       for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
+               if (hp_sdc.tq[i] == this)
+                       goto fail;
 
        this->actidx = 0;
        this->idx = 1;
 
        /* Search for empty slot */
-       for (i=0; i < HP_SDC_QUEUE_LEN; i++) {
+       for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
                if (hp_sdc.tq[i] == NULL) {
                        hp_sdc.tq[i] = this;
-                       write_unlock_irqrestore(&hp_sdc.lock, flags);
                        tasklet_schedule(&hp_sdc.task);
                        return 0;
                }
-       }
-       write_unlock_irqrestore(&hp_sdc.lock, flags);
+
        printk(KERN_WARNING PREFIX "No free slot to add transaction.\n");
        return -EBUSY;
 
  fail:
-       write_unlock_irqrestore(&hp_sdc.lock,flags);
        printk(KERN_WARNING PREFIX "Transaction add failed: transaction already queued?\n");
        return -EINVAL;
 }
 
-int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) {
+int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) {
+       unsigned long flags;
+       int ret;
+
+       write_lock_irqsave(&hp_sdc.lock, flags);
+       ret = __hp_sdc_enqueue_transaction(this);
+       write_unlock_irqrestore(&hp_sdc.lock,flags);
+
+       return ret;
+}
+
+int hp_sdc_dequeue_transaction(hp_sdc_transaction *this)
+{
        unsigned long flags;
        int i;
 
@@ -595,8 +647,9 @@ int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) {
 
        /* TODO: don't remove it if it's not done. */
 
-       for (i=0; i < HP_SDC_QUEUE_LEN; i++)
-               if (hp_sdc.tq[i] == this) hp_sdc.tq[i] = NULL;
+       for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
+               if (hp_sdc.tq[i] == this)
+                       hp_sdc.tq[i] = NULL;
 
        write_unlock_irqrestore(&hp_sdc.lock, flags);
        return 0;
@@ -605,11 +658,11 @@ int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) {
 
 
 /********************** User context functions **************************/
-int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback) {
-
-       if (callback == NULL || hp_sdc.dev == NULL) {
+int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback)
+{
+       if (callback == NULL || hp_sdc.dev == NULL)
                return -EINVAL;
-       }
+
        write_lock_irq(&hp_sdc.hook_lock);
        if (hp_sdc.timer != NULL) {
                write_unlock_irq(&hp_sdc.hook_lock);
@@ -629,11 +682,11 @@ int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback) {
        return 0;
 }
 
-int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback) {
-
-       if (callback == NULL || hp_sdc.dev == NULL) {
+int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback)
+{
+       if (callback == NULL || hp_sdc.dev == NULL)
                return -EINVAL;
-       }
+
        write_lock_irq(&hp_sdc.hook_lock);
        if (hp_sdc.hil != NULL) {
                write_unlock_irq(&hp_sdc.hook_lock);
@@ -650,11 +703,11 @@ int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback) {
        return 0;
 }
 
-int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback) {
-
-       if (callback == NULL || hp_sdc.dev == NULL) {
+int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback)
+{
+       if (callback == NULL || hp_sdc.dev == NULL)
                return -EINVAL;
-       }
+
        write_lock_irq(&hp_sdc.hook_lock);
        if (hp_sdc.cooked != NULL) {
                write_unlock_irq(&hp_sdc.hook_lock);
@@ -672,9 +725,8 @@ int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback) {
        return 0;
 }
 
-int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback) {
-
-
+int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback)
+{
        write_lock_irq(&hp_sdc.hook_lock);
        if ((callback != hp_sdc.timer) ||
            (hp_sdc.timer == NULL)) {
@@ -694,8 +746,8 @@ int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback) {
        return 0;
 }
 
-int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback) {
-
+int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback)
+{
        write_lock_irq(&hp_sdc.hook_lock);
        if ((callback != hp_sdc.hil) ||
            (hp_sdc.hil == NULL)) {
@@ -715,8 +767,8 @@ int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback) {
        return 0;
 }
 
-int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) {
-
+int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback)
+{
        write_lock_irq(&hp_sdc.hook_lock);
        if ((callback != hp_sdc.cooked) ||
            (hp_sdc.cooked == NULL)) {
@@ -738,7 +790,8 @@ int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) {
 
 /************************* Keepalive timer task *********************/
 
-void hp_sdc_kicker (unsigned long data) {
+void hp_sdc_kicker (unsigned long data)
+{
        tasklet_schedule(&hp_sdc.task);
        /* Re-insert the periodic task. */
        mod_timer(&hp_sdc.kicker, jiffies + HZ);
@@ -748,12 +801,12 @@ void hp_sdc_kicker (unsigned long data) {
 
 #if defined(__hppa__)
 
-static struct parisc_device_id hp_sdc_tbl[] = {
+static const struct parisc_device_id hp_sdc_tbl[] = {
        {
-               .hw_type =      HPHW_FIO, 
+               .hw_type =      HPHW_FIO,
                .hversion_rev = HVERSION_REV_ANY_ID,
                .hversion =     HVERSION_ANY_ID,
-               .sversion =     0x73, 
+               .sversion =     0x73,
         },
        { 0, }
 };
@@ -772,16 +825,15 @@ static struct parisc_driver hp_sdc_driver = {
 
 static int __init hp_sdc_init(void)
 {
-       int i;
        char *errstr;
        hp_sdc_transaction t_sync;
        uint8_t ts_sync[6];
        struct semaphore s_sync;
 
-       rwlock_init(&hp_sdc.lock);
-       rwlock_init(&hp_sdc.ibf_lock);
-       rwlock_init(&hp_sdc.rtq_lock);
-       rwlock_init(&hp_sdc.hook_lock);
+       rwlock_init(&hp_sdc.lock);
+       rwlock_init(&hp_sdc.ibf_lock);
+       rwlock_init(&hp_sdc.rtq_lock);
+       rwlock_init(&hp_sdc.hook_lock);
 
        hp_sdc.timer            = NULL;
        hp_sdc.hil              = NULL;
@@ -796,7 +848,8 @@ static int __init hp_sdc_init(void)
        hp_sdc.r7[3]            = 0xff;
        hp_sdc.ibf              = 1;
 
-       for (i = 0; i < HP_SDC_QUEUE_LEN; i++) hp_sdc.tq[i] = NULL;
+       memset(&hp_sdc.tq, 0, sizeof(hp_sdc.tq));
+
        hp_sdc.wcurr            = -1;
         hp_sdc.rcurr           = -1;
        hp_sdc.rqty             = 0;
@@ -804,27 +857,32 @@ static int __init hp_sdc_init(void)
        hp_sdc.dev_err = -ENODEV;
 
        errstr = "IO not found for";
-       if (!hp_sdc.base_io) goto err0;
+       if (!hp_sdc.base_io)
+               goto err0;
 
        errstr = "IRQ not found for";
-       if (!hp_sdc.irq) goto err0;
+       if (!hp_sdc.irq)
+               goto err0;
 
        hp_sdc.dev_err = -EBUSY;
 
 #if defined(__hppa__)
        errstr = "IO not available for";
-        if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name)) goto err0;
-#endif 
+        if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name))
+               goto err0;
+#endif
 
        errstr = "IRQ not available for";
-        if(request_irq(hp_sdc.irq, &hp_sdc_isr, 0, "HP SDC",
-                      (void *) hp_sdc.base_io)) goto err1;
+       if (request_irq(hp_sdc.irq, &hp_sdc_isr, IRQF_SHARED|IRQF_SAMPLE_RANDOM,
+                       "HP SDC", &hp_sdc))
+               goto err1;
 
        errstr = "NMI not available for";
-       if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, 0, "HP SDC NMI", 
-                       (void *) hp_sdc.base_io)) goto err2;
+       if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, IRQF_SHARED,
+                       "HP SDC NMI", &hp_sdc))
+               goto err2;
 
-       printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n", 
+       printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n",
               (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
 
        hp_sdc_status_in8();
@@ -854,13 +912,14 @@ static int __init hp_sdc_init(void)
        hp_sdc.dev_err = 0;
        return 0;
  err2:
-       free_irq(hp_sdc.irq, NULL);
+       free_irq(hp_sdc.irq, &hp_sdc);
  err1:
        release_region(hp_sdc.data_io, 2);
  err0:
-       printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n", 
+       printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n",
                errstr, (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
        hp_sdc.dev = NULL;
+
        return hp_sdc.dev_err;
 }
 
@@ -868,8 +927,10 @@ static int __init hp_sdc_init(void)
 
 static int __init hp_sdc_init_hppa(struct parisc_device *d)
 {
-       if (!d) return 1;
-       if (hp_sdc.dev != NULL) return 1;       /* We only expect one SDC */
+       if (!d)
+               return 1;
+       if (hp_sdc.dev != NULL)
+               return 1;       /* We only expect one SDC */
 
        hp_sdc.dev              = d;
        hp_sdc.irq              = d->irq;
@@ -898,18 +959,16 @@ static void hp_sdc_exit(void)
        /* Wait until we know this has been processed by the i8042 */
        hp_sdc_spin_ibf();
 
-       free_irq(hp_sdc.nmi, NULL);
-       free_irq(hp_sdc.irq, NULL);
+       free_irq(hp_sdc.nmi, &hp_sdc);
+       free_irq(hp_sdc.irq, &hp_sdc);
        write_unlock_irq(&hp_sdc.lock);
 
        del_timer(&hp_sdc.kicker);
 
        tasklet_kill(&hp_sdc.task);
 
-/*        release_region(hp_sdc.data_io, 2); */
-
 #if defined(__hppa__)
-       if (unregister_parisc_driver(&hp_sdc_driver)) 
+       if (unregister_parisc_driver(&hp_sdc_driver))
                printk(KERN_WARNING PREFIX "Error unregistering HP SDC");
 #endif
 }
@@ -923,7 +982,7 @@ static int __init hp_sdc_register(void)
        mm_segment_t fs;
        unsigned char i;
 #endif
-       
+
        hp_sdc.dev = NULL;
        hp_sdc.dev_err = 0;
 #if defined(__hppa__)
@@ -960,8 +1019,8 @@ static int __init hp_sdc_register(void)
        tq_init.seq             = tq_init_seq;
        tq_init.act.semaphore   = &tq_init_sem;
 
-       tq_init_seq[0] = 
-         HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
+       tq_init_seq[0] =
+               HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
        tq_init_seq[1] = HP_SDC_CMD_READ_KCC;
        tq_init_seq[2] = 1;
        tq_init_seq[3] = 0;
@@ -979,13 +1038,13 @@ static int __init hp_sdc_register(void)
        }
        hp_sdc.r11 = tq_init_seq[4];
        if (hp_sdc.r11 & HP_SDC_CFG_NEW) {
-               char *str;
+               const char *str;
                printk(KERN_INFO PREFIX "New style SDC\n");
                tq_init_seq[1] = HP_SDC_CMD_READ_XTD;
                tq_init.actidx          = 0;
                tq_init.idx             = 1;
                down(&tq_init_sem);
-               hp_sdc_enqueue_transaction(&tq_init);           
+               hp_sdc_enqueue_transaction(&tq_init);
                down(&tq_init_sem);
                up(&tq_init_sem);
                if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
@@ -995,15 +1054,13 @@ static int __init hp_sdc_register(void)
                hp_sdc.r7e = tq_init_seq[4];
                HP_SDC_XTD_REV_STRINGS(hp_sdc.r7e & HP_SDC_XTD_REV, str)
                printk(KERN_INFO PREFIX "Revision: %s\n", str);
-               if (hp_sdc.r7e & HP_SDC_XTD_BEEPER) {
+               if (hp_sdc.r7e & HP_SDC_XTD_BEEPER)
                        printk(KERN_INFO PREFIX "TI SN76494 beeper present\n");
-               }
-               if (hp_sdc.r7e & HP_SDC_XTD_BBRTC) {
+               if (hp_sdc.r7e & HP_SDC_XTD_BBRTC)
                        printk(KERN_INFO PREFIX "OKI MSM-58321 BBRTC present\n");
-               }
                printk(KERN_INFO PREFIX "Spunking the self test register to force PUP "
                       "on next firmware reset.\n");
-               tq_init_seq[0] = HP_SDC_ACT_PRECMD | 
+               tq_init_seq[0] = HP_SDC_ACT_PRECMD |
                        HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
                tq_init_seq[1] = HP_SDC_CMD_SET_STR;
                tq_init_seq[2] = 1;
@@ -1012,14 +1069,12 @@ static int __init hp_sdc_register(void)
                tq_init.idx             = 1;
                tq_init.endidx          = 4;
                down(&tq_init_sem);
-               hp_sdc_enqueue_transaction(&tq_init);           
+               hp_sdc_enqueue_transaction(&tq_init);
                down(&tq_init_sem);
                up(&tq_init_sem);
-       }
-       else {
-               printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n", 
+       } else
+               printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n",
                       (hp_sdc.r11 & HP_SDC_CFG_REV) ? "3300" : "2564/3087");
-       }
 
         return 0;
 }
@@ -1027,13 +1082,13 @@ static int __init hp_sdc_register(void)
 module_init(hp_sdc_register);
 module_exit(hp_sdc_exit);
 
-/* Timing notes:  These measurements taken on my 64MHz 7100-LC (715/64) 
+/* Timing notes:  These measurements taken on my 64MHz 7100-LC (715/64)
  *                                              cycles cycles-adj    time
  * between two consecutive mfctl(16)'s:              4        n/a    63ns
  * hp_sdc_spin_ibf when idle:                      119        115   1.7us
  * gsc_writeb status register:                      83         79   1.2us
  * IBF to clear after sending SET_IM:             6204       6006    93us
- * IBF to clear after sending LOAD_RT:            4467       4352    68us  
+ * IBF to clear after sending LOAD_RT:            4467       4352    68us
  * IBF to clear after sending two LOAD_RTs:      18974      18859   295us
  * READ_T1, read status/data, IRQ, call handler: 35564        n/a   556us
  * cmd to ~IBF READ_T1 2nd time right after:   5158403        n/a    81ms
index aa4a8a4..c45ea74 100644 (file)
@@ -58,12 +58,13 @@ struct hp_sdc_mlc_priv_s {
 } hp_sdc_mlc_priv;
 
 /************************* Interrupt context ******************************/
-static void hp_sdc_mlc_isr (int irq, void *dev_id, 
-                           uint8_t status, uint8_t data) {
-       int idx;
+static void hp_sdc_mlc_isr (int irq, void *dev_id,
+                           uint8_t status, uint8_t data)
+{
+       int idx;
        hil_mlc *mlc = &hp_sdc_mlc;
 
-       write_lock(&(mlc->lock));
+       write_lock(&mlc->lock);
        if (mlc->icount < 0) {
                printk(KERN_WARNING PREFIX "HIL Overflow!\n");
                up(&mlc->isem);
@@ -73,239 +74,232 @@ static void hp_sdc_mlc_isr (int irq, void *dev_id,
        if ((status & HP_SDC_STATUS_IRQMASK) == HP_SDC_STATUS_HILDATA) {
                mlc->ipacket[idx] |= data | HIL_ERR_INT;
                mlc->icount--;
-               if (hp_sdc_mlc_priv.got5x) goto check;
-               if (!idx) goto check;
-               if ((mlc->ipacket[idx-1] & HIL_PKT_ADDR_MASK) !=
+               if (hp_sdc_mlc_priv.got5x || !idx)
+                       goto check;
+               if ((mlc->ipacket[idx - 1] & HIL_PKT_ADDR_MASK) !=
                    (mlc->ipacket[idx] & HIL_PKT_ADDR_MASK)) {
                        mlc->ipacket[idx] &= ~HIL_PKT_ADDR_MASK;
-                       mlc->ipacket[idx] |= (mlc->ipacket[idx-1] 
-                                                   & HIL_PKT_ADDR_MASK);
+                       mlc->ipacket[idx] |= (mlc->ipacket[idx - 1]
+                                               & HIL_PKT_ADDR_MASK);
                }
                goto check;
        }
        /* We know status is 5X */
-       if (data & HP_SDC_HIL_ISERR) goto err;
-       mlc->ipacket[idx] = 
+       if (data & HP_SDC_HIL_ISERR)
+               goto err;
+       mlc->ipacket[idx] =
                (data & HP_SDC_HIL_R1MASK) << HIL_PKT_ADDR_SHIFT;
        hp_sdc_mlc_priv.got5x = 1;
        goto out;
 
  check:
        hp_sdc_mlc_priv.got5x = 0;
-       if (mlc->imatch == 0) goto done;
-       if ((mlc->imatch == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) 
-           && (mlc->ipacket[idx] == (mlc->imatch | idx))) goto done;
-       if (mlc->ipacket[idx] == mlc->imatch) goto done;
+       if (mlc->imatch == 0)
+               goto done;
+       if ((mlc->imatch == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL))
+           && (mlc->ipacket[idx] == (mlc->imatch | idx)))
+               goto done;
+       if (mlc->ipacket[idx] == mlc->imatch)
+               goto done;
        goto out;
 
- err:                          
+ err:
        printk(KERN_DEBUG PREFIX "err code %x\n", data);
+
        switch (data) {
        case HP_SDC_HIL_RC_DONE:
                printk(KERN_WARNING PREFIX "Bastard SDC reconfigured loop!\n");
                break;
+
        case HP_SDC_HIL_ERR:
-               mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_PERR | 
-                 HIL_ERR_FERR | HIL_ERR_FOF;
+               mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_PERR |
+                                       HIL_ERR_FERR | HIL_ERR_FOF;
                break;
+
        case HP_SDC_HIL_TO:
                mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_LERR;
                break;
+
        case HP_SDC_HIL_RC:
                printk(KERN_WARNING PREFIX "Bastard SDC decided to reconfigure loop!\n");
                break;
+
        default:
                printk(KERN_WARNING PREFIX "Unkown HIL Error status (%x)!\n", data);
                break;
        }
+
        /* No more data will be coming due to an error. */
  done:
        tasklet_schedule(mlc->tasklet);
-       up(&(mlc->isem));
+       up(&mlc->isem);
  out:
-       write_unlock(&(mlc->lock));
+       write_unlock(&mlc->lock);
 }
 
 
 /******************** Tasklet or userspace context functions ****************/
 
-static int hp_sdc_mlc_in (hil_mlc *mlc, suseconds_t timeout) {
-       unsigned long flags;
+static int hp_sdc_mlc_in(hil_mlc *mlc, suseconds_t timeout)
+{
        struct hp_sdc_mlc_priv_s *priv;
        int rc = 2;
 
        priv = mlc->priv;
 
-       write_lock_irqsave(&(mlc->lock), flags);
-
        /* Try to down the semaphore */
-       if (down_trylock(&(mlc->isem))) {
+       if (down_trylock(&mlc->isem)) {
                struct timeval tv;
                if (priv->emtestmode) {
-                       mlc->ipacket[0] = 
-                               HIL_ERR_INT | (mlc->opacket & 
-                                              (HIL_PKT_CMD | 
-                                               HIL_PKT_ADDR_MASK | 
+                       mlc->ipacket[0] =
+                               HIL_ERR_INT | (mlc->opacket &
+                                              (HIL_PKT_CMD |
+                                               HIL_PKT_ADDR_MASK |
                                                HIL_PKT_DATA_MASK));
                        mlc->icount = 14;
                        /* printk(KERN_DEBUG PREFIX ">[%x]\n", mlc->ipacket[0]); */
                        goto wasup;
                }
                do_gettimeofday(&tv);
-               tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec);
+               tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec);
                if (tv.tv_usec - mlc->instart.tv_usec > mlc->intimeout) {
-                 /*              printk("!%i %i", 
-                                 tv.tv_usec - mlc->instart.tv_usec, 
-                                 mlc->intimeout);
-                 */
+                       /*      printk("!%i %i",
+                               tv.tv_usec - mlc->instart.tv_usec,
+                               mlc->intimeout);
+                        */
                        rc = 1;
-                       up(&(mlc->isem));
+                       up(&mlc->isem);
                }
                goto done;
        }
  wasup:
-       up(&(mlc->isem));
+       up(&mlc->isem);
        rc = 0;
-       goto done;
  done:
-       write_unlock_irqrestore(&(mlc->lock), flags);
        return rc;
 }
 
-static int hp_sdc_mlc_cts (hil_mlc *mlc) {
+static int hp_sdc_mlc_cts(hil_mlc *mlc)
+{
        struct hp_sdc_mlc_priv_s *priv;
-       unsigned long flags;
 
-       priv = mlc->priv;       
-
-       write_lock_irqsave(&(mlc->lock), flags);
+       priv = mlc->priv;
 
        /* Try to down the semaphores -- they should be up. */
-       if (down_trylock(&(mlc->isem))) {
-               BUG();
-               goto busy;
-       }
-       if (down_trylock(&(mlc->osem))) {
-               BUG();
-               up(&(mlc->isem));
-               goto busy;
-       }
-       up(&(mlc->isem));
-       up(&(mlc->osem));
+       BUG_ON(down_trylock(&mlc->isem));
+       BUG_ON(down_trylock(&mlc->osem));
+
+       up(&mlc->isem);
+       up(&mlc->osem);
 
-       if (down_trylock(&(mlc->csem))) {
-               if (priv->trans.act.semaphore != &(mlc->csem)) goto poll;
-               goto busy;
+       if (down_trylock(&mlc->csem)) {
+               if (priv->trans.act.semaphore != &mlc->csem)
+                       goto poll;
+               else
+                       goto busy;
        }
-       if (!(priv->tseq[4] & HP_SDC_USE_LOOP)) goto done;
+
+       if (!(priv->tseq[4] & HP_SDC_USE_LOOP))
+               goto done;
 
  poll:
-       priv->trans.act.semaphore = &(mlc->csem);
+       priv->trans.act.semaphore = &mlc->csem;
        priv->trans.actidx = 0;
        priv->trans.idx = 1;
        priv->trans.endidx = 5;
-       priv->tseq[0] = 
+       priv->tseq[0] =
                HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
        priv->tseq[1] = HP_SDC_CMD_READ_USE;
        priv->tseq[2] = 1;
        priv->tseq[3] = 0;
        priv->tseq[4] = 0;
-       hp_sdc_enqueue_transaction(&(priv->trans));
+       __hp_sdc_enqueue_transaction(&priv->trans);
  busy:
-       write_unlock_irqrestore(&(mlc->lock), flags);
        return 1;
  done:
-       priv->trans.act.semaphore = &(mlc->osem);
-       up(&(mlc->csem));
-       write_unlock_irqrestore(&(mlc->lock), flags);
+       priv->trans.act.semaphore = &mlc->osem;
+       up(&mlc->csem);
        return 0;
 }
 
-static void hp_sdc_mlc_out (hil_mlc *mlc) {
+static void hp_sdc_mlc_out(hil_mlc *mlc)
+{
        struct hp_sdc_mlc_priv_s *priv;
-       unsigned long flags;
 
        priv = mlc->priv;
 
-       write_lock_irqsave(&(mlc->lock), flags);
-       
        /* Try to down the semaphore -- it should be up. */
-       if (down_trylock(&(mlc->osem))) {
-               BUG();
-               goto done;
-       }
+       BUG_ON(down_trylock(&mlc->osem));
 
-       if (mlc->opacket & HIL_DO_ALTER_CTRL) goto do_control;
+       if (mlc->opacket & HIL_DO_ALTER_CTRL)
+               goto do_control;
 
  do_data:
        if (priv->emtestmode) {
-               up(&(mlc->osem));
-               goto done;
+               up(&mlc->osem);
+               return;
        }
        /* Shouldn't be sending commands when loop may be busy */
-       if (down_trylock(&(mlc->csem))) {
-               BUG();
-               goto done;
-       }
-       up(&(mlc->csem));
+       BUG_ON(down_trylock(&mlc->csem));
+       up(&mlc->csem);
 
        priv->trans.actidx = 0;
        priv->trans.idx = 1;
-       priv->trans.act.semaphore = &(mlc->osem);
+       priv->trans.act.semaphore = &mlc->osem;
        priv->trans.endidx = 6;
-       priv->tseq[0] = 
+       priv->tseq[0] =
                HP_SDC_ACT_DATAREG | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_SEMAPHORE;
        priv->tseq[1] = 0x7;
-       priv->tseq[2] = 
-               (mlc->opacket & 
+       priv->tseq[2] =
+               (mlc->opacket &
                 (HIL_PKT_ADDR_MASK | HIL_PKT_CMD))
                   >> HIL_PKT_ADDR_SHIFT;
-       priv->tseq[3] = 
-               (mlc->opacket & HIL_PKT_DATA_MASK) 
+       priv->tseq[3] =
+               (mlc->opacket & HIL_PKT_DATA_MASK)
                  >> HIL_PKT_DATA_SHIFT;
        priv->tseq[4] = 0;  /* No timeout */
-       if (priv->tseq[3] == HIL_CMD_DHR) priv->tseq[4] = 1;
+       if (priv->tseq[3] == HIL_CMD_DHR)
+               priv->tseq[4] = 1;
        priv->tseq[5] = HP_SDC_CMD_DO_HIL;
        goto enqueue;
 
  do_control:
        priv->emtestmode = mlc->opacket & HIL_CTRL_TEST;
-       
+
        /* we cannot emulate this, it should not be used. */
        BUG_ON((mlc->opacket & (HIL_CTRL_APE | HIL_CTRL_IPF)) == HIL_CTRL_APE);
-       
-       if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY) goto control_only;
-       if (mlc->opacket & HIL_CTRL_APE) { 
-               BUG(); /* Should not send command/data after engaging APE */
-               goto done;
-       }
-       /* Disengaging APE this way would not be valid either since 
+
+       if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY)
+               goto control_only;
+
+       /* Should not send command/data after engaging APE */
+       BUG_ON(mlc->opacket & HIL_CTRL_APE);
+
+       /* Disengaging APE this way would not be valid either since
         * the loop must be allowed to idle.
         *
-        * So, it works out that we really never actually send control 
-        * and data when using SDC, we just send the data. 
+        * So, it works out that we really never actually send control
+        * and data when using SDC, we just send the data.
         */
        goto do_data;
 
  control_only:
        priv->trans.actidx = 0;
        priv->trans.idx = 1;
-       priv->trans.act.semaphore = &(mlc->osem);
+       priv->trans.act.semaphore = &mlc->osem;
        priv->trans.endidx = 4;
-       priv->tseq[0] = 
+       priv->tseq[0] =
          HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
        priv->tseq[1] = HP_SDC_CMD_SET_LPC;
        priv->tseq[2] = 1;
-       //      priv->tseq[3] = (mlc->ddc + 1) | HP_SDC_LPS_ACSUCC;
+       /* priv->tseq[3] = (mlc->ddc + 1) | HP_SDC_LPS_ACSUCC; */
        priv->tseq[3] = 0;
        if (mlc->opacket & HIL_CTRL_APE) {
                priv->tseq[3] |= HP_SDC_LPC_APE_IPF;
-               down_trylock(&(mlc->csem));
-       } 
+               down_trylock(&mlc->csem);
+       }
  enqueue:
-       hp_sdc_enqueue_transaction(&(priv->trans));
- done:
-       write_unlock_irqrestore(&(mlc->lock), flags);
+       hp_sdc_enqueue_transaction(&priv->trans);
 }
 
 static int __init hp_sdc_mlc_init(void)
@@ -316,18 +310,18 @@ static int __init hp_sdc_mlc_init(void)
 
        hp_sdc_mlc_priv.emtestmode = 0;
        hp_sdc_mlc_priv.trans.seq = hp_sdc_mlc_priv.tseq;
-       hp_sdc_mlc_priv.trans.act.semaphore = &(mlc->osem);
+       hp_sdc_mlc_priv.trans.act.semaphore = &mlc->osem;
        hp_sdc_mlc_priv.got5x = 0;
 
-       mlc->cts                = &hp_sdc_mlc_cts;
-       mlc->in                 = &hp_sdc_mlc_in;
-       mlc->out                = &hp_sdc_mlc_out;
+       mlc->cts = &hp_sdc_mlc_cts;
+       mlc->in = &hp_sdc_mlc_in;
+       mlc->out = &hp_sdc_mlc_out;
+       mlc->priv = &hp_sdc_mlc_priv;
 
        if (hil_mlc_register(mlc)) {
                printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n");
                goto err0;
        }
-       mlc->priv               = &hp_sdc_mlc_priv;
 
        if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) {
                printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n");
@@ -335,10 +329,9 @@ static int __init hp_sdc_mlc_init(void)
        }
        return 0;
  err1:
-       if (hil_mlc_unregister(mlc)) {
+       if (hil_mlc_unregister(mlc))
                printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
                        "This is bad.  Could cause an oops.\n");
-       }
  err0:
        return -EBUSY;
 }
@@ -346,14 +339,14 @@ static int __init hp_sdc_mlc_init(void)
 static void __exit hp_sdc_mlc_exit(void)
 {
        hil_mlc *mlc = &hp_sdc_mlc;
-       if (hp_sdc_release_hil_irq(&hp_sdc_mlc_isr)) {
+
+       if (hp_sdc_release_hil_irq(&hp_sdc_mlc_isr))
                printk(KERN_ERR PREFIX "Failed to release the raw HIL ISR hook.\n"
                        "This is bad.  Could cause an oops.\n");
-       }
-       if (hil_mlc_unregister(mlc)) {
+
+       if (hil_mlc_unregister(mlc))
                printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
                        "This is bad.  Could cause an oops.\n");
-       }
 }
 
 module_init(hp_sdc_mlc_init);
index d36bd54..6858bc5 100644 (file)
@@ -160,6 +160,28 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
                },
        },
        {
+               /*
+                * No data is coming from the touchscreen unless KBC
+                * is in legacy mode.
+                */
+               .ident = "Panasonic CF-29",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"),
+               },
+       },
+       {
+               /*
+                * Errors on MUX ports are reported without raising AUXDATA
+                * causing "spurious NAK" messages.
+                */
+               .ident = "HP Pavilion DV4017EA",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EA032EA#ABF)"),
+               },
+       },
+       {
                .ident = "Toshiba P10",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
@@ -280,6 +302,8 @@ static struct pnp_driver i8042_pnp_kbd_driver = {
 };
 
 static struct pnp_device_id pnp_aux_devids[] = {
+       { .id = "FJC6000", .driver_data = 0 },
+       { .id = "FJC6001", .driver_data = 0 },
        { .id = "PNP0f03", .driver_data = 0 },
        { .id = "PNP0f0b", .driver_data = 0 },
        { .id = "PNP0f0e", .driver_data = 0 },
index db9cca3..7c17377 100644 (file)
@@ -768,6 +768,13 @@ static void i8042_controller_reset(void)
        i8042_flush();
 
 /*
+ * Disable both KBD and AUX interfaces so they don't get in the way
+ */
+
+       i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS;
+       i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT);
+
+/*
  * Disable MUX mode if present.
  */
 
index 0a26e06..693e3b2 100644 (file)
@@ -39,7 +39,8 @@
 /*
  * This code has been heavily tested on a Nokia 770, and lightly
  * tested on other ads7846 devices (OSK/Mistral, Lubbock).
- * Support for ads7843 and ads7845 has only been stubbed in.
+ * Support for ads7843 tested on Atmel at91sam926x-EK.
+ * Support for ads7845 has only been stubbed in.
  *
  * IRQ handling needs a workaround because of a shortcoming in handling
  * edge triggered IRQs on some platforms like the OMAP1/2. These
@@ -246,18 +247,16 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
 
        /* REVISIT:  take a few more samples, and compare ... */
 
-       /* maybe off internal vREF */
-       if (use_internal) {
-               req->ref_off = REF_OFF;
-               req->xfer[4].tx_buf = &req->ref_off;
-               req->xfer[4].len = 1;
-               spi_message_add_tail(&req->xfer[4], &req->msg);
-
-               req->xfer[5].rx_buf = &req->scratch;
-               req->xfer[5].len = 2;
-               CS_CHANGE(req->xfer[5]);
-               spi_message_add_tail(&req->xfer[5], &req->msg);
-       }
+       /* converter in low power mode & enable PENIRQ */
+       req->ref_off = PWRDOWN;
+       req->xfer[4].tx_buf = &req->ref_off;
+       req->xfer[4].len = 1;
+       spi_message_add_tail(&req->xfer[4], &req->msg);
+
+       req->xfer[5].rx_buf = &req->scratch;
+       req->xfer[5].len = 2;
+       CS_CHANGE(req->xfer[5]);
+       spi_message_add_tail(&req->xfer[5], &req->msg);
 
        ts->irq_disabled = 1;
        disable_irq(spi->irq);
@@ -536,6 +535,9 @@ static void ads7846_rx(void *ads)
        } else
                Rt = 0;
 
+       if (ts->model == 7843)
+               Rt = ts->pressure_max / 2;
+
        /* Sample found inconsistent by debouncing or pressure is beyond
         * the maximum. Don't report it to user space, repeat at least
         * once more the measurement
@@ -897,7 +899,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
 
        input_dev->name = "ADS784x Touchscreen";
        input_dev->phys = ts->phys;
-       input_dev->cdev.dev = &spi->dev;
+       input_dev->dev.parent = &spi->dev;
 
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
        input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
index e294558..e6a31d1 100644 (file)
@@ -300,8 +300,7 @@ static int __init corgits_probe(struct platform_device *pdev)
        input_dev->id.vendor = 0x0001;
        input_dev->id.product = 0x0002;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &pdev->dev;
-       input_dev->private = corgi_ts;
+       input_dev->dev.parent = &pdev->dev;
 
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
        input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
index 9d61cd1..557d781 100644 (file)
@@ -312,14 +312,13 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
        init_completion(&elo->cmd_done);
        snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys);
 
-       input_dev->private = elo;
        input_dev->name = "Elo Serial TouchScreen";
        input_dev->phys = elo->phys;
        input_dev->id.bustype = BUS_RS232;
        input_dev->id.vendor = SERIO_ELO;
        input_dev->id.product = elo->id;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &serio->dev;
+       input_dev->dev.parent = &serio->dev;
 
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
        input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
index 9157eb1..39d6026 100644 (file)
@@ -130,13 +130,13 @@ static int gunze_connect(struct serio *serio, struct serio_driver *drv)
        gunze->dev = input_dev;
        snprintf(gunze->phys, sizeof(serio->phys), "%s/input0", serio->phys);
 
-       input_dev->private = gunze;
        input_dev->name = "Gunze AHL-51S TouchScreen";
        input_dev->phys = gunze->phys;
        input_dev->id.bustype = BUS_RS232;
        input_dev->id.vendor = SERIO_GUNZE;
        input_dev->id.product = 0x0051;
        input_dev->id.version = 0x0100;
+       input_dev->dev.parent = &serio->dev;
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
        input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
        input_set_abs_params(input_dev, ABS_X, 24, 1000, 0, 0);
index c4116d4..09ed780 100644 (file)
@@ -147,7 +147,7 @@ enum flite_pwr {
 unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr)
 {
        unsigned char brightness = (pwr == FLITE_PWR_OFF) ? 0 : flite_brightness;
-       struct h3600_dev *ts = dev->private;
+       struct h3600_dev *ts = input_get_drvdata(dev);
 
        /* Must be in this order */
        ts->serio->write(ts->serio, 1);
@@ -260,7 +260,7 @@ static int h3600ts_event(struct input_dev *dev, unsigned int type,
                         unsigned int code, int value)
 {
 #if 0
-       struct h3600_dev *ts = dev->private;
+       struct h3600_dev *ts = input_get_drvdata(dev);
 
        switch (type) {
                case EV_LED: {
@@ -367,8 +367,9 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv)
        input_dev->id.vendor = SERIO_H3600;
        input_dev->id.product = 0x0666;  /* FIXME !!! We can ask the hardware */
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &serio->dev;
-       input_dev->private = ts;
+       input_dev->dev.parent = &serio->dev;
+
+       input_set_drvdata(input_dev, ts);
 
        input_dev->event = h3600ts_event;
 
index c3c2d73..4ec3b1f 100644 (file)
@@ -144,13 +144,13 @@ static int mtouch_connect(struct serio *serio, struct serio_driver *drv)
        mtouch->dev = input_dev;
        snprintf(mtouch->phys, sizeof(mtouch->phys), "%s/input0", serio->phys);
 
-       input_dev->private = mtouch;
        input_dev->name = "MicroTouch Serial TouchScreen";
        input_dev->phys = mtouch->phys;
        input_dev->id.bustype = BUS_RS232;
        input_dev->id.vendor = SERIO_MICROTOUCH;
        input_dev->id.product = 0;
        input_dev->id.version = 0x0100;
+       input_dev->dev.parent = &serio->dev;
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
        input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
        input_set_abs_params(mtouch->dev, ABS_X, MTOUCH_MIN_XC, MTOUCH_MAX_XC, 0, 0);
index bd27679..f2c0d3c 100644 (file)
@@ -105,14 +105,13 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv)
        pm->dev = input_dev;
        snprintf(pm->phys, sizeof(pm->phys), "%s/input0", serio->phys);
 
-       input_dev->private = pm;
        input_dev->name = "Penmount Serial TouchScreen";
        input_dev->phys = pm->phys;
        input_dev->id.bustype = BUS_RS232;
        input_dev->id.vendor = SERIO_PENMOUNT;
        input_dev->id.product = 0;
        input_dev->id.version = 0x0100;
-       input_dev->cdev.dev = &serio->dev;
+       input_dev->dev.parent = &serio->dev;
 
         input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
         input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
index 35ba46c..3def7bb 100644 (file)
@@ -118,13 +118,13 @@ static int tr_connect(struct serio *serio, struct serio_driver *drv)
        tr->dev = input_dev;
        snprintf(tr->phys, sizeof(tr->phys), "%s/input0", serio->phys);
 
-       input_dev->private = tr;
        input_dev->name = "Touchright Serial TouchScreen";
        input_dev->phys = tr->phys;
        input_dev->id.bustype = BUS_RS232;
        input_dev->id.vendor = SERIO_TOUCHRIGHT;
        input_dev->id.product = 0;
        input_dev->id.version = 0x0100;
+       input_dev->dev.parent = &serio->dev;
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
        input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
        input_set_abs_params(tr->dev, ABS_X, TR_MIN_XC, TR_MAX_XC, 0, 0);
index 4dc073d..ac4bdcf 100644 (file)
@@ -125,13 +125,13 @@ static int tw_connect(struct serio *serio, struct serio_driver *drv)
        tw->dev = input_dev;
        snprintf(tw->phys, sizeof(tw->phys), "%s/input0", serio->phys);
 
-       input_dev->private = tw;
        input_dev->name = "Touchwindow Serial TouchScreen";
        input_dev->phys = tw->phys;
        input_dev->id.bustype = BUS_RS232;
        input_dev->id.vendor = SERIO_TOUCHWIN;
        input_dev->id.product = 0;
        input_dev->id.version = 0x0100;
+       input_dev->dev.parent = &serio->dev;
        input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
        input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
        input_set_abs_params(tw->dev, ABS_X, TW_MIN_XC, TW_MAX_XC, 0, 0);
index e8606c4..6582816 100644 (file)
@@ -97,6 +97,8 @@ struct ucb1400 {
 };
 
 static int adcsync;
+static int ts_delay = 55; /* us */
+static int ts_delay_pressure;  /* us */
 
 static inline u16 ucb1400_reg_read(struct ucb1400 *ucb, u16 reg)
 {
@@ -159,6 +161,7 @@ static inline unsigned int ucb1400_ts_read_pressure(struct ucb1400 *ucb)
                        UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
                        UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
                        UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+       udelay(ts_delay_pressure);
        return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPY);
 }
 
@@ -180,7 +183,7 @@ static inline unsigned int ucb1400_ts_read_xpos(struct ucb1400 *ucb)
                        UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
                        UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
 
-       udelay(55);
+       udelay(ts_delay);
 
        return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPY);
 }
@@ -203,7 +206,7 @@ static inline unsigned int ucb1400_ts_read_ypos(struct ucb1400 *ucb)
                        UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
                        UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
 
-       udelay(55);
+       udelay(ts_delay);
 
        return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPX);
 }
@@ -369,7 +372,7 @@ static irqreturn_t ucb1400_hard_irq(int irqnr, void *devid)
 
 static int ucb1400_ts_open(struct input_dev *idev)
 {
-       struct ucb1400 *ucb = idev->private;
+       struct ucb1400 *ucb = input_get_drvdata(idev);
        int ret = 0;
 
        BUG_ON(ucb->ts_task);
@@ -385,7 +388,7 @@ static int ucb1400_ts_open(struct input_dev *idev)
 
 static void ucb1400_ts_close(struct input_dev *idev)
 {
-       struct ucb1400 *ucb = idev->private;
+       struct ucb1400 *ucb = input_get_drvdata(idev);
 
        if (ucb->ts_task)
                kthread_stop(ucb->ts_task);
@@ -507,8 +510,9 @@ static int ucb1400_ts_probe(struct device *dev)
        }
        printk(KERN_DEBUG "UCB1400: found IRQ %d\n", ucb->irq);
 
-       idev->private           = ucb;
-       idev->cdev.dev          = dev;
+       input_set_drvdata(idev, ucb);
+
+       idev->dev.parent        = dev;
        idev->name              = "UCB1400 touchscreen interface";
        idev->id.vendor         = ucb1400_reg_read(ucb, AC97_VENDOR_ID1);
        idev->id.product        = id;
@@ -571,7 +575,15 @@ static void __exit ucb1400_ts_exit(void)
        driver_unregister(&ucb1400_ts_driver);
 }
 
-module_param(adcsync, int, 0444);
+module_param(adcsync, bool, 0444);
+MODULE_PARM_DESC(adcsync, "Synchronize touch readings with ADCSYNC pin.");
+
+module_param(ts_delay, int, 0444);
+MODULE_PARM_DESC(ts_delay, "Delay between panel setup and position read. Default = 55us.");
+
+module_param(ts_delay_pressure, int, 0444);
+MODULE_PARM_DESC(ts_delay_pressure,
+                 "delay between panel setup and pressure read.  Default = 0us.");
 
 module_init(ucb1400_ts_init);
 module_exit(ucb1400_ts_exit);
index 0300dca..5e5b5c9 100644 (file)
@@ -111,13 +111,13 @@ struct tsdev {
        int minor;
        char name[8];
        wait_queue_head_t wait;
-       struct list_head list;
+       struct list_head client_list;
        struct input_handle handle;
        int x, y, pressure;
        struct ts_calibration cal;
 };
 
-struct tsdev_list {
+struct tsdev_client {
        struct fasync_struct *fasync;
        struct list_head node;
        struct tsdev *tsdev;
@@ -139,38 +139,49 @@ static struct tsdev *tsdev_table[TSDEV_MINORS/2];
 
 static int tsdev_fasync(int fd, struct file *file, int on)
 {
-       struct tsdev_list *list = file->private_data;
+       struct tsdev_client *client = file->private_data;
        int retval;
 
-       retval = fasync_helper(fd, file, on, &list->fasync);
+       retval = fasync_helper(fd, file, on, &client->fasync);
        return retval < 0 ? retval : 0;
 }
 
 static int tsdev_open(struct inode *inode, struct file *file)
 {
        int i = iminor(inode) - TSDEV_MINOR_BASE;
-       struct tsdev_list *list;
+       struct tsdev_client *client;
+       struct tsdev *tsdev;
+       int error;
 
        printk(KERN_WARNING "tsdev (compaq touchscreen emulation) is scheduled "
                "for removal.\nSee Documentation/feature-removal-schedule.txt "
                "for details.\n");
 
-       if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK])
+       if (i >= TSDEV_MINORS)
+               return -ENODEV;
+
+       tsdev = tsdev_table[i & TSDEV_MINOR_MASK];
+       if (!tsdev || !tsdev->exist)
                return -ENODEV;
 
-       if (!(list = kzalloc(sizeof(struct tsdev_list), GFP_KERNEL)))
+       client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL);
+       if (!client)
                return -ENOMEM;
 
-       list->raw = (i >= TSDEV_MINORS/2) ? 1 : 0;
+       client->tsdev = tsdev;
+       client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0;
+       list_add_tail(&client->node, &tsdev->client_list);
 
-       i &= TSDEV_MINOR_MASK;
-       list->tsdev = tsdev_table[i];
-       list_add_tail(&list->node, &tsdev_table[i]->list);
-       file->private_data = list;
+       if (!tsdev->open++ && tsdev->exist) {
+               error = input_open_device(&tsdev->handle);
+               if (error) {
+                       list_del(&client->node);
+                       kfree(client);
+                       return error;
+               }
+       }
 
-       if (!list->tsdev->open++)
-               if (list->tsdev->exist)
-                       input_open_device(&list->tsdev->handle);
+       file->private_data = client;
        return 0;
 }
 
@@ -182,45 +193,48 @@ static void tsdev_free(struct tsdev *tsdev)
 
 static int tsdev_release(struct inode *inode, struct file *file)
 {
-       struct tsdev_list *list = file->private_data;
+       struct tsdev_client *client = file->private_data;
+       struct tsdev *tsdev = client->tsdev;
 
        tsdev_fasync(-1, file, 0);
-       list_del(&list->node);
 
-       if (!--list->tsdev->open) {
-               if (list->tsdev->exist)
-                       input_close_device(&list->tsdev->handle);
+       list_del(&client->node);
+       kfree(client);
+
+       if (!--tsdev->open) {
+               if (tsdev->exist)
+                       input_close_device(&tsdev->handle);
                else
-                       tsdev_free(list->tsdev);
+                       tsdev_free(tsdev);
        }
-       kfree(list);
+
        return 0;
 }
 
 static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count,
-                         loff_t * ppos)
+                         loff_t *ppos)
 {
-       struct tsdev_list *list = file->private_data;
+       struct tsdev_client *client = file->private_data;
+       struct tsdev *tsdev = client->tsdev;
        int retval = 0;
 
-       if (list->head == list->tail && list->tsdev->exist && (file->f_flags & O_NONBLOCK))
+       if (client->head == client->tail && tsdev->exist && (file->f_flags & O_NONBLOCK))
                return -EAGAIN;
 
-       retval = wait_event_interruptible(list->tsdev->wait,
-                       list->head != list->tail || !list->tsdev->exist);
-
+       retval = wait_event_interruptible(tsdev->wait,
+                       client->head != client->tail || !tsdev->exist);
        if (retval)
                return retval;
 
-       if (!list->tsdev->exist)
+       if (!tsdev->exist)
                return -ENODEV;
 
-       while (list->head != list->tail &&
+       while (client->head != client->tail &&
               retval + sizeof (struct ts_event) <= count) {
-               if (copy_to_user (buffer + retval, list->event + list->tail,
+               if (copy_to_user (buffer + retval, client->event + client->tail,
                                  sizeof (struct ts_event)))
                        return -EFAULT;
-               list->tail = (list->tail + 1) & (TSDEV_BUFFER_SIZE - 1);
+               client->tail = (client->tail + 1) & (TSDEV_BUFFER_SIZE - 1);
                retval += sizeof (struct ts_event);
        }
 
@@ -228,32 +242,33 @@ static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count,
 }
 
 /* No kernel lock - fine */
-static unsigned int tsdev_poll(struct file *file, poll_table * wait)
+static unsigned int tsdev_poll(struct file *file, poll_table *wait)
 {
-       struct tsdev_list *list = file->private_data;
+       struct tsdev_client *client = file->private_data;
+       struct tsdev *tsdev = client->tsdev;
 
-       poll_wait(file, &list->tsdev->wait, wait);
-       return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
-               (list->tsdev->exist ? 0 : (POLLHUP | POLLERR));
+       poll_wait(file, &tsdev->wait, wait);
+       return ((client->head == client->tail) ? 0 : (POLLIN | POLLRDNORM)) |
+               (tsdev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
 static int tsdev_ioctl(struct inode *inode, struct file *file,
                       unsigned int cmd, unsigned long arg)
 {
-       struct tsdev_list *list = file->private_data;
-       struct tsdev *tsdev = list->tsdev;
+       struct tsdev_client *client = file->private_data;
+       struct tsdev *tsdev = client->tsdev;
        int retval = 0;
 
        switch (cmd) {
        case TS_GET_CAL:
-               if (copy_to_user ((void __user *)arg, &tsdev->cal,
-                                 sizeof (struct ts_calibration)))
+               if (copy_to_user((void __user *)arg, &tsdev->cal,
+                                sizeof (struct ts_calibration)))
                        retval = -EFAULT;
                break;
 
        case TS_SET_CAL:
-               if (copy_from_user (&tsdev->cal, (void __user *)arg,
-                                   sizeof (struct ts_calibration)))
+               if (copy_from_user(&tsdev->cal, (void __user *)arg,
+                                  sizeof (struct ts_calibration)))
                        retval = -EFAULT;
                break;
 
@@ -279,7 +294,7 @@ static void tsdev_event(struct input_handle *handle, unsigned int type,
                        unsigned int code, int value)
 {
        struct tsdev *tsdev = handle->private;
-       struct tsdev_list *list;
+       struct tsdev_client *client;
        struct timeval time;
 
        switch (type) {
@@ -343,18 +358,18 @@ static void tsdev_event(struct input_handle *handle, unsigned int type,
        if (type != EV_SYN || code != SYN_REPORT)
                return;
 
-       list_for_each_entry(list, &tsdev->list, node) {
+       list_for_each_entry(client, &tsdev->client_list, node) {
                int x, y, tmp;
 
                do_gettimeofday(&time);
-               list->event[list->head].millisecs = time.tv_usec / 100;
-               list->event[list->head].pressure = tsdev->pressure;
+               client->event[client->head].millisecs = time.tv_usec / 100;
+               client->event[client->head].pressure = tsdev->pressure;
 
                x = tsdev->x;
                y = tsdev->y;
 
                /* Calibration */
-               if (!list->raw) {
+               if (!client->raw) {
                        x = ((x * tsdev->cal.xscale) >> 8) + tsdev->cal.xtrans;
                        y = ((y * tsdev->cal.yscale) >> 8) + tsdev->cal.ytrans;
                        if (tsdev->cal.xyswap) {
@@ -362,33 +377,35 @@ static void tsdev_event(struct input_handle *handle, unsigned int type,
                        }
                }
 
-               list->event[list->head].x = x;
-               list->event[list->head].y = y;
-               list->head = (list->head + 1) & (TSDEV_BUFFER_SIZE - 1);
-               kill_fasync(&list->fasync, SIGIO, POLL_IN);
+               client->event[client->head].x = x;
+               client->event[client->head].y = y;
+               client->head = (client->head + 1) & (TSDEV_BUFFER_SIZE - 1);
+               kill_fasync(&client->fasync, SIGIO, POLL_IN);
        }
        wake_up_interruptible(&tsdev->wait);
 }
 
-static struct input_handle *tsdev_connect(struct input_handler *handler,
-                                         struct input_dev *dev,
-                                         const struct input_device_id *id)
+static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
+                        const struct input_device_id *id)
 {
        struct tsdev *tsdev;
        struct class_device *cdev;
+       dev_t devt;
        int minor, delta;
+       int error;
 
        for (minor = 0; minor < TSDEV_MINORS / 2 && tsdev_table[minor]; minor++);
        if (minor >= TSDEV_MINORS / 2) {
                printk(KERN_ERR
                       "tsdev: You have way too many touchscreens\n");
-               return NULL;
+               return -ENFILE;
        }
 
-       if (!(tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL)))
-               return NULL;
+       tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL);
+       if (!tsdev)
+               return -ENOMEM;
 
-       INIT_LIST_HEAD(&tsdev->list);
+       INIT_LIST_HEAD(&tsdev->client_list);
        init_waitqueue_head(&tsdev->wait);
 
        sprintf(tsdev->name, "ts%d", minor);
@@ -415,23 +432,45 @@ static struct input_handle *tsdev_connect(struct input_handler *handler,
 
        tsdev_table[minor] = tsdev;
 
-       cdev = class_device_create(&input_class, &dev->cdev,
-                       MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
-                       dev->cdev.dev, tsdev->name);
+       devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
+
+       cdev = class_device_create(&input_class, &dev->cdev, devt,
+                                  dev->cdev.dev, tsdev->name);
+       if (IS_ERR(cdev)) {
+               error = PTR_ERR(cdev);
+               goto err_free_tsdev;
+       }
 
        /* temporary symlink to keep userspace happy */
-       sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj,
-                         tsdev->name);
+       error = sysfs_create_link(&input_class.subsys.kobj,
+                                 &cdev->kobj, tsdev->name);
+       if (error)
+               goto err_cdev_destroy;
+
+       error = input_register_handle(&tsdev->handle);
+       if (error)
+               goto err_remove_link;
 
-       return &tsdev->handle;
+       return 0;
+
+ err_remove_link:
+       sysfs_remove_link(&input_class.subsys.kobj, tsdev->name);
+ err_cdev_destroy:
+       class_device_destroy(&input_class, devt);
+ err_free_tsdev:
+       tsdev_table[minor] = NULL;
+       kfree(tsdev);
+       return error;
 }
 
 static void tsdev_disconnect(struct input_handle *handle)
 {
        struct tsdev *tsdev = handle->private;
-       struct tsdev_list *list;
+       struct tsdev_client *client;
+
+       input_unregister_handle(handle);
 
-       sysfs_remove_link(&input_class.subsys.kset.kobj, tsdev->name);
+       sysfs_remove_link(&input_class.subsys.kobj, tsdev->name);
        class_device_destroy(&input_class,
                        MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
        tsdev->exist = 0;
@@ -439,8 +478,8 @@ static void tsdev_disconnect(struct input_handle *handle)
        if (tsdev->open) {
                input_close_device(handle);
                wake_up_interruptible(&tsdev->wait);
-               list_for_each_entry(list, &tsdev->list, node)
-                       kill_fasync(&list->fasync, SIGIO, POLL_HUP);
+               list_for_each_entry(client, &tsdev->client_list, node)
+                       kill_fasync(&client->fasync, SIGIO, POLL_HUP);
        } else
                tsdev_free(tsdev);
 }
index 38f648f..02c6fba 100644 (file)
@@ -19,7 +19,6 @@
 #include "isac.h"
 #include "hscx.h"
 #include "isdnl1.h"
-#include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/ppp_defs.h>
 #include <asm/io.h>
index f7e83a8..4c7deda 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
-#include <linux/pci.h>
 #include <linux/smp_lock.h>
 
 #include "hysdn_defs.h"
index 35233de..3d0354e 100644 (file)
@@ -459,7 +459,8 @@ therm_of_probe( struct of_device *dev, const struct of_device_id *match )
 static int
 therm_of_remove( struct of_device *dev )
 {
-       return i2c_del_driver( &g4fan_driver );
+       i2c_del_driver( &g4fan_driver );
+       return 0;
 }
 
 static struct of_device_id therm_of_match[] = {{
index 76d2177..741a93a 100644 (file)
@@ -82,6 +82,7 @@ static unsigned char cuda_rbuf[16];
 static unsigned char *reply_ptr;
 static int reading_reply;
 static int data_index;
+static int cuda_irq;
 #ifdef CONFIG_PPC
 static struct device_node *vias;
 #endif
@@ -160,10 +161,8 @@ int __init find_via_cuda(void)
     /* Clear and enable interrupts, but only on PPC. On 68K it's done  */
     /* for us by the main VIA driver in arch/m68k/mac/via.c        */
 
-#ifndef CONFIG_MAC
     out_8(&via[IFR], 0x7f);    /* clear interrupts by writing 1s */
     out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */
-#endif
 
     /* enable autopoll */
     cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1);
@@ -181,24 +180,22 @@ int __init find_via_cuda(void)
 
 static int __init via_cuda_start(void)
 {
-    unsigned int irq;
-
     if (via == NULL)
        return -ENODEV;
 
 #ifdef CONFIG_MAC
-    irq = IRQ_MAC_ADB;
+    cuda_irq = IRQ_MAC_ADB;
 #else /* CONFIG_MAC */
-    irq = irq_of_parse_and_map(vias, 0);
-    if (irq == NO_IRQ) {
+    cuda_irq = irq_of_parse_and_map(vias, 0);
+    if (cuda_irq == NO_IRQ) {
        printk(KERN_ERR "via-cuda: can't map interrupts for %s\n",
               vias->full_name);
        return -ENODEV;
     }
-#endif /* CONFIG_MAP */
+#endif /* CONFIG_MAC */
 
-    if (request_irq(irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) {
-       printk(KERN_ERR "via-cuda: can't request irq %d\n", irq);
+    if (request_irq(cuda_irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) {
+       printk(KERN_ERR "via-cuda: can't request irq %d\n", cuda_irq);
        return -EAGAIN;
     }
 
@@ -238,6 +235,7 @@ cuda_init(void)
        printk(KERN_ERR "cuda_init_via() failed\n");
        return -ENODEV;
     }
+    out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */
 
     return via_cuda_start();
 #endif
@@ -263,15 +261,17 @@ cuda_init_via(void)
     out_8(&via[B], in_8(&via[B]) | TACK | TIP);                        /* negate them */
     out_8(&via[ACR] ,(in_8(&via[ACR]) & ~SR_CTRL) | SR_EXT);   /* SR data in */
     (void)in_8(&via[SR]);                                              /* clear any left-over data */
-#ifndef CONFIG_MAC
+#ifdef CONFIG_PPC
     out_8(&via[IER], 0x7f);                                    /* disable interrupts from VIA */
     (void)in_8(&via[IER]);
+#else
+    out_8(&via[IER], SR_INT);                                  /* disable SR interrupt from VIA */
 #endif
 
     /* delay 4ms and then clear any pending interrupt */
     mdelay(4);
     (void)in_8(&via[SR]);
-    out_8(&via[IFR], in_8(&via[IFR]) & 0x7f);
+    out_8(&via[IFR], SR_INT);
 
     /* sync with the CUDA - assert TACK without TIP */
     out_8(&via[B], in_8(&via[B]) & ~TACK);
@@ -282,7 +282,7 @@ cuda_init_via(void)
     /* wait for the interrupt and then clear it */
     WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (2)");
     (void)in_8(&via[SR]);
-    out_8(&via[IFR], in_8(&via[IFR]) & 0x7f);
+    out_8(&via[IFR], SR_INT);
 
     /* finish the sync by negating TACK */
     out_8(&via[B], in_8(&via[B]) | TACK);
@@ -291,7 +291,7 @@ cuda_init_via(void)
     WAIT_FOR(in_8(&via[B]) & TREQ, "CUDA response to sync (3)");
     WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (4)");
     (void)in_8(&via[SR]);
-    out_8(&via[IFR], in_8(&via[IFR]) & 0x7f);
+    out_8(&via[IFR], SR_INT);
     out_8(&via[B], in_8(&via[B]) | TIP);       /* should be unnecessary */
 
     return 0;
@@ -428,16 +428,12 @@ cuda_start(void)
 void
 cuda_poll(void)
 {
-    unsigned long flags;
-
     /* cuda_interrupt only takes a normal lock, we disable
      * interrupts here to avoid re-entering and thus deadlocking.
-     * An option would be to disable only the IRQ source with
-     * disable_irq(), would that work on m68k ? --BenH
      */
-    local_irq_save(flags);
+    disable_irq(cuda_irq);
     cuda_interrupt(0, NULL);
-    local_irq_restore(flags);
+    enable_irq(cuda_irq);
 }
 
 static irqreturn_t
@@ -448,15 +444,25 @@ cuda_interrupt(int irq, void *arg)
     unsigned char ibuf[16];
     int ibuf_len = 0;
     int complete = 0;
-    unsigned char virq;
     
     spin_lock(&cuda_lock);
 
-    virq = in_8(&via[IFR]) & 0x7f;
-    out_8(&via[IFR], virq);   
-    if ((virq & SR_INT) == 0) {
-        spin_unlock(&cuda_lock);
-       return IRQ_NONE;
+    /* On powermacs, this handler is registered for the VIA IRQ. But it uses
+     * just the shift register IRQ -- other VIA interrupt sources are disabled.
+     * On m68k macs, the VIA IRQ sources are dispatched individually. Unless
+     * we are polling, the shift register IRQ flag has already been cleared.
+     */
+
+#ifdef CONFIG_MAC
+    if (!arg)
+#endif
+    {
+        if ((in_8(&via[IFR]) & SR_INT) == 0) {
+            spin_unlock(&cuda_lock);
+            return IRQ_NONE;
+        } else {
+            out_8(&via[IFR], SR_INT);
+        }
     }
     
     status = (~in_8(&via[B]) & (TIP|TREQ)) | (in_8(&via[ACR]) & SR_OUT);
index 1b3bad6..01b8eca 100644 (file)
  * 1999-08-02 (jmt) - Initial rewrite for Unified ADB.
  * 2000-03-29 Tony Mantler <tonym@mac.linux-m68k.org>
  *                             - Big overhaul, should actually work now.
+ * 2006-12-31 Finn Thain <fthain@telegraphics.com.au> - Another overhaul.
+ *
+ * Suggested reading:
+ *   Inside Macintosh, ch. 5 ADB Manager
+ *   Guide to the Macinstosh Family Hardware, ch. 8 Apple Desktop Bus
+ *   Rockwell R6522 VIA datasheet
+ *
+ * Apple's "ADB Analyzer" bus sniffer is invaluable:
+ *   ftp://ftp.apple.com/developer/Tool_Chest/Devices_-_Hardware/Apple_Desktop_Bus/
  */
  
 #include <stdarg.h>
@@ -26,7 +35,6 @@
 #include <asm/macints.h>
 #include <asm/machw.h>
 #include <asm/mac_via.h>
-#include <asm/io.h>
 #include <asm/system.h>
 
 static volatile unsigned char *via;
@@ -51,9 +59,7 @@ static volatile unsigned char *via;
 #define ANH            (15*RS)         /* A-side data, no handshake */
 
 /* Bits in B data register: all active low */
-#define TREQ           0x08            /* Transfer request (input) */
-#define TACK           0x10            /* Transfer acknowledge (output) */
-#define TIP            0x20            /* Transfer in progress (output) */
+#define CTLR_IRQ       0x08            /* Controller rcv status (input) */
 #define ST_MASK                0x30            /* mask for selecting ADB state bits */
 
 /* Bits in ACR */
@@ -65,8 +71,6 @@ static volatile unsigned char *via;
 #define IER_SET                0x80            /* set bits in IER */
 #define IER_CLR                0               /* clear bits in IER */
 #define SR_INT         0x04            /* Shift register full/empty */
-#define SR_DATA                0x08            /* Shift register data */
-#define SR_CLOCK       0x10            /* Shift register clock */
 
 /* ADB transaction states according to GMHW */
 #define ST_CMD         0x00            /* ADB state: command byte */
@@ -77,7 +81,6 @@ static volatile unsigned char *via;
 static int  macii_init_via(void);
 static void macii_start(void);
 static irqreturn_t macii_interrupt(int irq, void *arg);
-static void macii_retransmit(int);
 static void macii_queue_poll(void);
 
 static int macii_probe(void);
@@ -103,29 +106,37 @@ static enum macii_state {
        sending,
        reading,
        read_done,
-       awaiting_reply
 } macii_state;
 
-static int need_poll;
-static int command_byte;
-static int last_reply;
-static int last_active;
-
-static struct adb_request *current_req;
-static struct adb_request *last_req;
-static struct adb_request *retry_req;
-static unsigned char reply_buf[16];
-static unsigned char *reply_ptr;
-static int reply_len;
-static int reading_reply;
-static int data_index;
-static int first_byte;
-static int prefix_len;
-static int status = ST_IDLE|TREQ;
-static int last_status;
-static int driver_running;
-
-/* debug level 10 required for ADB logging (should be && debug_adb, ideally) */
+static struct adb_request *current_req; /* first request struct in the queue */
+static struct adb_request *last_req;     /* last request struct in the queue */
+static unsigned char reply_buf[16];        /* storage for autopolled replies */
+static unsigned char *reply_ptr;      /* next byte in req->data or reply_buf */
+static int reading_reply;        /* store reply in reply_buf else req->reply */
+static int data_index;      /* index of the next byte to send from req->data */
+static int reply_len; /* number of bytes received in reply_buf or req->reply */
+static int status;          /* VIA's ADB status bits captured upon interrupt */
+static int last_status;              /* status bits as at previous interrupt */
+static int srq_asserted;     /* have to poll for the device that asserted it */
+static int command_byte;         /* the most recent command byte transmitted */
+static int autopoll_devs;      /* bits set are device addresses to be polled */
+
+/* Sanity check for request queue. Doesn't check for cycles. */
+static int request_is_queued(struct adb_request *req) {
+       struct adb_request *cur;
+       unsigned long flags;
+       local_irq_save(flags);
+       cur = current_req;
+       while (cur) {
+               if (cur == req) {
+                       local_irq_restore(flags);
+                       return 1;
+               }
+               cur = cur->next;
+       }
+       local_irq_restore(flags);
+       return 0;
+}
 
 /* Check for MacII style ADB */
 static int macii_probe(void)
@@ -147,15 +158,16 @@ int macii_init(void)
        local_irq_save(flags);
        
        err = macii_init_via();
-       if (err) return err;
+       if (err) goto out;
 
        err = request_irq(IRQ_MAC_ADB, macii_interrupt, IRQ_FLG_LOCK, "ADB",
                          macii_interrupt);
-       if (err) return err;
+       if (err) goto out;
 
        macii_state = idle;
+out:
        local_irq_restore(flags);
-       return 0;
+       return err;
 }
 
 /* initialize the hardware */  
@@ -163,12 +175,12 @@ static int macii_init_via(void)
 {
        unsigned char x;
 
-       /* Set the lines up. We want TREQ as input TACK|TIP as output */
-       via[DIRB] = (via[DIRB] | TACK | TIP) & ~TREQ;
+       /* We want CTLR_IRQ as input and ST_EVEN | ST_ODD as output lines. */
+       via[DIRB] = (via[DIRB] | ST_EVEN | ST_ODD) & ~CTLR_IRQ;
 
        /* Set up state: idle */
        via[B] |= ST_IDLE;
-       last_status = via[B] & (ST_MASK|TREQ);
+       last_status = via[B] & (ST_MASK|CTLR_IRQ);
 
        /* Shift register on input */
        via[ACR] = (via[ACR] & ~SR_CTRL) | SR_EXT;
@@ -179,81 +191,72 @@ static int macii_init_via(void)
        return 0;
 }
 
-/* Send an ADB poll (Talk Register 0 command, tagged on the front of the request queue) */
+/* Send an ADB poll (Talk Register 0 command prepended to the request queue) */
 static void macii_queue_poll(void)
 {
-       static int device = 0;
-       static int in_poll=0;
+       /* No point polling the active device as it will never assert SRQ, so
+        * poll the next device in the autopoll list. This could leave us
+        * stuck in a polling loop if an unprobed device is asserting SRQ.
+        * In theory, that could only happen if a device was plugged in after
+        * probing started. Unplugging it again will break the cycle.
+        * (Simply polling the next higher device often ends up polling almost
+        * every device (after wrapping around), which takes too long.)
+        */
+       int device_mask;
+       int next_device;
        static struct adb_request req;
-       unsigned long flags;
-       
-       if (in_poll) printk("macii_queue_poll: double poll!\n");
-
-       in_poll++;
-       if (++device > 15) device = 1;
-
-       adb_request(&req, NULL, ADBREQ_REPLY|ADBREQ_NOSEND, 1,
-                   ADB_READREG(device, 0));
-
-       local_irq_save(flags);
-
-       req.next = current_req;
-       current_req = &req;
 
-       local_irq_restore(flags);
-       macii_start();
-       in_poll--;
-}
+       if (!autopoll_devs) return;
 
-/* Send an ADB retransmit (Talk, appended to the request queue) */
-static void macii_retransmit(int device)
-{
-       static int in_retransmit = 0;
-       static struct adb_request rt;
-       unsigned long flags;
-       
-       if (in_retransmit) printk("macii_retransmit: double retransmit!\n");
+       device_mask = (1 << (((command_byte & 0xF0) >> 4) + 1)) - 1;
+       if (autopoll_devs & ~device_mask)
+               next_device = ffs(autopoll_devs & ~device_mask) - 1;
+       else
+               next_device = ffs(autopoll_devs) - 1;
 
-       in_retransmit++;
+       BUG_ON(request_is_queued(&req));
 
-       adb_request(&rt, NULL, ADBREQ_REPLY|ADBREQ_NOSEND, 1,
-                   ADB_READREG(device, 0));
+       adb_request(&req, NULL, ADBREQ_NOSEND, 1,
+                   ADB_READREG(next_device, 0));
 
-       local_irq_save(flags);
+       req.sent = 0;
+       req.complete = 0;
+       req.reply_len = 0;
+       req.next = current_req;
 
        if (current_req != NULL) {
-               last_req->next = &rt;
-               last_req = &rt;
+               current_req = &req;
        } else {
-               current_req = &rt;
-               last_req = &rt;
+               current_req = &req;
+               last_req = &req;
        }
-
-       if (macii_state == idle) macii_start();
-
-       local_irq_restore(flags);
-       in_retransmit--;
 }
 
 /* Send an ADB request; if sync, poll out the reply 'till it's done */
 static int macii_send_request(struct adb_request *req, int sync)
 {
-       int i;
+       int err;
+       unsigned long flags;
 
-       i = macii_write(req);
-       if (i) return i;
+       BUG_ON(request_is_queued(req));
 
-       if (sync) {
-               while (!req->complete) macii_poll();
+       local_irq_save(flags);
+       err = macii_write(req);
+       local_irq_restore(flags);
+
+       if (!err && sync) {
+               while (!req->complete) {
+                       macii_poll();
+               }
+               BUG_ON(request_is_queued(req));
        }
-       return 0;
+
+       return err;
 }
 
-/* Send an ADB request */
+/* Send an ADB request (append to request queue) */
 static int macii_write(struct adb_request *req)
 {
-       unsigned long flags;
-
        if (req->nbytes < 2 || req->data[0] != ADB_PACKET || req->nbytes > 15) {
                req->complete = 1;
                return -EINVAL;
@@ -264,8 +267,6 @@ static int macii_write(struct adb_request *req)
        req->complete = 0;
        req->reply_len = 0;
 
-       local_irq_save(flags);
-
        if (current_req != NULL) {
                last_req->next = req;
                last_req = req;
@@ -274,28 +275,52 @@ static int macii_write(struct adb_request *req)
                last_req = req;
                if (macii_state == idle) macii_start();
        }
-
-       local_irq_restore(flags);
        return 0;
 }
 
 /* Start auto-polling */
 static int macii_autopoll(int devs)
 {
-       /* Just ping a random default address */
-       if (!(current_req || retry_req))
-               macii_retransmit( (last_active < 16 && last_active > 0) ? last_active : 3);
-       return 0;
+       static struct adb_request req;
+       unsigned long flags;
+       int err = 0;
+
+       /* bit 1 == device 1, and so on. */
+       autopoll_devs = devs & 0xFFFE;
+
+       if (!autopoll_devs) return 0;
+
+       local_irq_save(flags);
+
+       if (current_req == NULL) {
+               /* Send a Talk Reg 0. The controller will repeatedly transmit
+                * this as long as it is idle.
+                */
+               adb_request(&req, NULL, ADBREQ_NOSEND, 1,
+                           ADB_READREG(ffs(autopoll_devs) - 1, 0));
+               err = macii_write(&req);
+       }
+
+       local_irq_restore(flags);
+       return err;
+}
+
+static inline int need_autopoll(void) {
+       /* Was the last command Talk Reg 0
+        * and is the target on the autopoll list?
+        */
+       if ((command_byte & 0x0F) == 0x0C &&
+           ((1 << ((command_byte & 0xF0) >> 4)) & autopoll_devs))
+               return 0;
+       return 1;
 }
 
 /* Prod the chip without interrupts */
 static void macii_poll(void)
 {
-       unsigned long flags;
-
-       local_irq_save(flags);
-       if (via[IFR] & SR_INT) macii_interrupt(0, NULL);
-       local_irq_restore(flags);
+       disable_irq(IRQ_MAC_ADB);
+       macii_interrupt(0, NULL);
+       enable_irq(IRQ_MAC_ADB);
 }
 
 /* Reset the bus */
@@ -303,73 +328,34 @@ static int macii_reset_bus(void)
 {
        static struct adb_request req;
        
+       if (request_is_queued(&req))
+               return 0;
+
        /* Command = 0, Address = ignored */
        adb_request(&req, NULL, 0, 1, ADB_BUSRESET);
 
+       /* Don't want any more requests during the Global Reset low time. */
+       udelay(3000);
+
        return 0;
 }
 
 /* Start sending ADB packet */
 static void macii_start(void)
 {
-       unsigned long flags;
        struct adb_request *req;
 
        req = current_req;
-       if (!req) return;
-       
-       /* assert macii_state == idle */
-       if (macii_state != idle) {
-               printk("macii_start: called while driver busy (%p %x %x)!\n",
-                       req, macii_state, (uint) via1[B] & (ST_MASK|TREQ));
-               return;
-       }
 
-       local_irq_save(flags);
-       
-       /* 
-        * IRQ signaled ?? (means ADB controller wants to send, or might 
-        * be end of packet if we were reading)
-        */
-#if 0 /* FIXME: This is broke broke broke, for some reason */
-       if ((via[B] & TREQ) == 0) {
-               printk("macii_start: weird poll stuff. huh?\n");
-               /*
-                *      FIXME - we need to restart this on a timer
-                *      or a collision at boot hangs us.
-                *      Never set macii_state to idle here, or macii_start 
-                *      won't be called again from send_request!
-                *      (need to re-check other cases ...)
-                */
-               /*
-                * if the interrupt handler set the need_poll
-                * flag, it's hopefully a SRQ poll or re-Talk
-                * so we try to send here anyway
-                */
-               if (!need_poll) {
-                       if (console_loglevel == 10)
-                               printk("macii_start: device busy - retry %p state %d status %x!\n", 
-                                       req, macii_state,
-                                       (uint) via[B] & (ST_MASK|TREQ));
-                       retry_req = req;
-                       /* set ADB status here ? */
-                       local_irq_restore(flags);
-                       return;
-               } else {
-                       need_poll = 0;
-               }
-       }
-#endif
-       /*
-        * Another retry pending? (sanity check)
+       BUG_ON(req == NULL);
+
+       BUG_ON(macii_state != idle);
+
+       /* Now send it. Be careful though, that first byte of the request
+        * is actually ADB_PACKET; the real data begins at index 1!
+        * And req->nbytes is the number of bytes of real data plus one.
         */
-       if (retry_req) {
-               retry_req = NULL;
-       }
 
-       /* Now send it. Be careful though, that first byte of the request */
-       /* is actually ADB_PACKET; the real data begins at index 1!       */
-       
        /* store command byte */
        command_byte = req->data[1];
        /* Output mode */
@@ -381,115 +367,97 @@ static void macii_start(void)
 
        macii_state = sending;
        data_index = 2;
-
-       local_irq_restore(flags);
 }
 
 /*
- * The notorious ADB interrupt handler - does all of the protocol handling, 
- * except for starting new send operations. Relies heavily on the ADB 
- * controller sending and receiving data, thereby generating SR interrupts
- * for us. This means there has to be always activity on the ADB bus, otherwise
- * the whole process dies and has to be re-kicked by sending TALK requests ...
- * CUDA-based Macs seem to solve this with the autopoll option, for MacII-type
- * ADB the problem isn't solved yet (retransmit of the latest active TALK seems
- * a good choice; either on timeout or on a timer interrupt).
+ * The notorious ADB interrupt handler - does all of the protocol handling.
+ * Relies on the ADB controller sending and receiving data, thereby
+ * generating shift register interrupts (SR_INT) for us. This means there has
+ * to be activity on the ADB bus. The chip will poll to achieve this.
  *
  * The basic ADB state machine was left unchanged from the original MacII code
  * by Alan Cox, which was based on the CUDA driver for PowerMac. 
- * The syntax of the ADB status lines seems to be totally different on MacII, 
- * though. MacII uses the states Command -> Even -> Odd -> Even ->...-> Idle for
- * sending, and Idle -> Even -> Odd -> Even ->...-> Idle for receiving. Start 
- * and end of a receive packet are signaled by asserting /IRQ on the interrupt
- * line. Timeouts are signaled by a sequence of 4 0xFF, with /IRQ asserted on 
- * every other byte. SRQ is probably signaled by 3 or more 0xFF tacked on the 
- * end of a packet. (Thanks to Guido Koerber for eavesdropping on the ADB 
- * protocol with a logic analyzer!!)
- *
- * Note: As of 21/10/97, the MacII ADB part works including timeout detection
- * and retransmit (Talk to the last active device).
+ * The syntax of the ADB status lines is totally different on MacII,
+ * though. MacII uses the states Command -> Even -> Odd -> Even ->...-> Idle
+ * for sending and Idle -> Even -> Odd -> Even ->...-> Idle for receiving.
+ * Start and end of a receive packet are signalled by asserting /IRQ on the
+ * interrupt line (/IRQ means the CTLR_IRQ bit in port B; not to be confused
+ * with the VIA shift register interrupt. /IRQ never actually interrupts the
+ * processor, it's just an ordinary input.)
  */
 static irqreturn_t macii_interrupt(int irq, void *arg)
 {
-       int x, adbdir;
-       unsigned long flags;
+       int x;
+       static int entered;
        struct adb_request *req;
 
-       last_status = status;
-
-       /* prevent races due to SCSI enabling ints */
-       local_irq_save(flags);
-
-       if (driver_running) {
-               local_irq_restore(flags);
-               return IRQ_NONE;
+       if (!arg) {
+               /* Clear the SR IRQ flag when polling. */
+               if (via[IFR] & SR_INT)
+                       via[IFR] = SR_INT;
+               else
+                       return IRQ_NONE;
        }
 
-       driver_running = 1;
-       
-       status = via[B] & (ST_MASK|TREQ);
-       adbdir = via[ACR] & SR_OUT;
+       BUG_ON(entered++);
+
+       last_status = status;
+       status = via[B] & (ST_MASK|CTLR_IRQ);
 
        switch (macii_state) {
                case idle:
+                       if (reading_reply) {
+                               reply_ptr = current_req->reply;
+                       } else {
+                               BUG_ON(current_req != NULL);
+                               reply_ptr = reply_buf;
+                       }
+
                        x = via[SR];
-                       first_byte = x;
-                       /* set ADB state = even for first data byte */
-                       via[B] = (via[B] & ~ST_MASK) | ST_EVEN;
 
-                       reply_buf[0] = first_byte; /* was command_byte?? */
-                       reply_ptr = reply_buf + 1;
-                       reply_len = 1;
-                       prefix_len = 1;
-                       reading_reply = 0;
-                       
-                       macii_state = reading;
-                       break;
+                       if ((status & CTLR_IRQ) && (x == 0xFF)) {
+                               /* Bus timeout without SRQ sequence:
+                                *     data is "FF" while CTLR_IRQ is "H"
+                                */
+                               reply_len = 0;
+                               srq_asserted = 0;
+                               macii_state = read_done;
+                       } else {
+                               macii_state = reading;
+                               *reply_ptr = x;
+                               reply_len = 1;
+                       }
 
-               case awaiting_reply:
-                       /* handshake etc. for II ?? */
-                       x = via[SR];
-                       first_byte = x;
                        /* set ADB state = even for first data byte */
                        via[B] = (via[B] & ~ST_MASK) | ST_EVEN;
-
-                       current_req->reply[0] = first_byte;
-                       reply_ptr = current_req->reply + 1;
-                       reply_len = 1;
-                       prefix_len = 1;
-                       reading_reply = 1;
-
-                       macii_state = reading;                  
                        break;
 
                case sending:
                        req = current_req;
                        if (data_index >= req->nbytes) {
-                               /* print an error message if a listen command has no data */
-                               if (((command_byte & 0x0C) == 0x08)
-                                /* && (console_loglevel == 10) */
-                                   && (data_index == 2))
-                                       printk("MacII ADB: listen command with no data: %x!\n", 
-                                               command_byte);
-                               /* reset to shift in */
-                               via[ACR] &= ~SR_OUT;
-                               x = via[SR];
-                               /* set ADB state idle - might get SRQ */
-                               via[B] = (via[B] & ~ST_MASK) | ST_IDLE;
-
                                req->sent = 1;
+                               macii_state = idle;
 
                                if (req->reply_expected) {
-                                       macii_state = awaiting_reply;
+                                       reading_reply = 1;
                                } else {
                                        req->complete = 1;
                                        current_req = req->next;
                                        if (req->done) (*req->done)(req);
-                                       macii_state = idle;
-                                       if (current_req || retry_req)
+
+                                       if (current_req)
                                                macii_start();
                                        else
-                                               macii_retransmit((command_byte & 0xF0) >> 4);
+                                               if (need_autopoll())
+                                                       macii_autopoll(autopoll_devs);
+                               }
+
+                               if (macii_state == idle) {
+                                       /* reset to shift in */
+                                       via[ACR] &= ~SR_OUT;
+                                       x = via[SR];
+                                       /* set ADB state idle - might get SRQ */
+                                       via[B] = (via[B] & ~ST_MASK) | ST_IDLE;
                                }
                        } else {
                                via[SR] = req->data[data_index++];
@@ -505,147 +473,79 @@ static irqreturn_t macii_interrupt(int irq, void *arg)
                        break;
 
                case reading:
+                       x = via[SR];
+                       BUG_ON((status & ST_MASK) == ST_CMD ||
+                              (status & ST_MASK) == ST_IDLE);
+
+                       /* Bus timeout with SRQ sequence:
+                        *     data is "XX FF"      while CTLR_IRQ is "L L"
+                        * End of packet without SRQ sequence:
+                        *     data is "XX...YY 00" while CTLR_IRQ is "L...H L"
+                        * End of packet SRQ sequence:
+                        *     data is "XX...YY 00" while CTLR_IRQ is "L...L L"
+                        * (where XX is the first response byte and
+                        * YY is the last byte of valid response data.)
+                        */
 
-                       /* timeout / SRQ handling for II hw */
-                       if( (first_byte == 0xFF && (reply_len-prefix_len)==2 
-                            && memcmp(reply_ptr-2,"\xFF\xFF",2)==0) || 
-                           ((reply_len-prefix_len)==3 
-                            && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0))
-                       {
-                               /*
-                                * possible timeout (in fact, most probably a 
-                                * timeout, since SRQ can't be signaled without
-                                * transfer on the bus).
-                                * The last three bytes seen were FF, together 
-                                * with the starting byte (in case we started
-                                * on 'idle' or 'awaiting_reply') this probably
-                                * makes four. So this is mostl likely #5!
-                                * The timeout signal is a pattern 1 0 1 0 0..
-                                * on /INT, meaning we missed it :-(
-                                */
-                               x = via[SR];
-                               if (x != 0xFF) printk("MacII ADB: mistaken timeout/SRQ!\n");
-
-                               if ((status & TREQ) == (last_status & TREQ)) {
-                                       /* Not a timeout. Unsolicited SRQ? weird. */
-                                       /* Terminate the SRQ packet and poll */
-                                       need_poll = 1;
+                       srq_asserted = 0;
+                       if (!(status & CTLR_IRQ)) {
+                               if (x == 0xFF) {
+                                       if (!(last_status & CTLR_IRQ)) {
+                                               macii_state = read_done;
+                                               reply_len = 0;
+                                               srq_asserted = 1;
+                                       }
+                               } else if (x == 0x00) {
+                                       macii_state = read_done;
+                                       if (!(last_status & CTLR_IRQ))
+                                               srq_asserted = 1;
                                }
-                               /* There's no packet to get, so reply is blank */
-                               via[B] ^= ST_MASK;
-                               reply_ptr -= (reply_len-prefix_len);
-                               reply_len = prefix_len;
-                               macii_state = read_done;
-                               break;
-                       } /* end timeout / SRQ handling for II hw. */
-
-                       if((reply_len-prefix_len)>3
-                               && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0)
-                       {
-                               /* SRQ tacked on data packet */
-                               /* Terminate the packet (SRQ never ends) */
-                               x = via[SR];
-                               macii_state = read_done;
-                               reply_len -= 3;
-                               reply_ptr -= 3;
-                               need_poll = 1;
-                               /* need to continue; next byte not seen else */
-                       } else {
-                               /* Sanity check */
-                               if (reply_len > 15) reply_len = 0;
-                               /* read byte */
-                               x = via[SR];
-                               *reply_ptr = x;
+                       }
+
+                       if (macii_state == reading) {
+                               BUG_ON(reply_len > 15);
                                reply_ptr++;
+                               *reply_ptr = x;
                                reply_len++;
                        }
-                       /* The usual handshake ... */
-
-                       /*
-                        * NetBSD hints that the next to last byte 
-                        * is sent with IRQ !! 
-                        * Guido found out it's the last one (0x0),
-                        * but IRQ should be asserted already.
-                        * Problem with timeout detection: First
-                        * transition to /IRQ might be second 
-                        * byte of timeout packet! 
-                        * Timeouts are signaled by 4x FF.
-                        */
-                       if (((status & TREQ) == 0) && (x == 0x00)) { /* != 0xFF */
-                               /* invert state bits, toggle ODD/EVEN */
-                               via[B] ^= ST_MASK;
 
-                               /* adjust packet length */
-                               reply_len--;
-                               reply_ptr--;
-                               macii_state = read_done;
-                       } else {
-                               /* not caught: ST_CMD */
-                               /* required for re-entry 'reading'! */
-                               if ((status & ST_MASK) == ST_IDLE) {
-                                       /* (in)sanity check - set even */
-                                       via[B] = (via[B] & ~ST_MASK) | ST_EVEN;
-                               } else {
-                                       /* invert state bits */
-                                       via[B] ^= ST_MASK;
-                               }
-                       }
+                       /* invert state bits, toggle ODD/EVEN */
+                       via[B] ^= ST_MASK;
                        break;
 
                case read_done:
                        x = via[SR];
+
                        if (reading_reply) {
+                               reading_reply = 0;
                                req = current_req;
-                               req->reply_len = reply_ptr - req->reply;
+                               req->reply_len = reply_len;
                                req->complete = 1;
                                current_req = req->next;
                                if (req->done) (*req->done)(req);
-                       } else {
-                               adb_input(reply_buf, reply_ptr - reply_buf, 0);
-                       }
+                       } else if (reply_len && autopoll_devs)
+                               adb_input(reply_buf, reply_len, 0);
 
-                       /*
-                        * remember this device ID; it's the latest we got a 
-                        * reply from!
-                        */
-                       last_reply = command_byte;
-                       last_active = (command_byte & 0xF0) >> 4;
+                       macii_state = idle;
 
                        /* SRQ seen before, initiate poll now */
-                       if (need_poll) {
-                               macii_state = idle;
+                       if (srq_asserted)
                                macii_queue_poll();
-                               need_poll = 0;
-                               break;
-                       }
-                       
-                       /* set ADB state to idle */
-                       via[B] = (via[B] & ~ST_MASK) | ST_IDLE;
-                       
-                       /* /IRQ seen, so the ADB controller has data for us */
-                       if ((via[B] & TREQ) != 0) {
-                               macii_state = reading;
 
-                               reply_buf[0] = command_byte;
-                               reply_ptr = reply_buf + 1;
-                               reply_len = 1;
-                               prefix_len = 1;
-                               reading_reply = 0;
-                       } else {
-                               /* no IRQ, send next packet or wait */
-                               macii_state = idle;
-                               if (current_req)
-                                       macii_start();
-                               else
-                                       macii_retransmit(last_active);
-                       }
+                       if (current_req)
+                               macii_start();
+                       else
+                               if (need_autopoll())
+                                       macii_autopoll(autopoll_devs);
+
+                       if (macii_state == idle)
+                               via[B] = (via[B] & ~ST_MASK) | ST_IDLE;
                        break;
 
                default:
                break;
        }
-       /* reset mutex and interrupts */
-       driver_running = 0;
-       local_irq_restore(flags);
+
+       entered--;
        return IRQ_HANDLED;
 }
index 356c721..dfdf11c 100644 (file)
@@ -111,7 +111,6 @@ static int pmu_send_request(struct adb_request *req, int sync);
 static int pmu_autopoll(int devs);
 void pmu_poll(void);
 static int pmu_reset_bus(void);
-static int pmu_queue_request(struct adb_request *req);
 
 static void pmu_start(void);
 static void send_byte(int x);
@@ -475,7 +474,7 @@ pmu_request(struct adb_request *req, void (*done)(struct adb_request *),
        return pmu_queue_request(req);
 }
 
-static int 
+int
 pmu_queue_request(struct adb_request *req)
 {
        unsigned long flags;
index 5347a40..02a0ea6 100644 (file)
@@ -183,7 +183,8 @@ int flexcop_i2c_init(struct flexcop_device *fc)
        mutex_init(&fc->i2c_mutex);
 
        memset(&fc->i2c_adap, 0, sizeof(struct i2c_adapter));
-       strncpy(fc->i2c_adap.name, "B2C2 FlexCop device",I2C_NAME_SIZE);
+       strncpy(fc->i2c_adap.name, "B2C2 FlexCop device",
+               sizeof(fc->i2c_adap.name));
 
        i2c_set_adapdata(&fc->i2c_adap,fc);
 
index a6cbbdd..34d7abc 100644 (file)
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
-#include <linux/pci.h>
 #include <linux/input.h>
 #include <linux/dvb/frontend.h>
 #include <linux/mutex.h>
 #include <linux/mm.h>
+#include <asm/io.h>
 
 #include "dmxdev.h"
 #include "dvb_demux.h"
index 70df31b..088b6de 100644 (file)
@@ -19,7 +19,7 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d)
                return -EINVAL;
        }
 
-       strncpy(d->i2c_adap.name,d->desc->name,I2C_NAME_SIZE);
+       strncpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name));
 #ifdef I2C_ADAP_CLASS_TV_DIGITAL
        d->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
 #else
index a18c8f4..315e09e 100644 (file)
@@ -105,9 +105,9 @@ struct i2c_adapter * dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, enu
 }
 EXPORT_SYMBOL(dibx000_get_i2c_adapter);
 
-static int i2c_adapter_init(struct i2c_adapter *i2c_adap, struct i2c_algorithm *algo, const char name[I2C_NAME_SIZE], struct dibx000_i2c_master *mst)
+static int i2c_adapter_init(struct i2c_adapter *i2c_adap, struct i2c_algorithm *algo, const char *name, struct dibx000_i2c_master *mst)
 {
-       strncpy(i2c_adap->name, name, I2C_NAME_SIZE);
+       strncpy(i2c_adap->name, name, sizeof(i2c_adap->name));
        i2c_adap->class     = I2C_CLASS_TV_DIGITAL,
        i2c_adap->algo      = algo;
        i2c_adap->algo_data = NULL;
index 2aa9ce9..823cd6c 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/major.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/pci.h>
 #include <linux/signal.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
index a3246a2..05c7820 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/major.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/pci.h>
 #include <linux/signal.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
index 6867386..59a4360 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/major.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/pci.h>
 #include <linux/signal.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
index 42e2299..853b1a3 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/major.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/pci.h>
 #include <linux/signal.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
index 772fd52..2e4cf1e 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/major.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/pci.h>
 #include <linux/signal.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
index 88dbddd..d73c86a 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/videodev2.h>
-#include <linux/i2c.h>
 
 #include <media/tuner.h>
 #include <media/cx2341x.h>
index 97ef421..e627062 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/poll.h>
-#include <linux/pci.h>
 #include <linux/signal.h>
 #include <linux/ioport.h>
 #include <linux/types.h>
index ed882eb..418ea8b 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/usb.h>
index 1231335..50c7763 100644 (file)
@@ -15,6 +15,7 @@
 #ifndef __LINUX_OVCAMCHIP_PRIV_H
 #define __LINUX_OVCAMCHIP_PRIV_H
 
+#include <linux/i2c.h>
 #include <media/ovcamchip.h>
 
 #ifdef DEBUG
index 44dc747..74839f9 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/major.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/pci.h>
 #include <linux/signal.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
index 2ce3321..87c3144 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/slab.h>
 
 #include <linux/mm.h>
-#include <linux/pci.h>
 #include <linux/signal.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
index 269d711..80bf911 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/major.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/pci.h>
 #include <linux/signal.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
index e0fdb1a..339592e 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/major.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/pci.h>
 #include <linux/signal.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
index 13f69fe..51ab265 100644 (file)
@@ -24,7 +24,6 @@
 
 
 #include <linux/list.h>
-#include <linux/i2c.h>
 #include <media/v4l2-dev.h>
 #include <media/tuner.h>
 #include "usbvision.h"
index 083acfd..97471af 100644 (file)
@@ -1531,6 +1531,7 @@ mpt_resume(struct pci_dev *pdev)
        MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
        u32 device_state = pdev->current_state;
        int recovery_state;
+       int err;
 
        printk(MYIOC_s_INFO_FMT
        "pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
@@ -1538,7 +1539,9 @@ mpt_resume(struct pci_dev *pdev)
 
        pci_set_power_state(pdev, 0);
        pci_restore_state(pdev);
-       pci_enable_device(pdev);
+       err = pci_enable_device(pdev);
+       if (err)
+               return err;
 
        /* enable interrupts */
        CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
@@ -4739,12 +4742,8 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
 }
 
 /**
- * mpt_inactive_raid_list_free
- *
- * This clears this link list.
- *
- * @ioc - pointer to per adapter structure
- *
+ * mpt_inactive_raid_list_free - This clears this link list.
+ * @ioc : pointer to per adapter structure
  **/
 static void
 mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
@@ -4764,15 +4763,11 @@ mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
 }
 
 /**
- * mpt_inactive_raid_volumes
- *
- * This sets up link list of phy_disk_nums for devices belonging in an inactive volume
- *
- * @ioc - pointer to per adapter structure
- * @channel - volume channel
- * @id - volume target id
- *
+ * mpt_inactive_raid_volumes - sets up link list of phy_disk_nums for devices belonging in an inactive volume
  *
+ * @ioc : pointer to per adapter structure
+ * @channel : volume channel
+ * @id : volume target id
  **/
 static void
 mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
@@ -6663,7 +6658,7 @@ union loginfo_type {
 /**
  *     mpt_iocstatus_info_config - IOCSTATUS information for config pages
  *     @ioc: Pointer to MPT_ADAPTER structure
- *     ioc_status: U32 IOCStatus word from IOC
+ *     @ioc_status: U32 IOCStatus word from IOC
  *     @mf: Pointer to MPT request frame
  *
  *     Refer to lsi/mpi.h.
index e3a3927..d25d3be 100644 (file)
@@ -994,6 +994,7 @@ typedef struct _MPT_SCSI_HOST {
        int                       scandv_wait_done;
        long                      last_queue_full;
        u16                       tm_iocstatus;
+       u16                       spi_pending;
        struct list_head          target_reset_list;
 } MPT_SCSI_HOST;
 
index 2a3e9e6..fa0f776 100644 (file)
@@ -819,10 +819,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
                        sc->resid=0;
                case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:        /* 0x0040 */
                case MPI_IOCSTATUS_SUCCESS:                     /* 0x0000 */
-                       if (scsi_status == MPI_SCSI_STATUS_BUSY)
-                               sc->result = (DID_BUS_BUSY << 16) | scsi_status;
-                       else
-                               sc->result = (DID_OK << 16) | scsi_status;
+                       sc->result = (DID_OK << 16) | scsi_status;
                        if (scsi_state == 0) {
                                ;
                        } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
@@ -1188,20 +1185,7 @@ mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
 int
 mptscsih_resume(struct pci_dev *pdev)
 {
-       MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
-       struct Scsi_Host        *host = ioc->sh;
-       MPT_SCSI_HOST           *hd;
-
-       mpt_resume(pdev);
-
-       if(!host)
-               return 0;
-
-       hd = (MPT_SCSI_HOST *)host->hostdata;
-       if(!hd)
-               return 0;
-
-       return 0;
+       return mpt_resume(pdev);
 }
 
 #endif
@@ -1537,21 +1521,23 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     mptscsih_TMHandler - Generic handler for SCSI Task Management.
- *     Fall through to mpt_HardResetHandler if: not operational, too many
- *     failed TM requests or handshake failure.
- *
- *     @ioc: Pointer to MPT_ADAPTER structure
+ *     @hd: Pointer to MPT SCSI HOST structure
  *     @type: Task Management type
+ *     @channel: channel number for task management
  *     @id: Logical Target ID for reset (if appropriate)
  *     @lun: Logical Unit for reset (if appropriate)
  *     @ctx2abort: Context for the task to be aborted (if appropriate)
+ *     @timeout: timeout for task management control
+ *
+ *     Fall through to mpt_HardResetHandler if: not operational, too many
+ *     failed TM requests or handshake failure.
  *
  *     Remark: Currently invoked from a non-interrupt thread (_bh).
  *
  *     Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
  *     will be active.
  *
- *     Returns 0 for SUCCESS, or FAILED.
+ *     Returns 0 for SUCCESS, or %FAILED.
  **/
 int
 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
@@ -1650,9 +1636,11 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c
  *     mptscsih_IssueTaskMgmt - Generic send Task Management function.
  *     @hd: Pointer to MPT_SCSI_HOST structure
  *     @type: Task Management type
+ *     @channel: channel number for task management
  *     @id: Logical Target ID for reset (if appropriate)
  *     @lun: Logical Unit for reset (if appropriate)
  *     @ctx2abort: Context for the task to be aborted (if appropriate)
+ *     @timeout: timeout for task management control
  *
  *     Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
  *     or a non-interrupt thread.  In the former, must not call schedule().
@@ -2022,6 +2010,7 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
 /**
  *     mptscsih_tm_wait_for_completion - wait for completion of TM task
  *     @hd: Pointer to MPT host structure.
+ *     @timeout: timeout value
  *
  *     Returns {SUCCESS,FAILED}.
  */
index 85f21b5..d75f7ff 100644 (file)
@@ -96,14 +96,13 @@ static int  mptspiTaskCtx = -1;
 static int     mptspiInternalCtx = -1; /* Used only for internal commands */
 
 /**
- *     mptspi_setTargetNegoParms  - Update the target negotiation
- *     parameters based on the the Inquiry data, adapter capabilities,
- *     and NVRAM settings
- *
+ *     mptspi_setTargetNegoParms  - Update the target negotiation parameters
  *     @hd: Pointer to a SCSI Host Structure
- *     @vtarget: per target private data
+ *     @target: per target private data
  *     @sdev: SCSI device
  *
+ *     Update the target negotiation parameters based on the the Inquiry
+ *     data, adapter capabilities, and NVRAM settings.
  **/
 static void
 mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
@@ -234,7 +233,7 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
 /**
  *     mptspi_writeIOCPage4  - write IOC Page 4
  *     @hd: Pointer to a SCSI Host Structure
- *     @channel:
+ *     @channel: channel number
  *     @id: write IOC Page4 for this ID & Bus
  *
  *     Return: -EAGAIN if unable to obtain a Message Frame
@@ -446,7 +445,7 @@ static int mptspi_target_alloc(struct scsi_target *starget)
        return 0;
 }
 
-void
+static void
 mptspi_target_destroy(struct scsi_target *starget)
 {
        if (starget->hostdata)
@@ -677,7 +676,9 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
                return;
        }
 
+       hd->spi_pending |= (1 << sdev->id);
        spi_dv_device(sdev);
+       hd->spi_pending &= ~(1 << sdev->id);
 
        if (sdev->channel == 1 &&
            mptscsih_quiesce_raid(hd, 0, vtarget->channel, vtarget->id) < 0)
@@ -1203,11 +1204,27 @@ mptspi_dv_renegotiate_work(struct work_struct *work)
                container_of(work, struct work_queue_wrapper, work);
        struct _MPT_SCSI_HOST *hd = wqw->hd;
        struct scsi_device *sdev;
+       struct scsi_target *starget;
+       struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
+       u32 nego;
 
        kfree(wqw);
 
-       shost_for_each_device(sdev, hd->ioc->sh)
-               mptspi_dv_device(hd, sdev);
+       if (hd->spi_pending) {
+               shost_for_each_device(sdev, hd->ioc->sh) {
+                       if  (hd->spi_pending & (1 << sdev->id))
+                               continue;
+                       starget = scsi_target(sdev);
+                       nego = mptspi_getRP(starget);
+                       pg1.RequestedParameters = cpu_to_le32(nego);
+                       pg1.Reserved = 0;
+                       pg1.Configuration = 0;
+                       mptspi_write_spi_device_pg1(starget, &pg1);
+               }
+       } else {
+               shost_for_each_device(sdev, hd->ioc->sh)
+                       mptspi_dv_device(hd, sdev);
+       }
 }
 
 static void
@@ -1453,6 +1470,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        init_waitqueue_head(&hd->scandv_waitq);
        hd->scandv_wait_done = 0;
        hd->last_queue_full = 0;
+       hd->spi_pending = 0;
 
        /* Some versions of the firmware don't support page 0; without
         * that we can't get the parameters */
index ca86f11..276ba3c 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
 #include <linux/miscdevice.h>
-#include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/platform_device.h>
 #include <asm/uaccess.h>
index 6a51e99..60c8b26 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/kernel.h>
 #include <linux/proc_fs.h>
 #include <linux/hdpu_features.h>
-#include <linux/pci.h>
 
 #include <linux/platform_device.h>
 
index bc60e2f..1ba6c08 100644 (file)
 
 #include <linux/tifm.h>
 #include <linux/dma-mapping.h>
-#include <linux/freezer.h>
 
 #define DRIVER_NAME "tifm_7xx1"
-#define DRIVER_VERSION "0.7"
+#define DRIVER_VERSION "0.8"
+
+#define TIFM_IRQ_ENABLE           0x80000000
+#define TIFM_IRQ_SOCKMASK(x)      (x)
+#define TIFM_IRQ_CARDMASK(x)      ((x) << 8)
+#define TIFM_IRQ_FIFOMASK(x)      ((x) << 16)
+#define TIFM_IRQ_SETALL           0xffffffff
+
+static void tifm_7xx1_dummy_eject(struct tifm_adapter *fm,
+                                 struct tifm_dev *sock)
+{
+}
 
 static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock)
 {
@@ -22,7 +32,7 @@ static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock)
 
        spin_lock_irqsave(&fm->lock, flags);
        fm->socket_change_set |= 1 << sock->socket_id;
-       wake_up_all(&fm->change_set_notify);
+       tifm_queue_work(&fm->media_switcher);
        spin_unlock_irqrestore(&fm->lock, flags);
 }
 
@@ -30,8 +40,7 @@ static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id)
 {
        struct tifm_adapter *fm = dev_id;
        struct tifm_dev *sock;
-       unsigned int irq_status;
-       unsigned int sock_irq_status, cnt;
+       unsigned int irq_status, cnt;
 
        spin_lock(&fm->lock);
        irq_status = readl(fm->addr + FM_INTERRUPT_STATUS);
@@ -45,12 +54,12 @@ static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id)
 
                for (cnt = 0; cnt < fm->num_sockets; cnt++) {
                        sock = fm->sockets[cnt];
-                       sock_irq_status = (irq_status >> cnt)
-                                         & (TIFM_IRQ_FIFOMASK(1)
-                                            | TIFM_IRQ_CARDMASK(1));
-
-                       if (sock && sock_irq_status)
-                               sock->signal_irq(sock, sock_irq_status);
+                       if (sock) {
+                               if ((irq_status >> cnt) & TIFM_IRQ_FIFOMASK(1))
+                                       sock->data_event(sock);
+                               if ((irq_status >> cnt) & TIFM_IRQ_CARDMASK(1))
+                                       sock->card_event(sock);
+                       }
                }
 
                fm->socket_change_set |= irq_status
@@ -58,57 +67,57 @@ static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id)
        }
        writel(irq_status, fm->addr + FM_INTERRUPT_STATUS);
 
-       if (!fm->socket_change_set)
+       if (fm->finish_me)
+               complete_all(fm->finish_me);
+       else if (!fm->socket_change_set)
                writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE);
        else
-               wake_up_all(&fm->change_set_notify);
+               tifm_queue_work(&fm->media_switcher);
 
        spin_unlock(&fm->lock);
        return IRQ_HANDLED;
 }
 
-static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr,
-                                                int is_x2)
+static unsigned char tifm_7xx1_toggle_sock_power(char __iomem *sock_addr)
 {
        unsigned int s_state;
        int cnt;
 
        writel(0x0e00, sock_addr + SOCK_CONTROL);
 
-       for (cnt = 0; cnt < 100; cnt++) {
+       for (cnt = 16; cnt <= 256; cnt <<= 1) {
                if (!(TIFM_SOCK_STATE_POWERED
                      & readl(sock_addr + SOCK_PRESENT_STATE)))
                        break;
-               msleep(10);
+
+               msleep(cnt);
        }
 
        s_state = readl(sock_addr + SOCK_PRESENT_STATE);
        if (!(TIFM_SOCK_STATE_OCCUPIED & s_state))
-               return FM_NULL;
-
-       if (is_x2) {
-               writel((s_state & 7) | 0x0c00, sock_addr + SOCK_CONTROL);
-       } else {
-               // SmartMedia cards need extra 40 msec
-               if (((readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7) == 1)
-                       msleep(40);
-               writel(readl(sock_addr + SOCK_CONTROL) | TIFM_CTRL_LED,
-                      sock_addr + SOCK_CONTROL);
-               msleep(10);
-               writel((s_state & 0x7) | 0x0c00 | TIFM_CTRL_LED,
-                       sock_addr + SOCK_CONTROL);
-       }
+               return 0;
 
-       for (cnt = 0; cnt < 100; cnt++) {
+       writel(readl(sock_addr + SOCK_CONTROL) | TIFM_CTRL_LED,
+              sock_addr + SOCK_CONTROL);
+
+       /* xd needs some extra time before power on */
+       if (((readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7)
+           == TIFM_TYPE_XD)
+               msleep(40);
+
+       writel((s_state & 7) | 0x0c00, sock_addr + SOCK_CONTROL);
+       /* wait for power to stabilize */
+       msleep(20);
+       for (cnt = 16; cnt <= 256; cnt <<= 1) {
                if ((TIFM_SOCK_STATE_POWERED
                     & readl(sock_addr + SOCK_PRESENT_STATE)))
                        break;
-               msleep(10);
+
+               msleep(cnt);
        }
 
-       if (!is_x2)
-               writel(readl(sock_addr + SOCK_CONTROL) & (~TIFM_CTRL_LED),
-                      sock_addr + SOCK_CONTROL);
+       writel(readl(sock_addr + SOCK_CONTROL) & (~TIFM_CTRL_LED),
+              sock_addr + SOCK_CONTROL);
 
        return (readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7;
 }
@@ -119,127 +128,77 @@ tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num)
        return base_addr + ((sock_num + 1) << 10);
 }
 
-static int tifm_7xx1_switch_media(void *data)
+static void tifm_7xx1_switch_media(struct work_struct *work)
 {
-       struct tifm_adapter *fm = data;
-       unsigned long flags;
-       tifm_media_id media_id;
-       char *card_name = "xx";
-       int cnt, rc;
+       struct tifm_adapter *fm = container_of(work, struct tifm_adapter,
+                                              media_switcher);
        struct tifm_dev *sock;
-       unsigned int socket_change_set;
-
-       while (1) {
-               rc = wait_event_interruptible(fm->change_set_notify,
-                                             fm->socket_change_set);
-               if (rc == -ERESTARTSYS)
-                       try_to_freeze();
+       unsigned long flags;
+       unsigned char media_id;
+       unsigned int socket_change_set, cnt;
 
-               spin_lock_irqsave(&fm->lock, flags);
-               socket_change_set = fm->socket_change_set;
-               fm->socket_change_set = 0;
+       spin_lock_irqsave(&fm->lock, flags);
+       socket_change_set = fm->socket_change_set;
+       fm->socket_change_set = 0;
 
-               dev_dbg(fm->dev, "checking media set %x\n",
-                       socket_change_set);
+       dev_dbg(fm->cdev.dev, "checking media set %x\n",
+               socket_change_set);
 
-               if (kthread_should_stop())
-                       socket_change_set = (1 << fm->num_sockets) - 1;
+       if (!socket_change_set) {
                spin_unlock_irqrestore(&fm->lock, flags);
+               return;
+       }
 
-               if (!socket_change_set)
+       for (cnt = 0; cnt < fm->num_sockets; cnt++) {
+               if (!(socket_change_set & (1 << cnt)))
                        continue;
-
-               spin_lock_irqsave(&fm->lock, flags);
-               for (cnt = 0; cnt < fm->num_sockets; cnt++) {
-                       if (!(socket_change_set & (1 << cnt)))
-                               continue;
-                       sock = fm->sockets[cnt];
-                       if (sock) {
-                               printk(KERN_INFO DRIVER_NAME
-                                      ": demand removing card from socket %d\n",
-                                      cnt);
-                               fm->sockets[cnt] = NULL;
-                               spin_unlock_irqrestore(&fm->lock, flags);
-                               device_unregister(&sock->dev);
-                               spin_lock_irqsave(&fm->lock, flags);
-                               writel(0x0e00,
-                                      tifm_7xx1_sock_addr(fm->addr, cnt)
-                                      + SOCK_CONTROL);
-                       }
-                       if (kthread_should_stop())
-                               continue;
-
+               sock = fm->sockets[cnt];
+               if (sock) {
+                       printk(KERN_INFO
+                              "%s : demand removing card from socket %u:%u\n",
+                              fm->cdev.class_id, fm->id, cnt);
+                       fm->sockets[cnt] = NULL;
                        spin_unlock_irqrestore(&fm->lock, flags);
-                       media_id = tifm_7xx1_toggle_sock_power(
-                                       tifm_7xx1_sock_addr(fm->addr, cnt),
-                                       fm->num_sockets == 2);
-                       if (media_id) {
-                               sock = tifm_alloc_device(fm);
-                               if (sock) {
-                                       sock->addr = tifm_7xx1_sock_addr(fm->addr,
-                                                                        cnt);
-                                       sock->media_id = media_id;
-                                       sock->socket_id = cnt;
-                                       switch (media_id) {
-                                       case 1:
-                                               card_name = "xd";
-                                               break;
-                                       case 2:
-                                               card_name = "ms";
-                                               break;
-                                       case 3:
-                                               card_name = "sd";
-                                               break;
-                                       default:
-                                               tifm_free_device(&sock->dev);
-                                               spin_lock_irqsave(&fm->lock, flags);
-                                               continue;
-                                       }
-                                       snprintf(sock->dev.bus_id, BUS_ID_SIZE,
-                                                "tifm_%s%u:%u", card_name,
-                                                fm->id, cnt);
-                                       printk(KERN_INFO DRIVER_NAME
-                                              ": %s card detected in socket %d\n",
-                                              card_name, cnt);
-                                       if (!device_register(&sock->dev)) {
-                                               spin_lock_irqsave(&fm->lock, flags);
-                                               if (!fm->sockets[cnt]) {
-                                                       fm->sockets[cnt] = sock;
-                                                       sock = NULL;
-                                               }
-                                               spin_unlock_irqrestore(&fm->lock, flags);
-                                       }
-                                       if (sock)
-                                               tifm_free_device(&sock->dev);
-                               }
-                               spin_lock_irqsave(&fm->lock, flags);
-                       }
+                       device_unregister(&sock->dev);
+                       spin_lock_irqsave(&fm->lock, flags);
+                       writel(0x0e00, tifm_7xx1_sock_addr(fm->addr, cnt)
+                              + SOCK_CONTROL);
                }
 
-               if (!kthread_should_stop()) {
-                       writel(TIFM_IRQ_FIFOMASK(socket_change_set)
-                              | TIFM_IRQ_CARDMASK(socket_change_set),
-                              fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-                       writel(TIFM_IRQ_FIFOMASK(socket_change_set)
-                              | TIFM_IRQ_CARDMASK(socket_change_set),
-                              fm->addr + FM_SET_INTERRUPT_ENABLE);
-                       writel(TIFM_IRQ_ENABLE,
-                              fm->addr + FM_SET_INTERRUPT_ENABLE);
-                       spin_unlock_irqrestore(&fm->lock, flags);
-               } else {
-                       for (cnt = 0; cnt < fm->num_sockets; cnt++) {
-                               if (fm->sockets[cnt])
-                                       fm->socket_change_set |= 1 << cnt;
-                       }
-                       if (!fm->socket_change_set) {
-                               spin_unlock_irqrestore(&fm->lock, flags);
-                               return 0;
-                       } else {
+               spin_unlock_irqrestore(&fm->lock, flags);
+
+               media_id = tifm_7xx1_toggle_sock_power(
+                               tifm_7xx1_sock_addr(fm->addr, cnt));
+
+               // tifm_alloc_device will check if media_id is valid
+               sock = tifm_alloc_device(fm, cnt, media_id);
+               if (sock) {
+                       sock->addr = tifm_7xx1_sock_addr(fm->addr, cnt);
+
+                       if (!device_register(&sock->dev)) {
+                               spin_lock_irqsave(&fm->lock, flags);
+                               if (!fm->sockets[cnt]) {
+                                       fm->sockets[cnt] = sock;
+                                       sock = NULL;
+                               }
                                spin_unlock_irqrestore(&fm->lock, flags);
                        }
+                       if (sock)
+                               tifm_free_device(&sock->dev);
                }
+               spin_lock_irqsave(&fm->lock, flags);
        }
-       return 0;
+
+       writel(TIFM_IRQ_FIFOMASK(socket_change_set)
+              | TIFM_IRQ_CARDMASK(socket_change_set),
+              fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
+
+       writel(TIFM_IRQ_FIFOMASK(socket_change_set)
+              | TIFM_IRQ_CARDMASK(socket_change_set),
+              fm->addr + FM_SET_INTERRUPT_ENABLE);
+
+       writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE);
+       spin_unlock_irqrestore(&fm->lock, flags);
 }
 
 #ifdef CONFIG_PM
@@ -258,9 +217,11 @@ static int tifm_7xx1_suspend(struct pci_dev *dev, pm_message_t state)
 static int tifm_7xx1_resume(struct pci_dev *dev)
 {
        struct tifm_adapter *fm = pci_get_drvdata(dev);
-       int cnt, rc;
+       int rc;
+       unsigned int good_sockets = 0, bad_sockets = 0;
        unsigned long flags;
-       tifm_media_id new_ids[fm->num_sockets];
+       unsigned char new_ids[fm->num_sockets];
+       DECLARE_COMPLETION_ONSTACK(finish_resume);
 
        pci_set_power_state(dev, PCI_D0);
        pci_restore_state(dev);
@@ -271,45 +232,49 @@ static int tifm_7xx1_resume(struct pci_dev *dev)
 
        dev_dbg(&dev->dev, "resuming host\n");
 
-       for (cnt = 0; cnt < fm->num_sockets; cnt++)
-               new_ids[cnt] = tifm_7xx1_toggle_sock_power(
-                                       tifm_7xx1_sock_addr(fm->addr, cnt),
-                                       fm->num_sockets == 2);
+       for (rc = 0; rc < fm->num_sockets; rc++)
+               new_ids[rc] = tifm_7xx1_toggle_sock_power(
+                                       tifm_7xx1_sock_addr(fm->addr, rc));
        spin_lock_irqsave(&fm->lock, flags);
-       fm->socket_change_set = 0;
-       for (cnt = 0; cnt < fm->num_sockets; cnt++) {
-               if (fm->sockets[cnt]) {
-                       if (fm->sockets[cnt]->media_id == new_ids[cnt])
-                               fm->socket_change_set |= 1 << cnt;
-
-                       fm->sockets[cnt]->media_id = new_ids[cnt];
+       for (rc = 0; rc < fm->num_sockets; rc++) {
+               if (fm->sockets[rc]) {
+                       if (fm->sockets[rc]->type == new_ids[rc])
+                               good_sockets |= 1 << rc;
+                       else
+                               bad_sockets |= 1 << rc;
                }
        }
 
        writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
               fm->addr + FM_SET_INTERRUPT_ENABLE);
-       if (!fm->socket_change_set) {
-               spin_unlock_irqrestore(&fm->lock, flags);
-               return 0;
-       } else {
-               fm->socket_change_set = 0;
+       dev_dbg(&dev->dev, "change sets on resume: good %x, bad %x\n",
+               good_sockets, bad_sockets);
+
+       fm->socket_change_set = 0;
+       if (good_sockets) {
+               fm->finish_me = &finish_resume;
                spin_unlock_irqrestore(&fm->lock, flags);
+               rc = wait_for_completion_timeout(&finish_resume, HZ);
+               dev_dbg(&dev->dev, "wait returned %d\n", rc);
+               writel(TIFM_IRQ_FIFOMASK(good_sockets)
+                      | TIFM_IRQ_CARDMASK(good_sockets),
+                      fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
+               writel(TIFM_IRQ_FIFOMASK(good_sockets)
+                      | TIFM_IRQ_CARDMASK(good_sockets),
+                      fm->addr + FM_SET_INTERRUPT_ENABLE);
+               spin_lock_irqsave(&fm->lock, flags);
+               fm->finish_me = NULL;
+               fm->socket_change_set ^= good_sockets & fm->socket_change_set;
        }
 
-       wait_event_timeout(fm->change_set_notify, fm->socket_change_set, HZ);
+       fm->socket_change_set |= bad_sockets;
+       if (fm->socket_change_set)
+               tifm_queue_work(&fm->media_switcher);
 
-       spin_lock_irqsave(&fm->lock, flags);
-       writel(TIFM_IRQ_FIFOMASK(fm->socket_change_set)
-              | TIFM_IRQ_CARDMASK(fm->socket_change_set),
-              fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-       writel(TIFM_IRQ_FIFOMASK(fm->socket_change_set)
-              | TIFM_IRQ_CARDMASK(fm->socket_change_set),
-              fm->addr + FM_SET_INTERRUPT_ENABLE);
+       spin_unlock_irqrestore(&fm->lock, flags);
        writel(TIFM_IRQ_ENABLE,
               fm->addr + FM_SET_INTERRUPT_ENABLE);
-       fm->socket_change_set = 0;
 
-       spin_unlock_irqrestore(&fm->lock, flags);
        return 0;
 }
 
@@ -345,20 +310,14 @@ static int tifm_7xx1_probe(struct pci_dev *dev,
 
        pci_intx(dev, 1);
 
-       fm = tifm_alloc_adapter();
+       fm = tifm_alloc_adapter(dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM
+                               ? 4 : 2, &dev->dev);
        if (!fm) {
                rc = -ENOMEM;
                goto err_out_int;
        }
 
-       fm->dev = &dev->dev;
-       fm->num_sockets = (dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM)
-                         ? 4 : 2;
-       fm->sockets = kzalloc(sizeof(struct tifm_dev*) * fm->num_sockets,
-                             GFP_KERNEL);
-       if (!fm->sockets)
-               goto err_out_free;
-
+       INIT_WORK(&fm->media_switcher, tifm_7xx1_switch_media);
        fm->eject = tifm_7xx1_eject;
        pci_set_drvdata(dev, fm);
 
@@ -367,19 +326,16 @@ static int tifm_7xx1_probe(struct pci_dev *dev,
        if (!fm->addr)
                goto err_out_free;
 
-       rc = request_irq(dev->irq, tifm_7xx1_isr, IRQF_SHARED, DRIVER_NAME, fm);
+       rc = request_irq(dev->irq, tifm_7xx1_isr, SA_SHIRQ, DRIVER_NAME, fm);
        if (rc)
                goto err_out_unmap;
 
-       init_waitqueue_head(&fm->change_set_notify);
-       rc = tifm_add_adapter(fm, tifm_7xx1_switch_media);
+       rc = tifm_add_adapter(fm);
        if (rc)
                goto err_out_irq;
 
-       writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
        writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
               fm->addr + FM_SET_INTERRUPT_ENABLE);
-       wake_up_process(fm->media_switcher);
        return 0;
 
 err_out_irq:
@@ -401,18 +357,12 @@ err_out:
 static void tifm_7xx1_remove(struct pci_dev *dev)
 {
        struct tifm_adapter *fm = pci_get_drvdata(dev);
-       unsigned long flags;
 
+       fm->eject = tifm_7xx1_dummy_eject;
        writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
        mmiowb();
        free_irq(dev->irq, fm);
 
-       spin_lock_irqsave(&fm->lock, flags);
-       fm->socket_change_set = (1 << fm->num_sockets) - 1;
-       spin_unlock_irqrestore(&fm->lock, flags);
-
-       kthread_stop(fm->media_switcher);
-
        tifm_remove_adapter(fm);
 
        pci_set_drvdata(dev, NULL);
index 6b10ebe..d195fb0 100644 (file)
 #include <linux/idr.h>
 
 #define DRIVER_NAME "tifm_core"
-#define DRIVER_VERSION "0.7"
+#define DRIVER_VERSION "0.8"
 
+static struct workqueue_struct *workqueue;
 static DEFINE_IDR(tifm_adapter_idr);
 static DEFINE_SPINLOCK(tifm_adapter_lock);
 
-static tifm_media_id *tifm_device_match(tifm_media_id *ids,
-                       struct tifm_dev *dev)
+static const char *tifm_media_type_name(unsigned char type, unsigned char nt)
 {
-       while (*ids) {
-               if (dev->media_id == *ids)
-                       return ids;
-               ids++;
-       }
-       return NULL;
+       const char *card_type_name[3][3] = {
+               { "SmartMedia/xD", "MemoryStick", "MMC/SD" },
+               { "XD", "MS", "SD"},
+               { "xd", "ms", "sd"}
+       };
+
+       if (nt > 2 || type < 1 || type > 3)
+               return NULL;
+       return card_type_name[nt][type - 1];
 }
 
-static int tifm_match(struct device *dev, struct device_driver *drv)
+static int tifm_dev_match(struct tifm_dev *sock, struct tifm_device_id *id)
 {
-       struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
-       struct tifm_driver *fm_drv;
-
-       fm_drv = container_of(drv, struct tifm_driver, driver);
-       if (!fm_drv->id_table)
-               return -EINVAL;
-       if (tifm_device_match(fm_drv->id_table, fm_dev))
+       if (sock->type == id->type)
                return 1;
-       return -ENODEV;
+       return 0;
+}
+
+static int tifm_bus_match(struct device *dev, struct device_driver *drv)
+{
+       struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+       struct tifm_driver *fm_drv = container_of(drv, struct tifm_driver,
+                                                 driver);
+       struct tifm_device_id *ids = fm_drv->id_table;
+
+       if (ids) {
+               while (ids->type) {
+                       if (tifm_dev_match(sock, ids))
+                               return 1;
+                       ++ids;
+               }
+       }
+       return 0;
 }
 
 static int tifm_uevent(struct device *dev, char **envp, int num_envp,
                       char *buffer, int buffer_size)
 {
-       struct tifm_dev *fm_dev;
+       struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
        int i = 0;
        int length = 0;
-       const char *card_type_name[] = {"INV", "SM", "MS", "SD"};
 
-       if (!dev || !(fm_dev = container_of(dev, struct tifm_dev, dev)))
-               return -ENODEV;
        if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
-                       "TIFM_CARD_TYPE=%s", card_type_name[fm_dev->media_id]))
+                          "TIFM_CARD_TYPE=%s",
+                          tifm_media_type_name(sock->type, 1)))
                return -ENOMEM;
 
        return 0;
 }
 
+static int tifm_device_probe(struct device *dev)
+{
+       struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+       struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
+                                              driver);
+       int rc = -ENODEV;
+
+       get_device(dev);
+       if (dev->driver && drv->probe) {
+               rc = drv->probe(sock);
+               if (!rc)
+                       return 0;
+       }
+       put_device(dev);
+       return rc;
+}
+
+static void tifm_dummy_event(struct tifm_dev *sock)
+{
+       return;
+}
+
+static int tifm_device_remove(struct device *dev)
+{
+       struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+       struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
+                                              driver);
+
+       if (dev->driver && drv->remove) {
+               sock->card_event = tifm_dummy_event;
+               sock->data_event = tifm_dummy_event;
+               drv->remove(sock);
+               sock->dev.driver = NULL;
+       }
+
+       put_device(dev);
+       return 0;
+}
+
 #ifdef CONFIG_PM
 
 static int tifm_device_suspend(struct device *dev, pm_message_t state)
 {
-       struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
-       struct tifm_driver *drv = fm_dev->drv;
+       struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+       struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
+                                              driver);
 
-       if (drv && drv->suspend)
-               return drv->suspend(fm_dev, state);
+       if (dev->driver && drv->suspend)
+               return drv->suspend(sock, state);
        return 0;
 }
 
 static int tifm_device_resume(struct device *dev)
 {
-       struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
-       struct tifm_driver *drv = fm_dev->drv;
+       struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+       struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
+                                              driver);
 
-       if (drv && drv->resume)
-               return drv->resume(fm_dev);
+       if (dev->driver && drv->resume)
+               return drv->resume(sock);
        return 0;
 }
 
@@ -89,19 +142,33 @@ static int tifm_device_resume(struct device *dev)
 
 #endif /* CONFIG_PM */
 
+static ssize_t type_show(struct device *dev, struct device_attribute *attr,
+                        char *buf)
+{
+       struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+       return sprintf(buf, "%x", sock->type);
+}
+
+static struct device_attribute tifm_dev_attrs[] = {
+       __ATTR(type, S_IRUGO, type_show, NULL),
+       __ATTR_NULL
+};
+
 static struct bus_type tifm_bus_type = {
-       .name    = "tifm",
-       .match   = tifm_match,
-       .uevent  = tifm_uevent,
-       .suspend = tifm_device_suspend,
-       .resume  = tifm_device_resume
+       .name      = "tifm",
+       .dev_attrs = tifm_dev_attrs,
+       .match     = tifm_bus_match,
+       .uevent    = tifm_uevent,
+       .probe     = tifm_device_probe,
+       .remove    = tifm_device_remove,
+       .suspend   = tifm_device_suspend,
+       .resume    = tifm_device_resume
 };
 
 static void tifm_free(struct class_device *cdev)
 {
        struct tifm_adapter *fm = container_of(cdev, struct tifm_adapter, cdev);
 
-       kfree(fm->sockets);
        kfree(fm);
 }
 
@@ -110,28 +177,25 @@ static struct class tifm_adapter_class = {
        .release = tifm_free
 };
 
-struct tifm_adapter *tifm_alloc_adapter(void)
+struct tifm_adapter *tifm_alloc_adapter(unsigned int num_sockets,
+                                       struct device *dev)
 {
        struct tifm_adapter *fm;
 
-       fm = kzalloc(sizeof(struct tifm_adapter), GFP_KERNEL);
+       fm = kzalloc(sizeof(struct tifm_adapter)
+                    + sizeof(struct tifm_dev*) * num_sockets, GFP_KERNEL);
        if (fm) {
                fm->cdev.class = &tifm_adapter_class;
-               spin_lock_init(&fm->lock);
+               fm->cdev.dev = dev;
                class_device_initialize(&fm->cdev);
+               spin_lock_init(&fm->lock);
+               fm->num_sockets = num_sockets;
        }
        return fm;
 }
 EXPORT_SYMBOL(tifm_alloc_adapter);
 
-void tifm_free_adapter(struct tifm_adapter *fm)
-{
-       class_device_put(&fm->cdev);
-}
-EXPORT_SYMBOL(tifm_free_adapter);
-
-int tifm_add_adapter(struct tifm_adapter *fm,
-                    int (*mediathreadfn)(void *data))
+int tifm_add_adapter(struct tifm_adapter *fm)
 {
        int rc;
 
@@ -141,59 +205,80 @@ int tifm_add_adapter(struct tifm_adapter *fm,
        spin_lock(&tifm_adapter_lock);
        rc = idr_get_new(&tifm_adapter_idr, fm, &fm->id);
        spin_unlock(&tifm_adapter_lock);
-       if (!rc) {
-               snprintf(fm->cdev.class_id, BUS_ID_SIZE, "tifm%u", fm->id);
-               fm->media_switcher = kthread_create(mediathreadfn,
-                                                   fm, "tifm/%u", fm->id);
-
-               if (!IS_ERR(fm->media_switcher))
-                       return class_device_add(&fm->cdev);
+       if (rc)
+               return rc;
 
+       snprintf(fm->cdev.class_id, BUS_ID_SIZE, "tifm%u", fm->id);
+       rc = class_device_add(&fm->cdev);
+       if (rc) {
                spin_lock(&tifm_adapter_lock);
                idr_remove(&tifm_adapter_idr, fm->id);
                spin_unlock(&tifm_adapter_lock);
-               rc = -ENOMEM;
        }
+
        return rc;
 }
 EXPORT_SYMBOL(tifm_add_adapter);
 
 void tifm_remove_adapter(struct tifm_adapter *fm)
 {
-       class_device_del(&fm->cdev);
+       unsigned int cnt;
+
+       flush_workqueue(workqueue);
+       for (cnt = 0; cnt < fm->num_sockets; ++cnt) {
+               if (fm->sockets[cnt])
+                       device_unregister(&fm->sockets[cnt]->dev);
+       }
 
        spin_lock(&tifm_adapter_lock);
        idr_remove(&tifm_adapter_idr, fm->id);
        spin_unlock(&tifm_adapter_lock);
+       class_device_del(&fm->cdev);
 }
 EXPORT_SYMBOL(tifm_remove_adapter);
 
-void tifm_free_device(struct device *dev)
+void tifm_free_adapter(struct tifm_adapter *fm)
 {
-       struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
-       kfree(fm_dev);
+       class_device_put(&fm->cdev);
 }
-EXPORT_SYMBOL(tifm_free_device);
+EXPORT_SYMBOL(tifm_free_adapter);
 
-static void tifm_dummy_signal_irq(struct tifm_dev *sock,
-                                 unsigned int sock_irq_status)
+void tifm_free_device(struct device *dev)
 {
-       return;
+       struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+       kfree(sock);
 }
+EXPORT_SYMBOL(tifm_free_device);
 
-struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm)
+struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id,
+                                  unsigned char type)
 {
-       struct tifm_dev *dev = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL);
-
-       if (dev) {
-               spin_lock_init(&dev->lock);
-
-               dev->dev.parent = fm->dev;
-               dev->dev.bus = &tifm_bus_type;
-               dev->dev.release = tifm_free_device;
-               dev->signal_irq = tifm_dummy_signal_irq;
+       struct tifm_dev *sock = NULL;
+
+       if (!tifm_media_type_name(type, 0))
+               return sock;
+
+       sock = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL);
+       if (sock) {
+               spin_lock_init(&sock->lock);
+               sock->type = type;
+               sock->socket_id = id;
+               sock->card_event = tifm_dummy_event;
+               sock->data_event = tifm_dummy_event;
+
+               sock->dev.parent = fm->cdev.dev;
+               sock->dev.bus = &tifm_bus_type;
+               sock->dev.dma_mask = fm->cdev.dev->dma_mask;
+               sock->dev.release = tifm_free_device;
+
+               snprintf(sock->dev.bus_id, BUS_ID_SIZE,
+                        "tifm_%s%u:%u", tifm_media_type_name(type, 2),
+                        fm->id, id);
+               printk(KERN_INFO DRIVER_NAME
+                      ": %s card detected in socket %u:%u\n",
+                      tifm_media_type_name(type, 0), fm->id, id);
        }
-       return dev;
+       return sock;
 }
 EXPORT_SYMBOL(tifm_alloc_device);
 
@@ -218,54 +303,15 @@ void tifm_unmap_sg(struct tifm_dev *sock, struct scatterlist *sg, int nents,
 }
 EXPORT_SYMBOL(tifm_unmap_sg);
 
-static int tifm_device_probe(struct device *dev)
-{
-       struct tifm_driver *drv;
-       struct tifm_dev *fm_dev;
-       int rc = 0;
-       const tifm_media_id *id;
-
-       drv = container_of(dev->driver, struct tifm_driver, driver);
-       fm_dev = container_of(dev, struct tifm_dev, dev);
-       get_device(dev);
-       if (!fm_dev->drv && drv->probe && drv->id_table) {
-               rc = -ENODEV;
-               id = tifm_device_match(drv->id_table, fm_dev);
-               if (id)
-                       rc = drv->probe(fm_dev);
-               if (rc >= 0) {
-                       rc = 0;
-                       fm_dev->drv = drv;
-               }
-       }
-       if (rc)
-               put_device(dev);
-       return rc;
-}
-
-static int tifm_device_remove(struct device *dev)
+void tifm_queue_work(struct work_struct *work)
 {
-       struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
-       struct tifm_driver *drv = fm_dev->drv;
-
-       if (drv) {
-               fm_dev->signal_irq = tifm_dummy_signal_irq;
-               if (drv->remove)
-                       drv->remove(fm_dev);
-               fm_dev->drv = NULL;
-       }
-
-       put_device(dev);
-       return 0;
+       queue_work(workqueue, work);
 }
+EXPORT_SYMBOL(tifm_queue_work);
 
 int tifm_register_driver(struct tifm_driver *drv)
 {
        drv->driver.bus = &tifm_bus_type;
-       drv->driver.probe = tifm_device_probe;
-       drv->driver.remove = tifm_device_remove;
-       drv->driver.suspend = tifm_device_suspend;
-       drv->driver.resume = tifm_device_resume;
 
        return driver_register(&drv->driver);
 }
@@ -279,13 +325,25 @@ EXPORT_SYMBOL(tifm_unregister_driver);
 
 static int __init tifm_init(void)
 {
-       int rc = bus_register(&tifm_bus_type);
+       int rc;
 
-       if (!rc) {
-               rc = class_register(&tifm_adapter_class);
-               if (rc)
-                       bus_unregister(&tifm_bus_type);
-       }
+       workqueue = create_freezeable_workqueue("tifm");
+       if (!workqueue)
+               return -ENOMEM;
+
+       rc = bus_register(&tifm_bus_type);
+
+       if (rc)
+               goto err_out_wq;
+
+       rc = class_register(&tifm_adapter_class);
+       if (!rc)
+               return 0;
+
+       bus_unregister(&tifm_bus_type);
+
+err_out_wq:
+       destroy_workqueue(workqueue);
 
        return rc;
 }
@@ -294,6 +352,7 @@ static void __exit tifm_exit(void)
 {
        class_unregister(&tifm_adapter_class);
        bus_unregister(&tifm_bus_type);
+       destroy_workqueue(workqueue);
 }
 
 subsys_initcall(tifm_init);
index 12af9c7..6c97491 100644 (file)
@@ -19,110 +19,10 @@ config MMC_DEBUG
          This is an option for use by developers; most people should
          say N here.  This enables MMC core and driver debugging.
 
-config MMC_BLOCK
-       tristate "MMC block device driver"
-       depends on MMC && BLOCK
-       default y
-       help
-         Say Y here to enable the MMC block device driver support.
-         This provides a block device driver, which you can use to
-         mount the filesystem. Almost everyone wishing MMC support
-         should say Y or M here.
-
-config MMC_ARMMMCI
-       tristate "ARM AMBA Multimedia Card Interface support"
-       depends on ARM_AMBA && MMC
-       help
-         This selects the ARM(R) AMBA(R) PrimeCell Multimedia Card
-         Interface (PL180 and PL181) support.  If you have an ARM(R)
-         platform with a Multimedia Card slot, say Y or M here.
-
-         If unsure, say N.
-
-config MMC_PXA
-       tristate "Intel PXA25x/26x/27x Multimedia Card Interface support"
-       depends on ARCH_PXA && MMC
-       help
-         This selects the Intel(R) PXA(R) Multimedia card Interface.
-         If you have a PXA(R) platform with a Multimedia Card slot,
-         say Y or M here.
-
-         If unsure, say N.
-
-config MMC_SDHCI
-       tristate "Secure Digital Host Controller Interface support  (EXPERIMENTAL)"
-       depends on PCI && MMC && EXPERIMENTAL
-       help
-         This select the generic Secure Digital Host Controller Interface.
-         It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
-         and Toshiba(R). Most controllers found in laptops are of this type.
-         If you have a controller with this interface, say Y or M here.
-
-         If unsure, say N.
-
-config MMC_OMAP
-       tristate "TI OMAP Multimedia Card Interface support"
-       depends on ARCH_OMAP && MMC
-       select TPS65010 if MACH_OMAP_H2
-       help
-         This selects the TI OMAP Multimedia card Interface.
-         If you have an OMAP board with a Multimedia Card slot,
-         say Y or M here.
-
-         If unsure, say N.
+source "drivers/mmc/core/Kconfig"
 
-config MMC_WBSD
-       tristate "Winbond W83L51xD SD/MMC Card Interface support"
-       depends on MMC && ISA_DMA_API
-       help
-         This selects the Winbond(R) W83L51xD Secure digital and
-          Multimedia card Interface.
-         If you have a machine with a integrated W83L518D or W83L519D
-         SD/MMC card reader, say Y or M here.
-
-         If unsure, say N.
-
-config MMC_AU1X
-       tristate "Alchemy AU1XX0 MMC Card Interface support"
-       depends on MMC && SOC_AU1200
-       help
-         This selects the AMD Alchemy(R) Multimedia card interface.
-         If you have a Alchemy platform with a MMC slot, say Y or M here.
-
-         If unsure, say N.
-
-config MMC_AT91
-       tristate "AT91 SD/MMC Card Interface support"
-       depends on ARCH_AT91 && MMC
-       help
-         This selects the AT91 MCI controller.
-
-         If unsure, say N.
-
-config MMC_IMX
-       tristate "Motorola i.MX Multimedia Card Interface support"
-       depends on ARCH_IMX && MMC
-       help
-         This selects the Motorola i.MX Multimedia card Interface.
-         If you have a i.MX platform with a Multimedia Card slot,
-         say Y or M here.
-
-         If unsure, say N.
-
-config MMC_TIFM_SD
-       tristate "TI Flash Media MMC/SD Interface support  (EXPERIMENTAL)"
-       depends on MMC && EXPERIMENTAL && PCI
-       select TIFM_CORE
-       help
-         Say Y here if you want to be able to access MMC/SD cards with
-         the Texas Instruments(R) Flash Media card reader, found in many
-         laptops.
-         This option 'selects' (turns on, enables) 'TIFM_CORE', but you
-         probably also need appropriate card reader host adapter, such as
-         'Misc devices: TI Flash Media PCI74xx/PCI76xx host adapter support
-         (TIFM_7XX1)'.
+source "drivers/mmc/card/Kconfig"
 
-          To compile this driver as a module, choose M here: the
-         module will be called tifm_sd.
+source "drivers/mmc/host/Kconfig"
 
 endmenu
index 83ffb93..9979f5e 100644 (file)
@@ -2,32 +2,11 @@
 # Makefile for the kernel mmc device drivers.
 #
 
-#
-# Core
-#
-obj-$(CONFIG_MMC)              += mmc_core.o
-
-#
-# Media drivers
-#
-obj-$(CONFIG_MMC_BLOCK)                += mmc_block.o
-
-#
-# Host drivers
-#
-obj-$(CONFIG_MMC_ARMMMCI)      += mmci.o
-obj-$(CONFIG_MMC_PXA)          += pxamci.o
-obj-$(CONFIG_MMC_IMX)          += imxmmc.o
-obj-$(CONFIG_MMC_SDHCI)                += sdhci.o
-obj-$(CONFIG_MMC_WBSD)         += wbsd.o
-obj-$(CONFIG_MMC_AU1X)         += au1xmmc.o
-obj-$(CONFIG_MMC_OMAP)         += omap.o
-obj-$(CONFIG_MMC_AT91)         += at91_mci.o
-obj-$(CONFIG_MMC_TIFM_SD)      += tifm_sd.o
-
-mmc_core-y := mmc.o mmc_sysfs.o
-mmc_core-$(CONFIG_BLOCK) += mmc_queue.o
-
 ifeq ($(CONFIG_MMC_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
+       EXTRA_CFLAGS            += -DDEBUG
 endif
+
+obj-$(CONFIG_MMC)              += core/
+obj-$(CONFIG_MMC)              += card/
+obj-$(CONFIG_MMC)              += host/
+
diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig
new file mode 100644 (file)
index 0000000..01a9fd3
--- /dev/null
@@ -0,0 +1,17 @@
+#
+# MMC/SD card drivers
+#
+
+comment "MMC/SD Card Drivers"
+       depends MMC
+
+config MMC_BLOCK
+       tristate "MMC block device driver"
+       depends on MMC && BLOCK
+       default y
+       help
+         Say Y here to enable the MMC block device driver support.
+         This provides a block device driver, which you can use to
+         mount the filesystem. Almost everyone wishing MMC support
+         should say Y or M here.
+
diff --git a/drivers/mmc/card/Makefile b/drivers/mmc/card/Makefile
new file mode 100644 (file)
index 0000000..cf8c939
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile for MMC/SD card drivers
+#
+
+ifeq ($(CONFIG_MMC_DEBUG),y)
+       EXTRA_CFLAGS            += -DDEBUG
+endif
+
+obj-$(CONFIG_MMC_BLOCK)                += mmc_block.o
+mmc_block-objs                 := block.o queue.o
+
similarity index 93%
rename from drivers/mmc/mmc_block.c
rename to drivers/mmc/card/block.c
index 86439a0..d24ab23 100644 (file)
@@ -2,6 +2,7 @@
  * Block driver for media (i.e., flash cards)
  *
  * Copyright 2002 Hewlett-Packard Company
+ * Copyright 2005-2007 Pierre Ossman
  *
  * Use consistent with the GNU GPL is permitted,
  * provided that this copyright notice is
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
-#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
-#include "mmc_queue.h"
+#include "queue.h"
 
 /*
  * max 8 partitions per card
@@ -223,10 +224,9 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
        struct mmc_blk_data *md = mq->data;
        struct mmc_card *card = md->queue.card;
        struct mmc_blk_request brq;
-       int ret = 1;
+       int ret = 1, sg_pos, data_size;
 
-       if (mmc_card_claim_host(card))
-               goto flush_queue;
+       mmc_claim_host(card->host);
 
        do {
                struct mmc_command cmd;
@@ -283,6 +283,20 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
                brq.data.sg = mq->sg;
                brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg);
 
+               if (brq.data.blocks !=
+                   (req->nr_sectors >> (md->block_bits - 9))) {
+                       data_size = brq.data.blocks * brq.data.blksz;
+                       for (sg_pos = 0; sg_pos < brq.data.sg_len; sg_pos++) {
+                               data_size -= mq->sg[sg_pos].length;
+                               if (data_size <= 0) {
+                                       mq->sg[sg_pos].length += data_size;
+                                       sg_pos++;
+                                       break;
+                               }
+                       }
+                       brq.data.sg_len = sg_pos;
+               }
+
                mmc_wait_for_req(card->host, &brq.mrq);
                if (brq.cmd.error) {
                        printk(KERN_ERR "%s: error %d sending read/write command\n",
@@ -342,7 +356,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
                spin_unlock_irq(&md->lock);
        } while (ret);
 
-       mmc_card_release_host(card);
+       mmc_release_host(card->host);
 
        return 1;
 
@@ -378,9 +392,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
                spin_unlock_irq(&md->lock);
        }
 
-flush_queue:
-
-       mmc_card_release_host(card);
+       mmc_release_host(card->host);
 
        spin_lock_irq(&md->lock);
        while (ret) {
@@ -477,11 +489,20 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
 
        blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits);
 
-       /*
-        * The CSD capacity field is in units of read_blkbits.
-        * set_capacity takes units of 512 bytes.
-        */
-       set_capacity(md->disk, card->csd.capacity << (card->csd.read_blkbits - 9));
+       if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
+               /*
+                * The EXT_CSD sector count is in number or 512 byte
+                * sectors.
+                */
+               set_capacity(md->disk, card->ext_csd.sectors);
+       } else {
+               /*
+                * The CSD capacity field is in units of read_blkbits.
+                * set_capacity takes units of 512 bytes.
+                */
+               set_capacity(md->disk,
+                       card->csd.capacity << (card->csd.read_blkbits - 9));
+       }
        return md;
 
  err_putdisk:
@@ -502,12 +523,12 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
        if (mmc_card_blockaddr(card))
                return 0;
 
-       mmc_card_claim_host(card);
+       mmc_claim_host(card->host);
        cmd.opcode = MMC_SET_BLOCKLEN;
        cmd.arg = 1 << md->block_bits;
        cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
        err = mmc_wait_for_cmd(card->host, &cmd, 5);
-       mmc_card_release_host(card);
+       mmc_release_host(card->host);
 
        if (err) {
                printk(KERN_ERR "%s: unable to set block size to %d: %d\n",
similarity index 96%
rename from drivers/mmc/mmc_queue.c
rename to drivers/mmc/card/queue.c
index c27e426..2e77963 100644 (file)
@@ -1,7 +1,8 @@
 /*
- *  linux/drivers/mmc/mmc_queue.c
+ *  linux/drivers/mmc/queue.c
  *
  *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright 2006-2007 Pierre Ossman
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -14,7 +15,7 @@
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
-#include "mmc_queue.h"
+#include "queue.h"
 
 #define MMC_QUEUE_SUSPENDED    (1 << 0)
 
@@ -179,7 +180,6 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
        blk_cleanup_queue(mq->queue);
        return ret;
 }
-EXPORT_SYMBOL(mmc_init_queue);
 
 void mmc_cleanup_queue(struct mmc_queue *mq)
 {
@@ -191,6 +191,9 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
        q->queuedata = NULL;
        spin_unlock_irqrestore(q->queue_lock, flags);
 
+       /* Make sure the queue isn't suspended, as that will deadlock */
+       mmc_queue_resume(mq);
+
        /* Then terminate our worker thread */
        kthread_stop(mq->thread);
 
@@ -226,7 +229,6 @@ void mmc_queue_suspend(struct mmc_queue *mq)
                down(&mq->thread_sem);
        }
 }
-EXPORT_SYMBOL(mmc_queue_suspend);
 
 /**
  * mmc_queue_resume - resume a previously suspended MMC request queue
@@ -247,4 +249,4 @@ void mmc_queue_resume(struct mmc_queue *mq)
                spin_unlock_irqrestore(q->queue_lock, flags);
        }
 }
-EXPORT_SYMBOL(mmc_queue_resume);
+
diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
new file mode 100644 (file)
index 0000000..94222b9
--- /dev/null
@@ -0,0 +1,17 @@
+#
+# MMC core configuration
+#
+
+config MMC_UNSAFE_RESUME
+       bool "Allow unsafe resume (DANGEROUS)"
+       depends on MMC != n
+       help
+         If you say Y here, the MMC layer will assume that all cards
+         stayed in their respective slots during the suspend. The
+         normal behaviour is to remove them at suspend and
+         redetecting them at resume. Breaking this assumption will
+         in most cases result in data corruption.
+
+         This option is usually just for embedded systems which use
+         a MMC/SD card for rootfs. Most people should say N here.
+
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
new file mode 100644 (file)
index 0000000..1075b02
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile for the kernel mmc core.
+#
+
+ifeq ($(CONFIG_MMC_DEBUG),y)
+       EXTRA_CFLAGS            += -DDEBUG
+endif
+
+obj-$(CONFIG_MMC)              += mmc_core.o
+mmc_core-y                     := core.o sysfs.o mmc.o mmc_ops.o sd.o sd_ops.o
+
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
new file mode 100644 (file)
index 0000000..72c7cf4
--- /dev/null
@@ -0,0 +1,727 @@
+/*
+ *  linux/drivers/mmc/core/core.c
+ *
+ *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
+ *  SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
+ *  Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
+ *  MMCv4 support Copyright (C) 2006 Philip Langdale, 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/pagemap.h>
+#include <linux/err.h>
+#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+
+#include "core.h"
+#include "sysfs.h"
+
+#include "mmc_ops.h"
+#include "sd_ops.h"
+
+extern int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
+extern int mmc_attach_sd(struct mmc_host *host, u32 ocr);
+
+/**
+ *     mmc_request_done - finish processing an MMC request
+ *     @host: MMC host which completed request
+ *     @mrq: MMC request which request
+ *
+ *     MMC drivers should call this function when they have completed
+ *     their processing of a request.
+ */
+void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
+{
+       struct mmc_command *cmd = mrq->cmd;
+       int err = cmd->error;
+
+       pr_debug("%s: req done (CMD%u): %d/%d/%d: %08x %08x %08x %08x\n",
+                mmc_hostname(host), cmd->opcode, err,
+                mrq->data ? mrq->data->error : 0,
+                mrq->stop ? mrq->stop->error : 0,
+                cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
+
+       if (err && cmd->retries) {
+               cmd->retries--;
+               cmd->error = 0;
+               host->ops->request(host, mrq);
+       } else if (mrq->done) {
+               mrq->done(mrq);
+       }
+}
+
+EXPORT_SYMBOL(mmc_request_done);
+
+/**
+ *     mmc_start_request - start a command on a host
+ *     @host: MMC host to start command on
+ *     @mrq: MMC request to start
+ *
+ *     Queue a command on the specified host.  We expect the
+ *     caller to be holding the host lock with interrupts disabled.
+ */
+void
+mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
+{
+#ifdef CONFIG_MMC_DEBUG
+       unsigned int i, sz;
+#endif
+
+       pr_debug("%s: starting CMD%u arg %08x flags %08x\n",
+                mmc_hostname(host), mrq->cmd->opcode,
+                mrq->cmd->arg, mrq->cmd->flags);
+
+       WARN_ON(!host->claimed);
+
+       mrq->cmd->error = 0;
+       mrq->cmd->mrq = mrq;
+       if (mrq->data) {
+               BUG_ON(mrq->data->blksz > host->max_blk_size);
+               BUG_ON(mrq->data->blocks > host->max_blk_count);
+               BUG_ON(mrq->data->blocks * mrq->data->blksz >
+                       host->max_req_size);
+
+#ifdef CONFIG_MMC_DEBUG
+               sz = 0;
+               for (i = 0;i < mrq->data->sg_len;i++)
+                       sz += mrq->data->sg[i].length;
+               BUG_ON(sz != mrq->data->blocks * mrq->data->blksz);
+#endif
+
+               mrq->cmd->data = mrq->data;
+               mrq->data->error = 0;
+               mrq->data->mrq = mrq;
+               if (mrq->stop) {
+                       mrq->data->stop = mrq->stop;
+                       mrq->stop->error = 0;
+                       mrq->stop->mrq = mrq;
+               }
+       }
+       host->ops->request(host, mrq);
+}
+
+EXPORT_SYMBOL(mmc_start_request);
+
+static void mmc_wait_done(struct mmc_request *mrq)
+{
+       complete(mrq->done_data);
+}
+
+int mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
+{
+       DECLARE_COMPLETION_ONSTACK(complete);
+
+       mrq->done_data = &complete;
+       mrq->done = mmc_wait_done;
+
+       mmc_start_request(host, mrq);
+
+       wait_for_completion(&complete);
+
+       return 0;
+}
+
+EXPORT_SYMBOL(mmc_wait_for_req);
+
+/**
+ *     mmc_wait_for_cmd - start a command and wait for completion
+ *     @host: MMC host to start command
+ *     @cmd: MMC command to start
+ *     @retries: maximum number of retries
+ *
+ *     Start a new MMC command for a host, and wait for the command
+ *     to complete.  Return any error that occurred while the command
+ *     was executing.  Do not attempt to parse the response.
+ */
+int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries)
+{
+       struct mmc_request mrq;
+
+       BUG_ON(!host->claimed);
+
+       memset(&mrq, 0, sizeof(struct mmc_request));
+
+       memset(cmd->resp, 0, sizeof(cmd->resp));
+       cmd->retries = retries;
+
+       mrq.cmd = cmd;
+       cmd->data = NULL;
+
+       mmc_wait_for_req(host, &mrq);
+
+       return cmd->error;
+}
+
+EXPORT_SYMBOL(mmc_wait_for_cmd);
+
+/**
+ *     mmc_set_data_timeout - set the timeout for a data command
+ *     @data: data phase for command
+ *     @card: the MMC card associated with the data transfer
+ *     @write: flag to differentiate reads from writes
+ */
+void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card,
+                         int write)
+{
+       unsigned int mult;
+
+       /*
+        * SD cards use a 100 multiplier rather than 10
+        */
+       mult = mmc_card_sd(card) ? 100 : 10;
+
+       /*
+        * Scale up the multiplier (and therefore the timeout) by
+        * the r2w factor for writes.
+        */
+       if (write)
+               mult <<= card->csd.r2w_factor;
+
+       data->timeout_ns = card->csd.tacc_ns * mult;
+       data->timeout_clks = card->csd.tacc_clks * mult;
+
+       /*
+        * SD cards also have an upper limit on the timeout.
+        */
+       if (mmc_card_sd(card)) {
+               unsigned int timeout_us, limit_us;
+
+               timeout_us = data->timeout_ns / 1000;
+               timeout_us += data->timeout_clks * 1000 /
+                       (card->host->ios.clock / 1000);
+
+               if (write)
+                       limit_us = 250000;
+               else
+                       limit_us = 100000;
+
+               /*
+                * SDHC cards always use these fixed values.
+                */
+               if (timeout_us > limit_us || mmc_card_blockaddr(card)) {
+                       data->timeout_ns = limit_us * 1000;
+                       data->timeout_clks = 0;
+               }
+       }
+}
+EXPORT_SYMBOL(mmc_set_data_timeout);
+
+/**
+ *     __mmc_claim_host - exclusively claim a host
+ *     @host: mmc host to claim
+ *     @card: mmc card to claim host for
+ *
+ *     Claim a host for a set of operations.  If a valid card
+ *     is passed and this wasn't the last card selected, select
+ *     the card before returning.
+ *
+ *     Note: you should use mmc_card_claim_host or mmc_claim_host.
+ */
+void mmc_claim_host(struct mmc_host *host)
+{
+       DECLARE_WAITQUEUE(wait, current);
+       unsigned long flags;
+
+       add_wait_queue(&host->wq, &wait);
+       spin_lock_irqsave(&host->lock, flags);
+       while (1) {
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               if (!host->claimed)
+                       break;
+               spin_unlock_irqrestore(&host->lock, flags);
+               schedule();
+               spin_lock_irqsave(&host->lock, flags);
+       }
+       set_current_state(TASK_RUNNING);
+       host->claimed = 1;
+       spin_unlock_irqrestore(&host->lock, flags);
+       remove_wait_queue(&host->wq, &wait);
+}
+
+EXPORT_SYMBOL(mmc_claim_host);
+
+/**
+ *     mmc_release_host - release a host
+ *     @host: mmc host to release
+ *
+ *     Release a MMC host, allowing others to claim the host
+ *     for their operations.
+ */
+void mmc_release_host(struct mmc_host *host)
+{
+       unsigned long flags;
+
+       BUG_ON(!host->claimed);
+
+       spin_lock_irqsave(&host->lock, flags);
+       host->claimed = 0;
+       spin_unlock_irqrestore(&host->lock, flags);
+
+       wake_up(&host->wq);
+}
+
+EXPORT_SYMBOL(mmc_release_host);
+
+/*
+ * Internal function that does the actual ios call to the host driver,
+ * optionally printing some debug output.
+ */
+static inline void mmc_set_ios(struct mmc_host *host)
+{
+       struct mmc_ios *ios = &host->ios;
+
+       pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u "
+               "width %u timing %u\n",
+                mmc_hostname(host), ios->clock, ios->bus_mode,
+                ios->power_mode, ios->chip_select, ios->vdd,
+                ios->bus_width, ios->timing);
+
+       host->ops->set_ios(host, ios);
+}
+
+/*
+ * Control chip select pin on a host.
+ */
+void mmc_set_chip_select(struct mmc_host *host, int mode)
+{
+       host->ios.chip_select = mode;
+       mmc_set_ios(host);
+}
+
+/*
+ * Sets the host clock to the highest possible frequency that
+ * is below "hz".
+ */
+void mmc_set_clock(struct mmc_host *host, unsigned int hz)
+{
+       WARN_ON(hz < host->f_min);
+
+       if (hz > host->f_max)
+               hz = host->f_max;
+
+       host->ios.clock = hz;
+       mmc_set_ios(host);
+}
+
+/*
+ * Change the bus mode (open drain/push-pull) of a host.
+ */
+void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode)
+{
+       host->ios.bus_mode = mode;
+       mmc_set_ios(host);
+}
+
+/*
+ * Change data bus width of a host.
+ */
+void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
+{
+       host->ios.bus_width = width;
+       mmc_set_ios(host);
+}
+
+/*
+ * Mask off any voltages we don't support and select
+ * the lowest voltage
+ */
+u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
+{
+       int bit;
+
+       ocr &= host->ocr_avail;
+
+       bit = ffs(ocr);
+       if (bit) {
+               bit -= 1;
+
+               ocr &= 3 << bit;
+
+               host->ios.vdd = bit;
+               mmc_set_ios(host);
+       } else {
+               ocr = 0;
+       }
+
+       return ocr;
+}
+
+/*
+ * Select timing parameters for host.
+ */
+void mmc_set_timing(struct mmc_host *host, unsigned int timing)
+{
+       host->ios.timing = timing;
+       mmc_set_ios(host);
+}
+
+/*
+ * Allocate a new MMC card
+ */
+struct mmc_card *mmc_alloc_card(struct mmc_host *host)
+{
+       struct mmc_card *card;
+
+       card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
+       if (!card)
+               return ERR_PTR(-ENOMEM);
+
+       mmc_init_card(card, host);
+
+       return card;
+}
+
+/*
+ * Apply power to the MMC stack.  This is a two-stage process.
+ * First, we enable power to the card without the clock running.
+ * We then wait a bit for the power to stabilise.  Finally,
+ * enable the bus drivers and clock to the card.
+ *
+ * We must _NOT_ enable the clock prior to power stablising.
+ *
+ * If a host does all the power sequencing itself, ignore the
+ * initial MMC_POWER_UP stage.
+ */
+static void mmc_power_up(struct mmc_host *host)
+{
+       int bit = fls(host->ocr_avail) - 1;
+
+       host->ios.vdd = bit;
+       host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+       host->ios.chip_select = MMC_CS_DONTCARE;
+       host->ios.power_mode = MMC_POWER_UP;
+       host->ios.bus_width = MMC_BUS_WIDTH_1;
+       host->ios.timing = MMC_TIMING_LEGACY;
+       mmc_set_ios(host);
+
+       mmc_delay(1);
+
+       host->ios.clock = host->f_min;
+       host->ios.power_mode = MMC_POWER_ON;
+       mmc_set_ios(host);
+
+       mmc_delay(2);
+}
+
+static void mmc_power_off(struct mmc_host *host)
+{
+       host->ios.clock = 0;
+       host->ios.vdd = 0;
+       host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+       host->ios.chip_select = MMC_CS_DONTCARE;
+       host->ios.power_mode = MMC_POWER_OFF;
+       host->ios.bus_width = MMC_BUS_WIDTH_1;
+       host->ios.timing = MMC_TIMING_LEGACY;
+       mmc_set_ios(host);
+}
+
+/*
+ * Assign a mmc bus handler to a host. Only one bus handler may control a
+ * host at any given time.
+ */
+void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops)
+{
+       unsigned long flags;
+
+       BUG_ON(!host);
+       BUG_ON(!ops);
+
+       BUG_ON(!host->claimed);
+
+       spin_lock_irqsave(&host->lock, flags);
+
+       BUG_ON(host->bus_ops);
+       BUG_ON(host->bus_refs);
+
+       host->bus_ops = ops;
+       host->bus_refs = 1;
+       host->bus_dead = 0;
+
+       spin_unlock_irqrestore(&host->lock, flags);
+}
+
+/*
+ * Remove the current bus handler from a host. Assumes that there are
+ * no interesting cards left, so the bus is powered down.
+ */
+void mmc_detach_bus(struct mmc_host *host)
+{
+       unsigned long flags;
+
+       BUG_ON(!host);
+
+       BUG_ON(!host->claimed);
+       BUG_ON(!host->bus_ops);
+
+       spin_lock_irqsave(&host->lock, flags);
+
+       host->bus_dead = 1;
+
+       spin_unlock_irqrestore(&host->lock, flags);
+
+       mmc_power_off(host);
+
+       mmc_bus_put(host);
+}
+
+/*
+ * Cleanup when the last reference to the bus operator is dropped.
+ */
+void __mmc_release_bus(struct mmc_host *host)
+{
+       BUG_ON(!host);
+       BUG_ON(host->bus_refs);
+       BUG_ON(!host->bus_dead);
+
+       host->bus_ops = NULL;
+}
+
+/**
+ *     mmc_detect_change - process change of state on a MMC socket
+ *     @host: host which changed state.
+ *     @delay: optional delay to wait before detection (jiffies)
+ *
+ *     All we know is that card(s) have been inserted or removed
+ *     from the socket(s).  We don't know which socket or cards.
+ */
+void mmc_detect_change(struct mmc_host *host, unsigned long delay)
+{
+#ifdef CONFIG_MMC_DEBUG
+       mmc_claim_host(host);
+       BUG_ON(host->removed);
+       mmc_release_host(host);
+#endif
+
+       mmc_schedule_delayed_work(&host->detect, delay);
+}
+
+EXPORT_SYMBOL(mmc_detect_change);
+
+
+static void mmc_rescan(struct work_struct *work)
+{
+       struct mmc_host *host =
+               container_of(work, struct mmc_host, detect.work);
+       u32 ocr;
+       int err;
+
+       mmc_bus_get(host);
+
+       if (host->bus_ops == NULL) {
+               /*
+                * Only we can add a new handler, so it's safe to
+                * release the lock here.
+                */
+               mmc_bus_put(host);
+
+               mmc_claim_host(host);
+
+               mmc_power_up(host);
+               mmc_go_idle(host);
+
+               mmc_send_if_cond(host, host->ocr_avail);
+
+               err = mmc_send_app_op_cond(host, 0, &ocr);
+               if (err == MMC_ERR_NONE) {
+                       if (mmc_attach_sd(host, ocr))
+                               mmc_power_off(host);
+               } else {
+                       /*
+                        * If we fail to detect any SD cards then try
+                        * searching for MMC cards.
+                        */
+                       err = mmc_send_op_cond(host, 0, &ocr);
+                       if (err == MMC_ERR_NONE) {
+                               if (mmc_attach_mmc(host, ocr))
+                                       mmc_power_off(host);
+                       } else {
+                               mmc_power_off(host);
+                               mmc_release_host(host);
+                       }
+               }
+       } else {
+               if (host->bus_ops->detect && !host->bus_dead)
+                       host->bus_ops->detect(host);
+
+               mmc_bus_put(host);
+       }
+}
+
+
+/**
+ *     mmc_alloc_host - initialise the per-host structure.
+ *     @extra: sizeof private data structure
+ *     @dev: pointer to host device model structure
+ *
+ *     Initialise the per-host structure.
+ */
+struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
+{
+       struct mmc_host *host;
+
+       host = mmc_alloc_host_sysfs(extra, dev);
+       if (host) {
+               spin_lock_init(&host->lock);
+               init_waitqueue_head(&host->wq);
+               INIT_DELAYED_WORK(&host->detect, mmc_rescan);
+
+               /*
+                * By default, hosts do not support SGIO or large requests.
+                * They have to set these according to their abilities.
+                */
+               host->max_hw_segs = 1;
+               host->max_phys_segs = 1;
+               host->max_seg_size = PAGE_CACHE_SIZE;
+
+               host->max_req_size = PAGE_CACHE_SIZE;
+               host->max_blk_size = 512;
+               host->max_blk_count = PAGE_CACHE_SIZE / 512;
+       }
+
+       return host;
+}
+
+EXPORT_SYMBOL(mmc_alloc_host);
+
+/**
+ *     mmc_add_host - initialise host hardware
+ *     @host: mmc host
+ */
+int mmc_add_host(struct mmc_host *host)
+{
+       int ret;
+
+       ret = mmc_add_host_sysfs(host);
+       if (ret == 0) {
+               mmc_power_off(host);
+               mmc_detect_change(host, 0);
+       }
+
+       return ret;
+}
+
+EXPORT_SYMBOL(mmc_add_host);
+
+/**
+ *     mmc_remove_host - remove host hardware
+ *     @host: mmc host
+ *
+ *     Unregister and remove all cards associated with this host,
+ *     and power down the MMC bus.
+ */
+void mmc_remove_host(struct mmc_host *host)
+{
+#ifdef CONFIG_MMC_DEBUG
+       mmc_claim_host(host);
+       host->removed = 1;
+       mmc_release_host(host);
+#endif
+
+       mmc_flush_scheduled_work();
+
+       mmc_bus_get(host);
+       if (host->bus_ops && !host->bus_dead) {
+               if (host->bus_ops->remove)
+                       host->bus_ops->remove(host);
+
+               mmc_claim_host(host);
+               mmc_detach_bus(host);
+               mmc_release_host(host);
+       }
+       mmc_bus_put(host);
+
+       BUG_ON(host->card);
+
+       mmc_power_off(host);
+       mmc_remove_host_sysfs(host);
+}
+
+EXPORT_SYMBOL(mmc_remove_host);
+
+/**
+ *     mmc_free_host - free the host structure
+ *     @host: mmc host
+ *
+ *     Free the host once all references to it have been dropped.
+ */
+void mmc_free_host(struct mmc_host *host)
+{
+       mmc_free_host_sysfs(host);
+}
+
+EXPORT_SYMBOL(mmc_free_host);
+
+#ifdef CONFIG_PM
+
+/**
+ *     mmc_suspend_host - suspend a host
+ *     @host: mmc host
+ *     @state: suspend mode (PM_SUSPEND_xxx)
+ */
+int mmc_suspend_host(struct mmc_host *host, pm_message_t state)
+{
+       mmc_flush_scheduled_work();
+
+       mmc_bus_get(host);
+       if (host->bus_ops && !host->bus_dead) {
+               if (host->bus_ops->suspend)
+                       host->bus_ops->suspend(host);
+               if (!host->bus_ops->resume) {
+                       if (host->bus_ops->remove)
+                               host->bus_ops->remove(host);
+
+                       mmc_claim_host(host);
+                       mmc_detach_bus(host);
+                       mmc_release_host(host);
+               }
+       }
+       mmc_bus_put(host);
+
+       mmc_power_off(host);
+
+       return 0;
+}
+
+EXPORT_SYMBOL(mmc_suspend_host);
+
+/**
+ *     mmc_resume_host - resume a previously suspended host
+ *     @host: mmc host
+ */
+int mmc_resume_host(struct mmc_host *host)
+{
+       mmc_bus_get(host);
+       if (host->bus_ops && !host->bus_dead) {
+               mmc_power_up(host);
+               BUG_ON(!host->bus_ops->resume);
+               host->bus_ops->resume(host);
+       }
+       mmc_bus_put(host);
+
+       /*
+        * We add a slight delay here so that resume can progress
+        * in parallel.
+        */
+       mmc_detect_change(host, 1);
+
+       return 0;
+}
+
+EXPORT_SYMBOL(mmc_resume_host);
+
+#endif
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
new file mode 100644 (file)
index 0000000..177264d
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ *  linux/drivers/mmc/core/core.h
+ *
+ *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright 2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _MMC_CORE_CORE_H
+#define _MMC_CORE_CORE_H
+
+#include <linux/delay.h>
+
+#define MMC_CMD_RETRIES        3
+
+struct mmc_bus_ops {
+       void (*remove)(struct mmc_host *);
+       void (*detect)(struct mmc_host *);
+       void (*suspend)(struct mmc_host *);
+       void (*resume)(struct mmc_host *);
+};
+
+void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
+void mmc_detach_bus(struct mmc_host *host);
+
+void __mmc_release_bus(struct mmc_host *host);
+
+static inline void mmc_bus_get(struct mmc_host *host)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&host->lock, flags);
+       host->bus_refs++;
+       spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static inline void mmc_bus_put(struct mmc_host *host)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&host->lock, flags);
+       host->bus_refs--;
+       if ((host->bus_refs == 0) && host->bus_ops)
+               __mmc_release_bus(host);
+       spin_unlock_irqrestore(&host->lock, flags);
+}
+
+void mmc_set_chip_select(struct mmc_host *host, int mode);
+void mmc_set_clock(struct mmc_host *host, unsigned int hz);
+void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode);
+void mmc_set_bus_width(struct mmc_host *host, unsigned int width);
+u32 mmc_select_voltage(struct mmc_host *host, u32 ocr);
+void mmc_set_timing(struct mmc_host *host, unsigned int timing);
+
+struct mmc_card *mmc_alloc_card(struct mmc_host *host);
+
+static inline void mmc_delay(unsigned int ms)
+{
+       if (ms < 1000 / HZ) {
+               cond_resched();
+               mdelay(ms);
+       } else {
+               msleep(ms);
+       }
+}
+
+#endif
+
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
new file mode 100644 (file)
index 0000000..42cc286
--- /dev/null
@@ -0,0 +1,537 @@
+/*
+ *  linux/drivers/mmc/mmc.c
+ *
+ *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
+ *  Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
+ *  MMCv4 support Copyright (C) 2006 Philip Langdale, 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+
+#include "core.h"
+#include "sysfs.h"
+#include "mmc_ops.h"
+
+static const unsigned int tran_exp[] = {
+       10000,          100000,         1000000,        10000000,
+       0,              0,              0,              0
+};
+
+static const unsigned char tran_mant[] = {
+       0,      10,     12,     13,     15,     20,     25,     30,
+       35,     40,     45,     50,     55,     60,     70,     80,
+};
+
+static const unsigned int tacc_exp[] = {
+       1,      10,     100,    1000,   10000,  100000, 1000000, 10000000,
+};
+
+static const unsigned int tacc_mant[] = {
+       0,      10,     12,     13,     15,     20,     25,     30,
+       35,     40,     45,     50,     55,     60,     70,     80,
+};
+
+#define UNSTUFF_BITS(resp,start,size)                                  \
+       ({                                                              \
+               const int __size = size;                                \
+               const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \
+               const int __off = 3 - ((start) / 32);                   \
+               const int __shft = (start) & 31;                        \
+               u32 __res;                                              \
+                                                                       \
+               __res = resp[__off] >> __shft;                          \
+               if (__size + __shft > 32)                               \
+                       __res |= resp[__off-1] << ((32 - __shft) % 32); \
+               __res & __mask;                                         \
+       })
+
+/*
+ * Given the decoded CSD structure, decode the raw CID to our CID structure.
+ */
+static int mmc_decode_cid(struct mmc_card *card)
+{
+       u32 *resp = card->raw_cid;
+
+       /*
+        * The selection of the format here is based upon published
+        * specs from sandisk and from what people have reported.
+        */
+       switch (card->csd.mmca_vsn) {
+       case 0: /* MMC v1.0 - v1.2 */
+       case 1: /* MMC v1.4 */
+               card->cid.manfid        = UNSTUFF_BITS(resp, 104, 24);
+               card->cid.prod_name[0]  = UNSTUFF_BITS(resp, 96, 8);
+               card->cid.prod_name[1]  = UNSTUFF_BITS(resp, 88, 8);
+               card->cid.prod_name[2]  = UNSTUFF_BITS(resp, 80, 8);
+               card->cid.prod_name[3]  = UNSTUFF_BITS(resp, 72, 8);
+               card->cid.prod_name[4]  = UNSTUFF_BITS(resp, 64, 8);
+               card->cid.prod_name[5]  = UNSTUFF_BITS(resp, 56, 8);
+               card->cid.prod_name[6]  = UNSTUFF_BITS(resp, 48, 8);
+               card->cid.hwrev         = UNSTUFF_BITS(resp, 44, 4);
+               card->cid.fwrev         = UNSTUFF_BITS(resp, 40, 4);
+               card->cid.serial        = UNSTUFF_BITS(resp, 16, 24);
+               card->cid.month         = UNSTUFF_BITS(resp, 12, 4);
+               card->cid.year          = UNSTUFF_BITS(resp, 8, 4) + 1997;
+               break;
+
+       case 2: /* MMC v2.0 - v2.2 */
+       case 3: /* MMC v3.1 - v3.3 */
+       case 4: /* MMC v4 */
+               card->cid.manfid        = UNSTUFF_BITS(resp, 120, 8);
+               card->cid.oemid         = UNSTUFF_BITS(resp, 104, 16);
+               card->cid.prod_name[0]  = UNSTUFF_BITS(resp, 96, 8);
+               card->cid.prod_name[1]  = UNSTUFF_BITS(resp, 88, 8);
+               card->cid.prod_name[2]  = UNSTUFF_BITS(resp, 80, 8);
+               card->cid.prod_name[3]  = UNSTUFF_BITS(resp, 72, 8);
+               card->cid.prod_name[4]  = UNSTUFF_BITS(resp, 64, 8);
+               card->cid.prod_name[5]  = UNSTUFF_BITS(resp, 56, 8);
+               card->cid.serial        = UNSTUFF_BITS(resp, 16, 32);
+               card->cid.month         = UNSTUFF_BITS(resp, 12, 4);
+               card->cid.year          = UNSTUFF_BITS(resp, 8, 4) + 1997;
+               break;
+
+       default:
+               printk("%s: card has unknown MMCA version %d\n",
+                       mmc_hostname(card->host), card->csd.mmca_vsn);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*
+ * Given a 128-bit response, decode to our card CSD structure.
+ */
+static int mmc_decode_csd(struct mmc_card *card)
+{
+       struct mmc_csd *csd = &card->csd;
+       unsigned int e, m, csd_struct;
+       u32 *resp = card->raw_csd;
+
+       /*
+        * We only understand CSD structure v1.1 and v1.2.
+        * v1.2 has extra information in bits 15, 11 and 10.
+        */
+       csd_struct = UNSTUFF_BITS(resp, 126, 2);
+       if (csd_struct != 1 && csd_struct != 2) {
+               printk("%s: unrecognised CSD structure version %d\n",
+                       mmc_hostname(card->host), csd_struct);
+               return -EINVAL;
+       }
+
+       csd->mmca_vsn    = UNSTUFF_BITS(resp, 122, 4);
+       m = UNSTUFF_BITS(resp, 115, 4);
+       e = UNSTUFF_BITS(resp, 112, 3);
+       csd->tacc_ns     = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+       csd->tacc_clks   = UNSTUFF_BITS(resp, 104, 8) * 100;
+
+       m = UNSTUFF_BITS(resp, 99, 4);
+       e = UNSTUFF_BITS(resp, 96, 3);
+       csd->max_dtr      = tran_exp[e] * tran_mant[m];
+       csd->cmdclass     = UNSTUFF_BITS(resp, 84, 12);
+
+       e = UNSTUFF_BITS(resp, 47, 3);
+       m = UNSTUFF_BITS(resp, 62, 12);
+       csd->capacity     = (1 + m) << (e + 2);
+
+       csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+       csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
+       csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
+       csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+       csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
+       csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
+       csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
+
+       return 0;
+}
+
+/*
+ * Read and decode extended CSD.
+ */
+static int mmc_read_ext_csd(struct mmc_card *card)
+{
+       int err;
+       u8 *ext_csd;
+
+       BUG_ON(!card);
+
+       err = MMC_ERR_FAILED;
+
+       if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
+               return MMC_ERR_NONE;
+
+       /*
+        * As the ext_csd is so large and mostly unused, we don't store the
+        * raw block in mmc_card.
+        */
+       ext_csd = kmalloc(512, GFP_KERNEL);
+       if (!ext_csd) {
+               printk(KERN_ERR "%s: could not allocate a buffer to "
+                       "receive the ext_csd. mmc v4 cards will be "
+                       "treated as v3.\n", mmc_hostname(card->host));
+               return MMC_ERR_FAILED;
+       }
+
+       err = mmc_send_ext_csd(card, ext_csd);
+       if (err != MMC_ERR_NONE) {
+               /*
+                * High capacity cards should have this "magic" size
+                * stored in their CSD.
+                */
+               if (card->csd.capacity == (4096 * 512)) {
+                       printk(KERN_ERR "%s: unable to read EXT_CSD "
+                               "on a possible high capacity card. "
+                               "Card will be ignored.\n",
+                               mmc_hostname(card->host));
+               } else {
+                       printk(KERN_WARNING "%s: unable to read "
+                               "EXT_CSD, performance might "
+                               "suffer.\n",
+                               mmc_hostname(card->host));
+                       err = MMC_ERR_NONE;
+               }
+               goto out;
+       }
+
+       card->ext_csd.sectors =
+               ext_csd[EXT_CSD_SEC_CNT + 0] << 0 |
+               ext_csd[EXT_CSD_SEC_CNT + 1] << 8 |
+               ext_csd[EXT_CSD_SEC_CNT + 2] << 16 |
+               ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
+       if (card->ext_csd.sectors)
+               mmc_card_set_blockaddr(card);
+
+       switch (ext_csd[EXT_CSD_CARD_TYPE]) {
+       case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
+               card->ext_csd.hs_max_dtr = 52000000;
+               break;
+       case EXT_CSD_CARD_TYPE_26:
+               card->ext_csd.hs_max_dtr = 26000000;
+               break;
+       default:
+               /* MMC v4 spec says this cannot happen */
+               printk(KERN_WARNING "%s: card is mmc v4 but doesn't "
+                       "support any high-speed modes.\n",
+                       mmc_hostname(card->host));
+               goto out;
+       }
+
+out:
+       kfree(ext_csd);
+
+       return err;
+}
+
+/*
+ * Handle the detection and initialisation of a card.
+ *
+ * In the case of a resume, "curcard" will contain the card
+ * we're trying to reinitialise.
+ */
+static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
+       struct mmc_card *oldcard)
+{
+       struct mmc_card *card;
+       int err;
+       u32 cid[4];
+       unsigned int max_dtr;
+
+       BUG_ON(!host);
+       BUG_ON(!host->claimed);
+
+       /*
+        * Since we're changing the OCR value, we seem to
+        * need to tell some cards to go back to the idle
+        * state.  We wait 1ms to give cards time to
+        * respond.
+        */
+       mmc_go_idle(host);
+
+       /* The extra bit indicates that we support high capacity */
+       err = mmc_send_op_cond(host, ocr | (1 << 30), NULL);
+       if (err != MMC_ERR_NONE)
+               goto err;
+
+       /*
+        * Fetch CID from card.
+        */
+       err = mmc_all_send_cid(host, cid);
+       if (err != MMC_ERR_NONE)
+               goto err;
+
+       if (oldcard) {
+               if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0)
+                       goto err;
+
+               card = oldcard;
+       } else {
+               /*
+                * Allocate card structure.
+                */
+               card = mmc_alloc_card(host);
+               if (IS_ERR(card))
+                       goto err;
+
+               card->type = MMC_TYPE_MMC;
+               card->rca = 1;
+               memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
+       }
+
+       /*
+        * Set card RCA.
+        */
+       err = mmc_set_relative_addr(card);
+       if (err != MMC_ERR_NONE)
+               goto free_card;
+
+       mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
+
+       if (!oldcard) {
+               /*
+                * Fetch CSD from card.
+                */
+               err = mmc_send_csd(card, card->raw_csd);
+               if (err != MMC_ERR_NONE)
+                       goto free_card;
+
+               err = mmc_decode_csd(card);
+               if (err < 0)
+                       goto free_card;
+               err = mmc_decode_cid(card);
+               if (err < 0)
+                       goto free_card;
+       }
+
+       /*
+        * Select card, as all following commands rely on that.
+        */
+       err = mmc_select_card(card);
+       if (err != MMC_ERR_NONE)
+               goto free_card;
+
+       if (!oldcard) {
+               /*
+                * Fetch and process extened CSD.
+                */
+               err = mmc_read_ext_csd(card);
+               if (err != MMC_ERR_NONE)
+                       goto free_card;
+       }
+
+       /*
+        * Activate high speed (if supported)
+        */
+       if ((card->ext_csd.hs_max_dtr != 0) &&
+               (host->caps & MMC_CAP_MMC_HIGHSPEED)) {
+               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                       EXT_CSD_HS_TIMING, 1);
+               if (err != MMC_ERR_NONE)
+                       goto free_card;
+
+               mmc_card_set_highspeed(card);
+
+               mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+       }
+
+       /*
+        * Compute bus speed.
+        */
+       max_dtr = (unsigned int)-1;
+
+       if (mmc_card_highspeed(card)) {
+               if (max_dtr > card->ext_csd.hs_max_dtr)
+                       max_dtr = card->ext_csd.hs_max_dtr;
+       } else if (max_dtr > card->csd.max_dtr) {
+               max_dtr = card->csd.max_dtr;
+       }
+
+       mmc_set_clock(host, max_dtr);
+
+       /*
+        * Activate wide bus (if supported).
+        */
+       if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
+               (host->caps & MMC_CAP_4_BIT_DATA)) {
+               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                       EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4);
+               if (err != MMC_ERR_NONE)
+                       goto free_card;
+
+               mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
+       }
+
+       if (!oldcard)
+               host->card = card;
+
+       return MMC_ERR_NONE;
+
+free_card:
+       if (!oldcard)
+               mmc_remove_card(card);
+err:
+
+       return MMC_ERR_FAILED;
+}
+
+/*
+ * Host is being removed. Free up the current card.
+ */
+static void mmc_remove(struct mmc_host *host)
+{
+       BUG_ON(!host);
+       BUG_ON(!host->card);
+
+       mmc_remove_card(host->card);
+       host->card = NULL;
+}
+
+/*
+ * Card detection callback from host.
+ */
+static void mmc_detect(struct mmc_host *host)
+{
+       int err;
+
+       BUG_ON(!host);
+       BUG_ON(!host->card);
+
+       mmc_claim_host(host);
+
+       /*
+        * Just check if our card has been removed.
+        */
+       err = mmc_send_status(host->card, NULL);
+
+       mmc_release_host(host);
+
+       if (err != MMC_ERR_NONE) {
+               mmc_remove_card(host->card);
+               host->card = NULL;
+
+               mmc_claim_host(host);
+               mmc_detach_bus(host);
+               mmc_release_host(host);
+       }
+}
+
+#ifdef CONFIG_MMC_UNSAFE_RESUME
+
+/*
+ * Suspend callback from host.
+ */
+static void mmc_suspend(struct mmc_host *host)
+{
+       BUG_ON(!host);
+       BUG_ON(!host->card);
+
+       mmc_claim_host(host);
+       mmc_deselect_cards(host);
+       host->card->state &= ~MMC_STATE_HIGHSPEED;
+       mmc_release_host(host);
+}
+
+/*
+ * Resume callback from host.
+ *
+ * This function tries to determine if the same card is still present
+ * and, if so, restore all state to it.
+ */
+static void mmc_resume(struct mmc_host *host)
+{
+       int err;
+
+       BUG_ON(!host);
+       BUG_ON(!host->card);
+
+       mmc_claim_host(host);
+
+       err = mmc_sd_init_card(host, host->ocr, host->card);
+       if (err != MMC_ERR_NONE) {
+               mmc_remove_card(host->card);
+               host->card = NULL;
+
+               mmc_detach_bus(host);
+       }
+
+       mmc_release_host(host);
+}
+
+#else
+
+#define mmc_suspend NULL
+#define mmc_resume NULL
+
+#endif
+
+static const struct mmc_bus_ops mmc_ops = {
+       .remove = mmc_remove,
+       .detect = mmc_detect,
+       .suspend = mmc_suspend,
+       .resume = mmc_resume,
+};
+
+/*
+ * Starting point for MMC card init.
+ */
+int mmc_attach_mmc(struct mmc_host *host, u32 ocr)
+{
+       int err;
+
+       BUG_ON(!host);
+       BUG_ON(!host->claimed);
+
+       mmc_attach_bus(host, &mmc_ops);
+
+       /*
+        * Sanity check the voltages that the card claims to
+        * support.
+        */
+       if (ocr & 0x7F) {
+               printk(KERN_WARNING "%s: card claims to support voltages "
+                      "below the defined range. These will be ignored.\n",
+                      mmc_hostname(host));
+               ocr &= ~0x7F;
+       }
+
+       host->ocr = mmc_select_voltage(host, ocr);
+
+       /*
+        * Can we support the voltage of the card?
+        */
+       if (!host->ocr)
+               goto err;
+
+       /*
+        * Detect and init the card.
+        */
+       err = mmc_sd_init_card(host, host->ocr, NULL);
+       if (err != MMC_ERR_NONE)
+               goto err;
+
+       mmc_release_host(host);
+
+       err = mmc_register_card(host->card);
+       if (err)
+               goto reclaim_host;
+
+       return 0;
+
+reclaim_host:
+       mmc_claim_host(host);
+       mmc_remove_card(host->card);
+       host->card = NULL;
+err:
+       mmc_detach_bus(host);
+       mmc_release_host(host);
+
+       return 0;
+}
+
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
new file mode 100644 (file)
index 0000000..7dd720f
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ *  linux/drivers/mmc/mmc_ops.h
+ *
+ *  Copyright 2006-2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+
+#include "core.h"
+#include "mmc_ops.h"
+
+static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
+{
+       int err;
+       struct mmc_command cmd;
+
+       BUG_ON(!host);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = MMC_SELECT_CARD;
+
+       if (card) {
+               cmd.arg = card->rca << 16;
+               cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+       } else {
+               cmd.arg = 0;
+               cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
+       }
+
+       err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_select_card(struct mmc_card *card)
+{
+       BUG_ON(!card);
+
+       return _mmc_select_card(card->host, card);
+}
+
+int mmc_deselect_cards(struct mmc_host *host)
+{
+       return _mmc_select_card(host, NULL);
+}
+
+int mmc_go_idle(struct mmc_host *host)
+{
+       int err;
+       struct mmc_command cmd;
+
+       mmc_set_chip_select(host, MMC_CS_HIGH);
+
+       mmc_delay(1);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = MMC_GO_IDLE_STATE;
+       cmd.arg = 0;
+       cmd.flags = MMC_RSP_NONE | MMC_CMD_BC;
+
+       err = mmc_wait_for_cmd(host, &cmd, 0);
+
+       mmc_delay(1);
+
+       mmc_set_chip_select(host, MMC_CS_DONTCARE);
+
+       mmc_delay(1);
+
+       return err;
+}
+
+int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
+{
+       struct mmc_command cmd;
+       int i, err = 0;
+
+       BUG_ON(!host);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = MMC_SEND_OP_COND;
+       cmd.arg = ocr;
+       cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
+
+       for (i = 100; i; i--) {
+               err = mmc_wait_for_cmd(host, &cmd, 0);
+               if (err != MMC_ERR_NONE)
+                       break;
+
+               if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
+                       break;
+
+               err = MMC_ERR_TIMEOUT;
+
+               mmc_delay(10);
+       }
+
+       if (rocr)
+               *rocr = cmd.resp[0];
+
+       return err;
+}
+
+int mmc_all_send_cid(struct mmc_host *host, u32 *cid)
+{
+       int err;
+       struct mmc_command cmd;
+
+       BUG_ON(!host);
+       BUG_ON(!cid);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = MMC_ALL_SEND_CID;
+       cmd.arg = 0;
+       cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
+
+       err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       memcpy(cid, cmd.resp, sizeof(u32) * 4);
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_set_relative_addr(struct mmc_card *card)
+{
+       int err;
+       struct mmc_command cmd;
+
+       BUG_ON(!card);
+       BUG_ON(!card->host);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = MMC_SET_RELATIVE_ADDR;
+       cmd.arg = card->rca << 16;
+       cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+
+       err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_send_csd(struct mmc_card *card, u32 *csd)
+{
+       int err;
+       struct mmc_command cmd;
+
+       BUG_ON(!card);
+       BUG_ON(!card->host);
+       BUG_ON(!csd);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = MMC_SEND_CSD;
+       cmd.arg = card->rca << 16;
+       cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;
+
+       err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       memcpy(csd, cmd.resp, sizeof(u32) * 4);
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd)
+{
+       struct mmc_request mrq;
+       struct mmc_command cmd;
+       struct mmc_data data;
+       struct scatterlist sg;
+
+       BUG_ON(!card);
+       BUG_ON(!card->host);
+       BUG_ON(!ext_csd);
+
+       memset(&mrq, 0, sizeof(struct mmc_request));
+       memset(&cmd, 0, sizeof(struct mmc_command));
+       memset(&data, 0, sizeof(struct mmc_data));
+
+       mrq.cmd = &cmd;
+       mrq.data = &data;
+
+       cmd.opcode = MMC_SEND_EXT_CSD;
+       cmd.arg = 0;
+       cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+       data.blksz = 512;
+       data.blocks = 1;
+       data.flags = MMC_DATA_READ;
+       data.sg = &sg;
+       data.sg_len = 1;
+
+       sg_init_one(&sg, ext_csd, 512);
+
+       mmc_set_data_timeout(&data, card, 0);
+
+       mmc_wait_for_req(card->host, &mrq);
+
+       if (cmd.error != MMC_ERR_NONE)
+               return cmd.error;
+       if (data.error != MMC_ERR_NONE)
+               return data.error;
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value)
+{
+       int err;
+       struct mmc_command cmd;
+
+       BUG_ON(!card);
+       BUG_ON(!card->host);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = MMC_SWITCH;
+       cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+                 (index << 16) |
+                 (value << 8) |
+                 set;
+       cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+
+       err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_send_status(struct mmc_card *card, u32 *status)
+{
+       int err;
+       struct mmc_command cmd;
+
+       BUG_ON(!card);
+       BUG_ON(!card->host);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = MMC_SEND_STATUS;
+       cmd.arg = card->rca << 16;
+       cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+
+       err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       if (status)
+               *status = cmd.resp[0];
+
+       return MMC_ERR_NONE;
+}
+
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
new file mode 100644 (file)
index 0000000..7a481e8
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  linux/drivers/mmc/mmc_ops.h
+ *
+ *  Copyright 2006-2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#ifndef _MMC_MMC_OPS_H
+#define _MMC_MMC_OPS_H
+
+int mmc_select_card(struct mmc_card *card);
+int mmc_deselect_cards(struct mmc_host *host);
+int mmc_go_idle(struct mmc_host *host);
+int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
+int mmc_all_send_cid(struct mmc_host *host, u32 *cid);
+int mmc_set_relative_addr(struct mmc_card *card);
+int mmc_send_csd(struct mmc_card *card, u32 *csd);
+int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd);
+int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value);
+int mmc_send_status(struct mmc_card *card, u32 *status);
+
+#endif
+
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
new file mode 100644 (file)
index 0000000..c1dfd03
--- /dev/null
@@ -0,0 +1,587 @@
+/*
+ *  linux/drivers/mmc/sd.c
+ *
+ *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
+ *  SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
+ *  Copyright (C) 2005-2007 Pierre Ossman, 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+
+#include "core.h"
+#include "sysfs.h"
+#include "mmc_ops.h"
+#include "sd_ops.h"
+
+#include "core.h"
+
+static const unsigned int tran_exp[] = {
+       10000,          100000,         1000000,        10000000,
+       0,              0,              0,              0
+};
+
+static const unsigned char tran_mant[] = {
+       0,      10,     12,     13,     15,     20,     25,     30,
+       35,     40,     45,     50,     55,     60,     70,     80,
+};
+
+static const unsigned int tacc_exp[] = {
+       1,      10,     100,    1000,   10000,  100000, 1000000, 10000000,
+};
+
+static const unsigned int tacc_mant[] = {
+       0,      10,     12,     13,     15,     20,     25,     30,
+       35,     40,     45,     50,     55,     60,     70,     80,
+};
+
+#define UNSTUFF_BITS(resp,start,size)                                  \
+       ({                                                              \
+               const int __size = size;                                \
+               const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \
+               const int __off = 3 - ((start) / 32);                   \
+               const int __shft = (start) & 31;                        \
+               u32 __res;                                              \
+                                                                       \
+               __res = resp[__off] >> __shft;                          \
+               if (__size + __shft > 32)                               \
+                       __res |= resp[__off-1] << ((32 - __shft) % 32); \
+               __res & __mask;                                         \
+       })
+
+/*
+ * Given the decoded CSD structure, decode the raw CID to our CID structure.
+ */
+static void mmc_decode_cid(struct mmc_card *card)
+{
+       u32 *resp = card->raw_cid;
+
+       memset(&card->cid, 0, sizeof(struct mmc_cid));
+
+       /*
+        * SD doesn't currently have a version field so we will
+        * have to assume we can parse this.
+        */
+       card->cid.manfid                = UNSTUFF_BITS(resp, 120, 8);
+       card->cid.oemid                 = UNSTUFF_BITS(resp, 104, 16);
+       card->cid.prod_name[0]          = UNSTUFF_BITS(resp, 96, 8);
+       card->cid.prod_name[1]          = UNSTUFF_BITS(resp, 88, 8);
+       card->cid.prod_name[2]          = UNSTUFF_BITS(resp, 80, 8);
+       card->cid.prod_name[3]          = UNSTUFF_BITS(resp, 72, 8);
+       card->cid.prod_name[4]          = UNSTUFF_BITS(resp, 64, 8);
+       card->cid.hwrev                 = UNSTUFF_BITS(resp, 60, 4);
+       card->cid.fwrev                 = UNSTUFF_BITS(resp, 56, 4);
+       card->cid.serial                = UNSTUFF_BITS(resp, 24, 32);
+       card->cid.year                  = UNSTUFF_BITS(resp, 12, 8);
+       card->cid.month                 = UNSTUFF_BITS(resp, 8, 4);
+
+       card->cid.year += 2000; /* SD cards year offset */
+}
+
+/*
+ * Given a 128-bit response, decode to our card CSD structure.
+ */
+static int mmc_decode_csd(struct mmc_card *card)
+{
+       struct mmc_csd *csd = &card->csd;
+       unsigned int e, m, csd_struct;
+       u32 *resp = card->raw_csd;
+
+       csd_struct = UNSTUFF_BITS(resp, 126, 2);
+
+       switch (csd_struct) {
+       case 0:
+               m = UNSTUFF_BITS(resp, 115, 4);
+               e = UNSTUFF_BITS(resp, 112, 3);
+               csd->tacc_ns     = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+               csd->tacc_clks   = UNSTUFF_BITS(resp, 104, 8) * 100;
+
+               m = UNSTUFF_BITS(resp, 99, 4);
+               e = UNSTUFF_BITS(resp, 96, 3);
+               csd->max_dtr      = tran_exp[e] * tran_mant[m];
+               csd->cmdclass     = UNSTUFF_BITS(resp, 84, 12);
+
+               e = UNSTUFF_BITS(resp, 47, 3);
+               m = UNSTUFF_BITS(resp, 62, 12);
+               csd->capacity     = (1 + m) << (e + 2);
+
+               csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+               csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
+               csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
+               csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+               csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
+               csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
+               csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
+               break;
+       case 1:
+               /*
+                * This is a block-addressed SDHC card. Most
+                * interesting fields are unused and have fixed
+                * values. To avoid getting tripped by buggy cards,
+                * we assume those fixed values ourselves.
+                */
+               mmc_card_set_blockaddr(card);
+
+               csd->tacc_ns     = 0; /* Unused */
+               csd->tacc_clks   = 0; /* Unused */
+
+               m = UNSTUFF_BITS(resp, 99, 4);
+               e = UNSTUFF_BITS(resp, 96, 3);
+               csd->max_dtr      = tran_exp[e] * tran_mant[m];
+               csd->cmdclass     = UNSTUFF_BITS(resp, 84, 12);
+
+               m = UNSTUFF_BITS(resp, 48, 22);
+               csd->capacity     = (1 + m) << 10;
+
+               csd->read_blkbits = 9;
+               csd->read_partial = 0;
+               csd->write_misalign = 0;
+               csd->read_misalign = 0;
+               csd->r2w_factor = 4; /* Unused */
+               csd->write_blkbits = 9;
+               csd->write_partial = 0;
+               break;
+       default:
+               printk("%s: unrecognised CSD structure version %d\n",
+                       mmc_hostname(card->host), csd_struct);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*
+ * Given a 64-bit response, decode to our card SCR structure.
+ */
+static int mmc_decode_scr(struct mmc_card *card)
+{
+       struct sd_scr *scr = &card->scr;
+       unsigned int scr_struct;
+       u32 resp[4];
+
+       BUG_ON(!mmc_card_sd(card));
+
+       resp[3] = card->raw_scr[1];
+       resp[2] = card->raw_scr[0];
+
+       scr_struct = UNSTUFF_BITS(resp, 60, 4);
+       if (scr_struct != 0) {
+               printk("%s: unrecognised SCR structure version %d\n",
+                       mmc_hostname(card->host), scr_struct);
+               return -EINVAL;
+       }
+
+       scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4);
+       scr->bus_widths = UNSTUFF_BITS(resp, 48, 4);
+
+       return 0;
+}
+
+/*
+ * Fetches and decodes switch information
+ */
+static int mmc_read_switch(struct mmc_card *card)
+{
+       int err;
+       u8 *status;
+
+       err = MMC_ERR_FAILED;
+
+       status = kmalloc(64, GFP_KERNEL);
+       if (!status) {
+               printk("%s: could not allocate a buffer for switch "
+                      "capabilities.\n",
+                       mmc_hostname(card->host));
+               return err;
+       }
+
+       err = mmc_sd_switch(card, 0, 0, 1, status);
+       if (err != MMC_ERR_NONE) {
+               /*
+                * Card not supporting high-speed will ignore the
+                * command.
+                */
+               err = MMC_ERR_NONE;
+               goto out;
+       }
+
+       if (status[13] & 0x02)
+               card->sw_caps.hs_max_dtr = 50000000;
+
+out:
+       kfree(status);
+
+       return err;
+}
+
+/*
+ * Test if the card supports high-speed mode and, if so, switch to it.
+ */
+static int mmc_switch_hs(struct mmc_card *card)
+{
+       int err;
+       u8 *status;
+
+       if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED))
+               return MMC_ERR_NONE;
+
+       if (card->sw_caps.hs_max_dtr == 0)
+               return MMC_ERR_NONE;
+
+       err = MMC_ERR_FAILED;
+
+       status = kmalloc(64, GFP_KERNEL);
+       if (!status) {
+               printk("%s: could not allocate a buffer for switch "
+                      "capabilities.\n",
+                       mmc_hostname(card->host));
+               return err;
+       }
+
+       err = mmc_sd_switch(card, 1, 0, 1, status);
+       if (err != MMC_ERR_NONE)
+               goto out;
+
+       if ((status[16] & 0xF) != 1) {
+               printk(KERN_WARNING "%s: Problem switching card "
+                       "into high-speed mode!\n",
+                       mmc_hostname(card->host));
+       } else {
+               mmc_card_set_highspeed(card);
+               mmc_set_timing(card->host, MMC_TIMING_SD_HS);
+       }
+
+out:
+       kfree(status);
+
+       return err;
+}
+
+/*
+ * Handle the detection and initialisation of a card.
+ *
+ * In the case of a resume, "curcard" will contain the card
+ * we're trying to reinitialise.
+ */
+static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
+       struct mmc_card *oldcard)
+{
+       struct mmc_card *card;
+       int err;
+       u32 cid[4];
+       unsigned int max_dtr;
+
+       BUG_ON(!host);
+       BUG_ON(!host->claimed);
+
+       /*
+        * Since we're changing the OCR value, we seem to
+        * need to tell some cards to go back to the idle
+        * state.  We wait 1ms to give cards time to
+        * respond.
+        */
+       mmc_go_idle(host);
+
+       /*
+        * If SD_SEND_IF_COND indicates an SD 2.0
+        * compliant card and we should set bit 30
+        * of the ocr to indicate that we can handle
+        * block-addressed SDHC cards.
+        */
+       err = mmc_send_if_cond(host, ocr);
+       if (err == MMC_ERR_NONE)
+               ocr |= 1 << 30;
+
+       err = mmc_send_app_op_cond(host, ocr, NULL);
+       if (err != MMC_ERR_NONE)
+               goto err;
+
+       /*
+        * Fetch CID from card.
+        */
+       err = mmc_all_send_cid(host, cid);
+       if (err != MMC_ERR_NONE)
+               goto err;
+
+       if (oldcard) {
+               if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0)
+                       goto err;
+
+               card = oldcard;
+       } else {
+               /*
+                * Allocate card structure.
+                */
+               card = mmc_alloc_card(host);
+               if (IS_ERR(card))
+                       goto err;
+
+               card->type = MMC_TYPE_SD;
+               memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
+       }
+
+       /*
+        * Set card RCA.
+        */
+       err = mmc_send_relative_addr(host, &card->rca);
+       if (err != MMC_ERR_NONE)
+               goto free_card;
+
+       mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
+
+       if (!oldcard) {
+               /*
+                * Fetch CSD from card.
+                */
+               err = mmc_send_csd(card, card->raw_csd);
+               if (err != MMC_ERR_NONE)
+                       goto free_card;
+
+               err = mmc_decode_csd(card);
+               if (err < 0)
+                       goto free_card;
+
+               mmc_decode_cid(card);
+       }
+
+       /*
+        * Select card, as all following commands rely on that.
+        */
+       err = mmc_select_card(card);
+       if (err != MMC_ERR_NONE)
+               goto free_card;
+
+       if (!oldcard) {
+               /*
+                * Fetch SCR from card.
+                */
+               err = mmc_app_send_scr(card, card->raw_scr);
+               if (err != MMC_ERR_NONE)
+                       goto free_card;
+
+               err = mmc_decode_scr(card);
+               if (err < 0)
+                       goto free_card;
+
+               /*
+                * Fetch switch information from card.
+                */
+               err = mmc_read_switch(card);
+               if (err != MMC_ERR_NONE)
+                       goto free_card;
+       }
+
+       /*
+        * Attempt to change to high-speed (if supported)
+        */
+       err = mmc_switch_hs(card);
+       if (err != MMC_ERR_NONE)
+               goto free_card;
+
+       /*
+        * Compute bus speed.
+        */
+       max_dtr = (unsigned int)-1;
+
+       if (mmc_card_highspeed(card)) {
+               if (max_dtr > card->sw_caps.hs_max_dtr)
+                       max_dtr = card->sw_caps.hs_max_dtr;
+       } else if (max_dtr > card->csd.max_dtr) {
+               max_dtr = card->csd.max_dtr;
+       }
+
+       mmc_set_clock(host, max_dtr);
+
+       /*
+        * Switch to wider bus (if supported).
+        */
+       if ((host->caps && MMC_CAP_4_BIT_DATA) &&
+               (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
+               err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4);
+               if (err != MMC_ERR_NONE)
+                       goto free_card;
+
+               mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
+       }
+
+       if (!oldcard)
+               host->card = card;
+
+       return MMC_ERR_NONE;
+
+free_card:
+       if (!oldcard)
+               mmc_remove_card(card);
+err:
+
+       return MMC_ERR_FAILED;
+}
+
+/*
+ * Host is being removed. Free up the current card.
+ */
+static void mmc_sd_remove(struct mmc_host *host)
+{
+       BUG_ON(!host);
+       BUG_ON(!host->card);
+
+       mmc_remove_card(host->card);
+       host->card = NULL;
+}
+
+/*
+ * Card detection callback from host.
+ */
+static void mmc_sd_detect(struct mmc_host *host)
+{
+       int err;
+
+       BUG_ON(!host);
+       BUG_ON(!host->card);
+
+       mmc_claim_host(host);
+
+       /*
+        * Just check if our card has been removed.
+        */
+       err = mmc_send_status(host->card, NULL);
+
+       mmc_release_host(host);
+
+       if (err != MMC_ERR_NONE) {
+               mmc_remove_card(host->card);
+               host->card = NULL;
+
+               mmc_claim_host(host);
+               mmc_detach_bus(host);
+               mmc_release_host(host);
+       }
+}
+
+#ifdef CONFIG_MMC_UNSAFE_RESUME
+
+/*
+ * Suspend callback from host.
+ */
+static void mmc_sd_suspend(struct mmc_host *host)
+{
+       BUG_ON(!host);
+       BUG_ON(!host->card);
+
+       mmc_claim_host(host);
+       mmc_deselect_cards(host);
+       host->card->state &= ~MMC_STATE_HIGHSPEED;
+       mmc_release_host(host);
+}
+
+/*
+ * Resume callback from host.
+ *
+ * This function tries to determine if the same card is still present
+ * and, if so, restore all state to it.
+ */
+static void mmc_sd_resume(struct mmc_host *host)
+{
+       int err;
+
+       BUG_ON(!host);
+       BUG_ON(!host->card);
+
+       mmc_claim_host(host);
+
+       err = mmc_sd_init_card(host, host->ocr, host->card);
+       if (err != MMC_ERR_NONE) {
+               mmc_remove_card(host->card);
+               host->card = NULL;
+
+               mmc_detach_bus(host);
+       }
+
+       mmc_release_host(host);
+}
+
+#else
+
+#define mmc_sd_suspend NULL
+#define mmc_sd_resume NULL
+
+#endif
+
+static const struct mmc_bus_ops mmc_sd_ops = {
+       .remove = mmc_sd_remove,
+       .detect = mmc_sd_detect,
+       .suspend = mmc_sd_suspend,
+       .resume = mmc_sd_resume,
+};
+
+/*
+ * Starting point for SD card init.
+ */
+int mmc_attach_sd(struct mmc_host *host, u32 ocr)
+{
+       int err;
+
+       BUG_ON(!host);
+       BUG_ON(!host->claimed);
+
+       mmc_attach_bus(host, &mmc_sd_ops);
+
+       /*
+        * Sanity check the voltages that the card claims to
+        * support.
+        */
+       if (ocr & 0x7F) {
+               printk(KERN_WARNING "%s: card claims to support voltages "
+                      "below the defined range. These will be ignored.\n",
+                      mmc_hostname(host));
+               ocr &= ~0x7F;
+       }
+
+       if (ocr & MMC_VDD_165_195) {
+               printk(KERN_WARNING "%s: SD card claims to support the "
+                      "incompletely defined 'low voltage range'. This "
+                      "will be ignored.\n", mmc_hostname(host));
+               ocr &= ~MMC_VDD_165_195;
+       }
+
+       host->ocr = mmc_select_voltage(host, ocr);
+
+       /*
+        * Can we support the voltage(s) of the card(s)?
+        */
+       if (!host->ocr)
+               goto err;
+
+       /*
+        * Detect and init the card.
+        */
+       err = mmc_sd_init_card(host, host->ocr, NULL);
+       if (err != MMC_ERR_NONE)
+               goto err;
+
+       mmc_release_host(host);
+
+       err = mmc_register_card(host->card);
+       if (err)
+               goto reclaim_host;
+
+       return 0;
+
+reclaim_host:
+       mmc_claim_host(host);
+       mmc_remove_card(host->card);
+       host->card = NULL;
+err:
+       mmc_detach_bus(host);
+       mmc_release_host(host);
+
+       return 0;
+}
+
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
new file mode 100644 (file)
index 0000000..9697ce5
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ *  linux/drivers/mmc/sd_ops.h
+ *
+ *  Copyright 2006-2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+
+#include "core.h"
+#include "sd_ops.h"
+
+/**
+ *     mmc_wait_for_app_cmd - start an application command and wait for
+                              completion
+ *     @host: MMC host to start command
+ *     @rca: RCA to send MMC_APP_CMD to
+ *     @cmd: MMC command to start
+ *     @retries: maximum number of retries
+ *
+ *     Sends a MMC_APP_CMD, checks the card response, sends the command
+ *     in the parameter and waits for it to complete. Return any error
+ *     that occurred while the command was executing.  Do not attempt to
+ *     parse the response.
+ */
+int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card,
+       struct mmc_command *cmd, int retries)
+{
+       struct mmc_request mrq;
+
+       int i, err;
+
+       BUG_ON(!cmd);
+       BUG_ON(retries < 0);
+
+       err = MMC_ERR_INVALID;
+
+       /*
+        * We have to resend MMC_APP_CMD for each attempt so
+        * we cannot use the retries field in mmc_command.
+        */
+       for (i = 0;i <= retries;i++) {
+               memset(&mrq, 0, sizeof(struct mmc_request));
+
+               err = mmc_app_cmd(host, card);
+               if (err != MMC_ERR_NONE)
+                       continue;
+
+               memset(&mrq, 0, sizeof(struct mmc_request));
+
+               memset(cmd->resp, 0, sizeof(cmd->resp));
+               cmd->retries = 0;
+
+               mrq.cmd = cmd;
+               cmd->data = NULL;
+
+               mmc_wait_for_req(host, &mrq);
+
+               err = cmd->error;
+               if (cmd->error == MMC_ERR_NONE)
+                       break;
+       }
+
+       return err;
+}
+
+EXPORT_SYMBOL(mmc_wait_for_app_cmd);
+
+int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card)
+{
+       int err;
+       struct mmc_command cmd;
+
+       BUG_ON(!host);
+       BUG_ON(card && (card->host != host));
+
+       cmd.opcode = MMC_APP_CMD;
+
+       if (card) {
+               cmd.arg = card->rca << 16;
+               cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+       } else {
+               cmd.arg = 0;
+               cmd.flags = MMC_RSP_R1 | MMC_CMD_BCR;
+       }
+
+       err = mmc_wait_for_cmd(host, &cmd, 0);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       /* Check that card supported application commands */
+       if (!(cmd.resp[0] & R1_APP_CMD))
+               return MMC_ERR_FAILED;
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_app_set_bus_width(struct mmc_card *card, int width)
+{
+       int err;
+       struct mmc_command cmd;
+
+       BUG_ON(!card);
+       BUG_ON(!card->host);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = SD_APP_SET_BUS_WIDTH;
+       cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+
+       switch (width) {
+       case MMC_BUS_WIDTH_1:
+               cmd.arg = SD_BUS_WIDTH_1;
+               break;
+       case MMC_BUS_WIDTH_4:
+               cmd.arg = SD_BUS_WIDTH_4;
+               break;
+       default:
+               return MMC_ERR_INVALID;
+       }
+
+       err = mmc_wait_for_app_cmd(card->host, card, &cmd, MMC_CMD_RETRIES);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
+{
+       struct mmc_command cmd;
+       int i, err = 0;
+
+       BUG_ON(!host);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = SD_APP_OP_COND;
+       cmd.arg = ocr;
+       cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
+
+       for (i = 100; i; i--) {
+               err = mmc_wait_for_app_cmd(host, NULL, &cmd, MMC_CMD_RETRIES);
+               if (err != MMC_ERR_NONE)
+                       break;
+
+               if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
+                       break;
+
+               err = MMC_ERR_TIMEOUT;
+
+               mmc_delay(10);
+       }
+
+       if (rocr)
+               *rocr = cmd.resp[0];
+
+       return err;
+}
+
+int mmc_send_if_cond(struct mmc_host *host, u32 ocr)
+{
+       struct mmc_command cmd;
+       int err;
+       static const u8 test_pattern = 0xAA;
+
+       /*
+        * To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND
+        * before SD_APP_OP_COND. This command will harmlessly fail for
+        * SD 1.0 cards.
+        */
+       cmd.opcode = SD_SEND_IF_COND;
+       cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern;
+       cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR;
+
+       err = mmc_wait_for_cmd(host, &cmd, 0);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       if ((cmd.resp[0] & 0xFF) != test_pattern)
+               return MMC_ERR_FAILED;
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca)
+{
+       int err;
+       struct mmc_command cmd;
+
+       BUG_ON(!host);
+       BUG_ON(!rca);
+
+       memset(&cmd, 0, sizeof(struct mmc_command));
+
+       cmd.opcode = SD_SEND_RELATIVE_ADDR;
+       cmd.arg = 0;
+       cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
+
+       err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       *rca = cmd.resp[0] >> 16;
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_app_send_scr(struct mmc_card *card, u32 *scr)
+{
+       int err;
+       struct mmc_request mrq;
+       struct mmc_command cmd;
+       struct mmc_data data;
+       struct scatterlist sg;
+
+       BUG_ON(!card);
+       BUG_ON(!card->host);
+       BUG_ON(!scr);
+
+       err = mmc_app_cmd(card->host, card);
+       if (err != MMC_ERR_NONE)
+               return err;
+
+       memset(&mrq, 0, sizeof(struct mmc_request));
+       memset(&cmd, 0, sizeof(struct mmc_command));
+       memset(&data, 0, sizeof(struct mmc_data));
+
+       mrq.cmd = &cmd;
+       mrq.data = &data;
+
+       cmd.opcode = SD_APP_SEND_SCR;
+       cmd.arg = 0;
+       cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+       data.blksz = 8;
+       data.blocks = 1;
+       data.flags = MMC_DATA_READ;
+       data.sg = &sg;
+       data.sg_len = 1;
+
+       sg_init_one(&sg, scr, 8);
+
+       mmc_set_data_timeout(&data, card, 0);
+
+       mmc_wait_for_req(card->host, &mrq);
+
+       if (cmd.error != MMC_ERR_NONE)
+               return cmd.error;
+       if (data.error != MMC_ERR_NONE)
+               return data.error;
+
+       scr[0] = ntohl(scr[0]);
+       scr[1] = ntohl(scr[1]);
+
+       return MMC_ERR_NONE;
+}
+
+int mmc_sd_switch(struct mmc_card *card, int mode, int group,
+       u8 value, u8 *resp)
+{
+       struct mmc_request mrq;
+       struct mmc_command cmd;
+       struct mmc_data data;
+       struct scatterlist sg;
+
+       BUG_ON(!card);
+       BUG_ON(!card->host);
+
+       mode = !!mode;
+       value &= 0xF;
+
+       memset(&mrq, 0, sizeof(struct mmc_request));
+       memset(&cmd, 0, sizeof(struct mmc_command));
+       memset(&data, 0, sizeof(struct mmc_data));
+
+       mrq.cmd = &cmd;
+       mrq.data = &data;
+
+       cmd.opcode = SD_SWITCH;
+       cmd.arg = mode << 31 | 0x00FFFFFF;
+       cmd.arg &= ~(0xF << (group * 4));
+       cmd.arg |= value << (group * 4);
+       cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+       data.blksz = 64;
+       data.blocks = 1;
+       data.flags = MMC_DATA_READ;
+       data.sg = &sg;
+       data.sg_len = 1;
+
+       sg_init_one(&sg, resp, 64);
+
+       mmc_set_data_timeout(&data, card, 0);
+
+       mmc_wait_for_req(card->host, &mrq);
+
+       if (cmd.error != MMC_ERR_NONE)
+               return cmd.error;
+       if (data.error != MMC_ERR_NONE)
+               return data.error;
+
+       return MMC_ERR_NONE;
+}
+
diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h
new file mode 100644 (file)
index 0000000..1240fdd
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  linux/drivers/mmc/sd_ops.h
+ *
+ *  Copyright 2006-2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#ifndef _MMC_SD_OPS_H
+#define _MMC_SD_OPS_H
+
+int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card);
+int mmc_app_set_bus_width(struct mmc_card *card, int width);
+int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
+int mmc_send_if_cond(struct mmc_host *host, u32 ocr);
+int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca);
+int mmc_app_send_scr(struct mmc_card *card, u32 *scr);
+int mmc_sd_switch(struct mmc_card *card, int mode, int group,
+       u8 value, u8 *resp);
+
+#endif
+
similarity index 97%
rename from drivers/mmc/mmc_sysfs.c
rename to drivers/mmc/core/sysfs.c
index e0e82d8..843b1fb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/mmc/mmc_sysfs.c
+ *  linux/drivers/mmc/core/sysfs.c
  *
  *  Copyright (C) 2003 Russell King, All Rights Reserved.
  *
@@ -18,7 +18,7 @@
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 
-#include "mmc.h"
+#include "sysfs.h"
 
 #define dev_to_mmc_card(d)     container_of(d, struct mmc_card, dev)
 #define to_mmc_driver(d)       container_of(d, struct mmc_driver, drv)
@@ -72,12 +72,11 @@ static void mmc_release_card(struct device *dev)
 /*
  * This currently matches any MMC driver to any MMC card - drivers
  * themselves make the decision whether to drive this card in their
- * probe method.  However, we force "bad" cards to fail.
+ * probe method.
  */
 static int mmc_bus_match(struct device *dev, struct device_driver *drv)
 {
-       struct mmc_card *card = dev_to_mmc_card(dev);
-       return !mmc_card_bad(card);
+       return 1;
 }
 
 static int
@@ -217,6 +216,8 @@ int mmc_register_card(struct mmc_card *card)
                                device_del(&card->dev);
                }
        }
+       if (ret == 0)
+               mmc_card_set_present(card);
        return ret;
 }
 
similarity index 86%
rename from drivers/mmc/mmc.h
rename to drivers/mmc/core/sysfs.h
index 149affe..80e29b3 100644 (file)
@@ -1,15 +1,16 @@
 /*
- *  linux/drivers/mmc/mmc.h
+ *  linux/drivers/mmc/core/sysfs.h
  *
  *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright 2007 Pierre Ossman
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#ifndef _MMC_H
-#define _MMC_H
-/* core-internal functions */
+#ifndef _MMC_CORE_SYSFS_H
+#define _MMC_CORE_SYSFS_H
+
 void mmc_init_card(struct mmc_card *card, struct mmc_host *host);
 int mmc_register_card(struct mmc_card *card);
 void mmc_remove_card(struct mmc_card *card);
@@ -22,4 +23,5 @@ void mmc_free_host_sysfs(struct mmc_host *host);
 int mmc_schedule_work(struct work_struct *work);
 int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay);
 void mmc_flush_scheduled_work(void);
+
 #endif
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
new file mode 100644 (file)
index 0000000..ed4deab
--- /dev/null
@@ -0,0 +1,103 @@
+#
+# MMC/SD host controller drivers
+#
+
+comment "MMC/SD Host Controller Drivers"
+       depends on MMC
+
+config MMC_ARMMMCI
+       tristate "ARM AMBA Multimedia Card Interface support"
+       depends on ARM_AMBA && MMC
+       help
+         This selects the ARM(R) AMBA(R) PrimeCell Multimedia Card
+         Interface (PL180 and PL181) support.  If you have an ARM(R)
+         platform with a Multimedia Card slot, say Y or M here.
+
+         If unsure, say N.
+
+config MMC_PXA
+       tristate "Intel PXA25x/26x/27x Multimedia Card Interface support"
+       depends on ARCH_PXA && MMC
+       help
+         This selects the Intel(R) PXA(R) Multimedia card Interface.
+         If you have a PXA(R) platform with a Multimedia Card slot,
+         say Y or M here.
+
+         If unsure, say N.
+
+config MMC_SDHCI
+       tristate "Secure Digital Host Controller Interface support  (EXPERIMENTAL)"
+       depends on PCI && MMC && EXPERIMENTAL
+       help
+         This select the generic Secure Digital Host Controller Interface.
+         It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
+         and Toshiba(R). Most controllers found in laptops are of this type.
+         If you have a controller with this interface, say Y or M here.
+
+         If unsure, say N.
+
+config MMC_OMAP
+       tristate "TI OMAP Multimedia Card Interface support"
+       depends on ARCH_OMAP && MMC
+       select TPS65010 if MACH_OMAP_H2
+       help
+         This selects the TI OMAP Multimedia card Interface.
+         If you have an OMAP board with a Multimedia Card slot,
+         say Y or M here.
+
+         If unsure, say N.
+
+config MMC_WBSD
+       tristate "Winbond W83L51xD SD/MMC Card Interface support"
+       depends on MMC && ISA_DMA_API
+       help
+         This selects the Winbond(R) W83L51xD Secure digital and
+          Multimedia card Interface.
+         If you have a machine with a integrated W83L518D or W83L519D
+         SD/MMC card reader, say Y or M here.
+
+         If unsure, say N.
+
+config MMC_AU1X
+       tristate "Alchemy AU1XX0 MMC Card Interface support"
+       depends on MMC && SOC_AU1200
+       help
+         This selects the AMD Alchemy(R) Multimedia card interface.
+         If you have a Alchemy platform with a MMC slot, say Y or M here.
+
+         If unsure, say N.
+
+config MMC_AT91
+       tristate "AT91 SD/MMC Card Interface support"
+       depends on ARCH_AT91 && MMC
+       help
+         This selects the AT91 MCI controller.
+
+         If unsure, say N.
+
+config MMC_IMX
+       tristate "Motorola i.MX Multimedia Card Interface support"
+       depends on ARCH_IMX && MMC
+       help
+         This selects the Motorola i.MX Multimedia card Interface.
+         If you have a i.MX platform with a Multimedia Card slot,
+         say Y or M here.
+
+         If unsure, say N.
+
+config MMC_TIFM_SD
+       tristate "TI Flash Media MMC/SD Interface support  (EXPERIMENTAL)"
+       depends on MMC && EXPERIMENTAL && PCI
+       select TIFM_CORE
+       help
+         Say Y here if you want to be able to access MMC/SD cards with
+         the Texas Instruments(R) Flash Media card reader, found in many
+         laptops.
+         This option 'selects' (turns on, enables) 'TIFM_CORE', but you
+         probably also need appropriate card reader host adapter, such as
+         'Misc devices: TI Flash Media PCI74xx/PCI76xx host adapter support
+         (TIFM_7XX1)'.
+
+          To compile this driver as a module, choose M here: the
+         module will be called tifm_sd.
+
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
new file mode 100644 (file)
index 0000000..6685f64
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# Makefile for MMC/SD host controller drivers
+#
+
+ifeq ($(CONFIG_MMC_DEBUG),y)
+       EXTRA_CFLAGS            += -DDEBUG
+endif
+
+obj-$(CONFIG_MMC_ARMMMCI)      += mmci.o
+obj-$(CONFIG_MMC_PXA)          += pxamci.o
+obj-$(CONFIG_MMC_IMX)          += imxmmc.o
+obj-$(CONFIG_MMC_SDHCI)                += sdhci.o
+obj-$(CONFIG_MMC_WBSD)         += wbsd.o
+obj-$(CONFIG_MMC_AU1X)         += au1xmmc.o
+obj-$(CONFIG_MMC_OMAP)         += omap.o
+obj-$(CONFIG_MMC_AT91)         += at91_mci.o
+obj-$(CONFIG_MMC_TIFM_SD)      += tifm_sd.o
+
similarity index 99%
rename from drivers/mmc/at91_mci.c
rename to drivers/mmc/host/at91_mci.c
index 459f4b4..e37943c 100644 (file)
@@ -67,7 +67,6 @@
 #include <linux/atmel_pdc.h>
 
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
similarity index 99%
rename from drivers/mmc/au1xmmc.c
rename to drivers/mmc/host/au1xmmc.c
index b834be2..b7156a4 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/dma-mapping.h>
 
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 #include <asm/io.h>
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
similarity index 99%
rename from drivers/mmc/imxmmc.c
rename to drivers/mmc/host/imxmmc.c
index 0de5c9e..7ee2045 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
-#include <linux/mmc/protocol.h>
 #include <linux/delay.h>
 
 #include <asm/dma.h>
similarity index 99%
rename from drivers/mmc/mmci.c
rename to drivers/mmc/host/mmci.c
index 5941dd9..d11c2d2 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/err.h>
 #include <linux/highmem.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 #include <linux/amba/bus.h>
 #include <linux/clk.h>
 
similarity index 100%
rename from drivers/mmc/mmci.h
rename to drivers/mmc/host/mmci.h
similarity index 98%
rename from drivers/mmc/omap.c
rename to drivers/mmc/host/omap.c
index 1e96a2f..1914e65 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/spinlock.h>
 #include <linux/timer.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 #include <linux/mmc/card.h>
 #include <linux/clk.h>
 
@@ -605,7 +604,7 @@ static void mmc_omap_switch_handler(struct work_struct *work)
        }
        if (mmc_omap_cover_is_open(host)) {
                if (!complained) {
-                       dev_info(mmc_dev(host->mmc), "cover is open");
+                       dev_info(mmc_dev(host->mmc), "cover is open\n");
                        complained = 1;
                }
                if (mmc_omap_enable_poll)
@@ -937,48 +936,55 @@ static void mmc_omap_power(struct mmc_omap_host *host, int on)
        }
 }
 
-static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+static int mmc_omap_calc_divisor(struct mmc_host *mmc, struct mmc_ios *ios)
 {
        struct mmc_omap_host *host = mmc_priv(mmc);
+       int func_clk_rate = clk_get_rate(host->fclk);
        int dsor;
-       int realclock, i;
-
-       realclock = ios->clock;
 
        if (ios->clock == 0)
-               dsor = 0;
-       else {
-               int func_clk_rate = clk_get_rate(host->fclk);
-
-               dsor = func_clk_rate / realclock;
-               if (dsor < 1)
-                       dsor = 1;
+               return 0;
 
-               if (func_clk_rate / dsor > realclock)
-                       dsor++;
+       dsor = func_clk_rate / ios->clock;
+       if (dsor < 1)
+               dsor = 1;
 
-               if (dsor > 250)
-                       dsor = 250;
+       if (func_clk_rate / dsor > ios->clock)
                dsor++;
 
-               if (ios->bus_width == MMC_BUS_WIDTH_4)
-                       dsor |= 1 << 15;
-       }
+       if (dsor > 250)
+               dsor = 250;
+       dsor++;
+
+       if (ios->bus_width == MMC_BUS_WIDTH_4)
+               dsor |= 1 << 15;
+
+       return dsor;
+}
+
+static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+       struct mmc_omap_host *host = mmc_priv(mmc);
+       int dsor;
+       int i;
+
+       dsor = mmc_omap_calc_divisor(mmc, ios);
+       host->bus_mode = ios->bus_mode;
+       host->hw_bus_mode = host->bus_mode;
 
        switch (ios->power_mode) {
        case MMC_POWER_OFF:
                mmc_omap_power(host, 0);
                break;
        case MMC_POWER_UP:
-       case MMC_POWER_ON:
+               /* Cannot touch dsor yet, just power up MMC */
                mmc_omap_power(host, 1);
+               return;
+       case MMC_POWER_ON:
                dsor |= 1 << 11;
                break;
        }
 
-       host->bus_mode = ios->bus_mode;
-       host->hw_bus_mode = host->bus_mode;
-
        clk_enable(host->fclk);
 
        /* On insanely high arm_per frequencies something sometimes
@@ -987,7 +993,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
         * Writing to the CON register twice seems to do the trick. */
        for (i = 0; i < 2; i++)
                OMAP_MMC_WRITE(host, CON, dsor);
-       if (ios->power_mode == MMC_POWER_UP) {
+       if (ios->power_mode == MMC_POWER_ON) {
                /* Send clock cycles, poll completion */
                OMAP_MMC_WRITE(host, IE, 0);
                OMAP_MMC_WRITE(host, STAT, 0xffff);
similarity index 99%
rename from drivers/mmc/pxamci.c
rename to drivers/mmc/host/pxamci.c
index 9774fc6..a98ff98 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 
 #include <asm/dma.h>
 #include <asm/io.h>
similarity index 97%
rename from drivers/mmc/sdhci.c
rename to drivers/mmc/host/sdhci.c
index d749f08..ff5bf73 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/mmc/sdhci.c - Secure Digital Host Controller Interface driver
  *
- *  Copyright (C) 2005-2006 Pierre Ossman, All Rights Reserved.
+ *  Copyright (C) 2005-2007 Pierre Ossman, 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
@@ -15,7 +15,6 @@
 #include <linux/dma-mapping.h>
 
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 
 #include <asm/scatterlist.h>
 
@@ -247,14 +246,13 @@ static void sdhci_read_block_pio(struct sdhci_host *host)
                        chunk_remain = min(blksize, 4);
                }
 
-               size = min(host->size, host->remain);
-               size = min(size, chunk_remain);
+               size = min(host->remain, chunk_remain);
 
                chunk_remain -= size;
                blksize -= size;
                host->offset += size;
                host->remain -= size;
-               host->size -= size;
+
                while (size) {
                        *buffer = data & 0xFF;
                        buffer++;
@@ -289,14 +287,13 @@ static void sdhci_write_block_pio(struct sdhci_host *host)
        buffer = sdhci_sg_to_buffer(host) + host->offset;
 
        while (blksize) {
-               size = min(host->size, host->remain);
-               size = min(size, chunk_remain);
+               size = min(host->remain, chunk_remain);
 
                chunk_remain -= size;
                blksize -= size;
                host->offset += size;
                host->remain -= size;
-               host->size -= size;
+
                while (size) {
                        data >>= 8;
                        data |= (u32)*buffer << 24;
@@ -325,7 +322,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host)
 
        BUG_ON(!host->data);
 
-       if (host->size == 0)
+       if (host->num_sg == 0)
                return;
 
        if (host->data->flags & MMC_DATA_READ)
@@ -339,10 +336,8 @@ static void sdhci_transfer_pio(struct sdhci_host *host)
                else
                        sdhci_write_block_pio(host);
 
-               if (host->size == 0)
+               if (host->num_sg == 0)
                        break;
-
-               BUG_ON(host->num_sg == 0);
        }
 
        DBG("PIO transfer complete.\n");
@@ -408,8 +403,6 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
 
                writel(sg_dma_address(data->sg), host->ioaddr + SDHCI_DMA_ADDRESS);
        } else {
-               host->size = data->blksz * data->blocks;
-
                host->cur_sg = data->sg;
                host->num_sg = data->sg_len;
 
@@ -473,10 +466,6 @@ static void sdhci_finish_data(struct sdhci_host *host)
                        "though there were blocks left.\n",
                        mmc_hostname(host->mmc));
                data->error = MMC_ERR_FAILED;
-       } else if (host->size != 0) {
-               printk(KERN_ERR "%s: %d bytes were left untransferred.\n",
-                       mmc_hostname(host->mmc), host->size);
-               data->error = MMC_ERR_FAILED;
        }
 
        DBG("Ending data transfer (%d bytes)\n", data->bytes_xfered);
@@ -669,20 +658,16 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
 
        pwr = SDHCI_POWER_ON;
 
-       switch (power) {
-       case MMC_VDD_170:
-       case MMC_VDD_180:
-       case MMC_VDD_190:
+       switch (1 << power) {
+       case MMC_VDD_165_195:
                pwr |= SDHCI_POWER_180;
                break;
-       case MMC_VDD_290:
-       case MMC_VDD_300:
-       case MMC_VDD_310:
+       case MMC_VDD_29_30:
+       case MMC_VDD_30_31:
                pwr |= SDHCI_POWER_300;
                break;
-       case MMC_VDD_320:
-       case MMC_VDD_330:
-       case MMC_VDD_340:
+       case MMC_VDD_32_33:
+       case MMC_VDD_33_34:
                pwr |= SDHCI_POWER_330;
                break;
        default:
@@ -1294,7 +1279,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
        if (caps & SDHCI_CAN_VDD_300)
                mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31;
        if (caps & SDHCI_CAN_VDD_180)
-               mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19;
+               mmc->ocr_avail |= MMC_VDD_165_195;
 
        if (mmc->ocr_avail == 0) {
                printk(KERN_ERR "%s: Hardware doesn't report any "
similarity index 98%
rename from drivers/mmc/sdhci.h
rename to drivers/mmc/host/sdhci.h
index e324f0a..7400f4b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/mmc/sdhci.h - Secure Digital Host Controller Interface driver
  *
- *  Copyright (C) 2005 Pierre Ossman, All Rights Reserved.
+ *  Copyright (C) 2005-2007 Pierre Ossman, 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
@@ -187,8 +187,6 @@ struct sdhci_host {
        int                     offset;         /* Offset into current sg */
        int                     remain;         /* Bytes left in current */
 
-       int                     size;           /* Remaining bytes in transfer */
-
        char                    slot_descr[20]; /* Name for reservations */
 
        int                     irq;            /* Device IRQ */
diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c
new file mode 100644 (file)
index 0000000..7511f96
--- /dev/null
@@ -0,0 +1,1102 @@
+/*
+ *  tifm_sd.c - TI FlashMedia driver
+ *
+ *  Copyright (C) 2006 Alex Dubov <oakad@yahoo.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Special thanks to Brad Campbell for extensive testing of this driver.
+ *
+ */
+
+
+#include <linux/tifm.h>
+#include <linux/mmc/host.h>
+#include <linux/highmem.h>
+#include <linux/scatterlist.h>
+#include <asm/io.h>
+
+#define DRIVER_NAME "tifm_sd"
+#define DRIVER_VERSION "0.8"
+
+static int no_dma = 0;
+static int fixed_timeout = 0;
+module_param(no_dma, bool, 0644);
+module_param(fixed_timeout, bool, 0644);
+
+/* Constants here are mostly from OMAP5912 datasheet */
+#define TIFM_MMCSD_RESET      0x0002
+#define TIFM_MMCSD_CLKMASK    0x03ff
+#define TIFM_MMCSD_POWER      0x0800
+#define TIFM_MMCSD_4BBUS      0x8000
+#define TIFM_MMCSD_RXDE       0x8000   /* rx dma enable */
+#define TIFM_MMCSD_TXDE       0x0080   /* tx dma enable */
+#define TIFM_MMCSD_BUFINT     0x0c00   /* set bits: AE, AF */
+#define TIFM_MMCSD_DPE        0x0020   /* data timeout counted in kilocycles */
+#define TIFM_MMCSD_INAB       0x0080   /* abort / initialize command */
+#define TIFM_MMCSD_READ       0x8000
+
+#define TIFM_MMCSD_ERRMASK    0x01e0   /* set bits: CCRC, CTO, DCRC, DTO */
+#define TIFM_MMCSD_EOC        0x0001   /* end of command phase  */
+#define TIFM_MMCSD_CD         0x0002   /* card detect           */
+#define TIFM_MMCSD_CB         0x0004   /* card enter busy state */
+#define TIFM_MMCSD_BRS        0x0008   /* block received/sent   */
+#define TIFM_MMCSD_EOFB       0x0010   /* card exit busy state  */
+#define TIFM_MMCSD_DTO        0x0020   /* data time-out         */
+#define TIFM_MMCSD_DCRC       0x0040   /* data crc error        */
+#define TIFM_MMCSD_CTO        0x0080   /* command time-out      */
+#define TIFM_MMCSD_CCRC       0x0100   /* command crc error     */
+#define TIFM_MMCSD_AF         0x0400   /* fifo almost full      */
+#define TIFM_MMCSD_AE         0x0800   /* fifo almost empty     */
+#define TIFM_MMCSD_OCRB       0x1000   /* OCR busy              */
+#define TIFM_MMCSD_CIRQ       0x2000   /* card irq (cmd40/sdio) */
+#define TIFM_MMCSD_CERR       0x4000   /* card status error     */
+
+#define TIFM_MMCSD_ODTO       0x0040   /* open drain / extended timeout */
+#define TIFM_MMCSD_CARD_RO    0x0200   /* card is read-only     */
+
+#define TIFM_MMCSD_FIFO_SIZE  0x0020
+
+#define TIFM_MMCSD_RSP_R0     0x0000
+#define TIFM_MMCSD_RSP_R1     0x0100
+#define TIFM_MMCSD_RSP_R2     0x0200
+#define TIFM_MMCSD_RSP_R3     0x0300
+#define TIFM_MMCSD_RSP_R4     0x0400
+#define TIFM_MMCSD_RSP_R5     0x0500
+#define TIFM_MMCSD_RSP_R6     0x0600
+
+#define TIFM_MMCSD_RSP_BUSY   0x0800
+
+#define TIFM_MMCSD_CMD_BC     0x0000
+#define TIFM_MMCSD_CMD_BCR    0x1000
+#define TIFM_MMCSD_CMD_AC     0x2000
+#define TIFM_MMCSD_CMD_ADTC   0x3000
+
+#define TIFM_MMCSD_MAX_BLOCK_SIZE  0x0800UL
+
+enum {
+       CMD_READY    = 0x0001,
+       FIFO_READY   = 0x0002,
+       BRS_READY    = 0x0004,
+       SCMD_ACTIVE  = 0x0008,
+       SCMD_READY   = 0x0010,
+       CARD_BUSY    = 0x0020,
+       DATA_CARRY   = 0x0040
+};
+
+struct tifm_sd {
+       struct tifm_dev       *dev;
+
+       unsigned short        eject:1,
+                             open_drain:1,
+                             no_dma:1;
+       unsigned short        cmd_flags;
+
+       unsigned int          clk_freq;
+       unsigned int          clk_div;
+       unsigned long         timeout_jiffies;
+
+       struct tasklet_struct finish_tasklet;
+       struct timer_list     timer;
+       struct mmc_request    *req;
+
+       int                   sg_len;
+       int                   sg_pos;
+       unsigned int          block_pos;
+       struct scatterlist    bounce_buf;
+       unsigned char         bounce_buf_data[TIFM_MMCSD_MAX_BLOCK_SIZE];
+};
+
+/* for some reason, host won't respond correctly to readw/writew */
+static void tifm_sd_read_fifo(struct tifm_sd *host, struct page *pg,
+                             unsigned int off, unsigned int cnt)
+{
+       struct tifm_dev *sock = host->dev;
+       unsigned char *buf;
+       unsigned int pos = 0, val;
+
+       buf = kmap_atomic(pg, KM_BIO_DST_IRQ) + off;
+       if (host->cmd_flags & DATA_CARRY) {
+               buf[pos++] = host->bounce_buf_data[0];
+               host->cmd_flags &= ~DATA_CARRY;
+       }
+
+       while (pos < cnt) {
+               val = readl(sock->addr + SOCK_MMCSD_DATA);
+               buf[pos++] = val & 0xff;
+               if (pos == cnt) {
+                       host->bounce_buf_data[0] = (val >> 8) & 0xff;
+                       host->cmd_flags |= DATA_CARRY;
+                       break;
+               }
+               buf[pos++] = (val >> 8) & 0xff;
+       }
+       kunmap_atomic(buf - off, KM_BIO_DST_IRQ);
+}
+
+static void tifm_sd_write_fifo(struct tifm_sd *host, struct page *pg,
+                              unsigned int off, unsigned int cnt)
+{
+       struct tifm_dev *sock = host->dev;
+       unsigned char *buf;
+       unsigned int pos = 0, val;
+
+       buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + off;
+       if (host->cmd_flags & DATA_CARRY) {
+               val = host->bounce_buf_data[0] | ((buf[pos++] << 8) & 0xff00);
+               writel(val, sock->addr + SOCK_MMCSD_DATA);
+               host->cmd_flags &= ~DATA_CARRY;
+       }
+
+       while (pos < cnt) {
+               val = buf[pos++];
+               if (pos == cnt) {
+                       host->bounce_buf_data[0] = val & 0xff;
+                       host->cmd_flags |= DATA_CARRY;
+                       break;
+               }
+               val |= (buf[pos++] << 8) & 0xff00;
+               writel(val, sock->addr + SOCK_MMCSD_DATA);
+       }
+       kunmap_atomic(buf - off, KM_BIO_SRC_IRQ);
+}
+
+static void tifm_sd_transfer_data(struct tifm_sd *host)
+{
+       struct mmc_data *r_data = host->req->cmd->data;
+       struct scatterlist *sg = r_data->sg;
+       unsigned int off, cnt, t_size = TIFM_MMCSD_FIFO_SIZE * 2;
+       unsigned int p_off, p_cnt;
+       struct page *pg;
+
+       if (host->sg_pos == host->sg_len)
+               return;
+       while (t_size) {
+               cnt = sg[host->sg_pos].length - host->block_pos;
+               if (!cnt) {
+                       host->block_pos = 0;
+                       host->sg_pos++;
+                       if (host->sg_pos == host->sg_len) {
+                               if ((r_data->flags & MMC_DATA_WRITE)
+                                   && DATA_CARRY)
+                                       writel(host->bounce_buf_data[0],
+                                              host->dev->addr
+                                              + SOCK_MMCSD_DATA);
+
+                               return;
+                       }
+                       cnt = sg[host->sg_pos].length;
+               }
+               off = sg[host->sg_pos].offset + host->block_pos;
+
+               pg = nth_page(sg[host->sg_pos].page, off >> PAGE_SHIFT);
+               p_off = offset_in_page(off);
+               p_cnt = PAGE_SIZE - p_off;
+               p_cnt = min(p_cnt, cnt);
+               p_cnt = min(p_cnt, t_size);
+
+               if (r_data->flags & MMC_DATA_READ)
+                       tifm_sd_read_fifo(host, pg, p_off, p_cnt);
+               else if (r_data->flags & MMC_DATA_WRITE)
+                       tifm_sd_write_fifo(host, pg, p_off, p_cnt);
+
+               t_size -= p_cnt;
+               host->block_pos += p_cnt;
+       }
+}
+
+static void tifm_sd_copy_page(struct page *dst, unsigned int dst_off,
+                             struct page *src, unsigned int src_off,
+                             unsigned int count)
+{
+       unsigned char *src_buf = kmap_atomic(src, KM_BIO_SRC_IRQ) + src_off;
+       unsigned char *dst_buf = kmap_atomic(dst, KM_BIO_DST_IRQ) + dst_off;
+
+       memcpy(dst_buf, src_buf, count);
+
+       kunmap_atomic(dst_buf - dst_off, KM_BIO_DST_IRQ);
+       kunmap_atomic(src_buf - src_off, KM_BIO_SRC_IRQ);
+}
+
+static void tifm_sd_bounce_block(struct tifm_sd *host, struct mmc_data *r_data)
+{
+       struct scatterlist *sg = r_data->sg;
+       unsigned int t_size = r_data->blksz;
+       unsigned int off, cnt;
+       unsigned int p_off, p_cnt;
+       struct page *pg;
+
+       dev_dbg(&host->dev->dev, "bouncing block\n");
+       while (t_size) {
+               cnt = sg[host->sg_pos].length - host->block_pos;
+               if (!cnt) {
+                       host->block_pos = 0;
+                       host->sg_pos++;
+                       if (host->sg_pos == host->sg_len)
+                               return;
+                       cnt = sg[host->sg_pos].length;
+               }
+               off = sg[host->sg_pos].offset + host->block_pos;
+
+               pg = nth_page(sg[host->sg_pos].page, off >> PAGE_SHIFT);
+               p_off = offset_in_page(off);
+               p_cnt = PAGE_SIZE - p_off;
+               p_cnt = min(p_cnt, cnt);
+               p_cnt = min(p_cnt, t_size);
+
+               if (r_data->flags & MMC_DATA_WRITE)
+                       tifm_sd_copy_page(host->bounce_buf.page,
+                                         r_data->blksz - t_size,
+                                         pg, p_off, p_cnt);
+               else if (r_data->flags & MMC_DATA_READ)
+                       tifm_sd_copy_page(pg, p_off, host->bounce_buf.page,
+                                         r_data->blksz - t_size, p_cnt);
+
+               t_size -= p_cnt;
+               host->block_pos += p_cnt;
+       }
+}
+
+static int tifm_sd_set_dma_data(struct tifm_sd *host, struct mmc_data *r_data)
+{
+       struct tifm_dev *sock = host->dev;
+       unsigned int t_size = TIFM_DMA_TSIZE * r_data->blksz;
+       unsigned int dma_len, dma_blk_cnt, dma_off;
+       struct scatterlist *sg = NULL;
+       unsigned long flags;
+
+       if (host->sg_pos == host->sg_len)
+               return 1;
+
+       if (host->cmd_flags & DATA_CARRY) {
+               host->cmd_flags &= ~DATA_CARRY;
+               local_irq_save(flags);
+               tifm_sd_bounce_block(host, r_data);
+               local_irq_restore(flags);
+               if (host->sg_pos == host->sg_len)
+                       return 1;
+       }
+
+       dma_len = sg_dma_len(&r_data->sg[host->sg_pos]) - host->block_pos;
+       if (!dma_len) {
+               host->block_pos = 0;
+               host->sg_pos++;
+               if (host->sg_pos == host->sg_len)
+                       return 1;
+               dma_len = sg_dma_len(&r_data->sg[host->sg_pos]);
+       }
+
+       if (dma_len < t_size) {
+               dma_blk_cnt = dma_len / r_data->blksz;
+               dma_off = host->block_pos;
+               host->block_pos += dma_blk_cnt * r_data->blksz;
+       } else {
+               dma_blk_cnt = TIFM_DMA_TSIZE;
+               dma_off = host->block_pos;
+               host->block_pos += t_size;
+       }
+
+       if (dma_blk_cnt)
+               sg = &r_data->sg[host->sg_pos];
+       else if (dma_len) {
+               if (r_data->flags & MMC_DATA_WRITE) {
+                       local_irq_save(flags);
+                       tifm_sd_bounce_block(host, r_data);
+                       local_irq_restore(flags);
+               } else
+                       host->cmd_flags |= DATA_CARRY;
+
+               sg = &host->bounce_buf;
+               dma_off = 0;
+               dma_blk_cnt = 1;
+       } else
+               return 1;
+
+       dev_dbg(&sock->dev, "setting dma for %d blocks\n", dma_blk_cnt);
+       writel(sg_dma_address(sg) + dma_off, sock->addr + SOCK_DMA_ADDRESS);
+       if (r_data->flags & MMC_DATA_WRITE)
+               writel((dma_blk_cnt << 8) | TIFM_DMA_TX | TIFM_DMA_EN,
+                      sock->addr + SOCK_DMA_CONTROL);
+       else
+               writel((dma_blk_cnt << 8) | TIFM_DMA_EN,
+                      sock->addr + SOCK_DMA_CONTROL);
+
+       return 0;
+}
+
+static unsigned int tifm_sd_op_flags(struct mmc_command *cmd)
+{
+       unsigned int rc = 0;
+
+       switch (mmc_resp_type(cmd)) {
+       case MMC_RSP_NONE:
+               rc |= TIFM_MMCSD_RSP_R0;
+               break;
+       case MMC_RSP_R1B:
+               rc |= TIFM_MMCSD_RSP_BUSY; // deliberate fall-through
+       case MMC_RSP_R1:
+               rc |= TIFM_MMCSD_RSP_R1;
+               break;
+       case MMC_RSP_R2:
+               rc |= TIFM_MMCSD_RSP_R2;
+               break;
+       case MMC_RSP_R3:
+               rc |= TIFM_MMCSD_RSP_R3;
+               break;
+       default:
+               BUG();
+       }
+
+       switch (mmc_cmd_type(cmd)) {
+       case MMC_CMD_BC:
+               rc |= TIFM_MMCSD_CMD_BC;
+               break;
+       case MMC_CMD_BCR:
+               rc |= TIFM_MMCSD_CMD_BCR;
+               break;
+       case MMC_CMD_AC:
+               rc |= TIFM_MMCSD_CMD_AC;
+               break;
+       case MMC_CMD_ADTC:
+               rc |= TIFM_MMCSD_CMD_ADTC;
+               break;
+       default:
+               BUG();
+       }
+       return rc;
+}
+
+static void tifm_sd_exec(struct tifm_sd *host, struct mmc_command *cmd)
+{
+       struct tifm_dev *sock = host->dev;
+       unsigned int cmd_mask = tifm_sd_op_flags(cmd);
+
+       if (host->open_drain)
+               cmd_mask |= TIFM_MMCSD_ODTO;
+
+       if (cmd->data && (cmd->data->flags & MMC_DATA_READ))
+               cmd_mask |= TIFM_MMCSD_READ;
+
+       dev_dbg(&sock->dev, "executing opcode 0x%x, arg: 0x%x, mask: 0x%x\n",
+               cmd->opcode, cmd->arg, cmd_mask);
+
+       writel((cmd->arg >> 16) & 0xffff, sock->addr + SOCK_MMCSD_ARG_HIGH);
+       writel(cmd->arg & 0xffff, sock->addr + SOCK_MMCSD_ARG_LOW);
+       writel(cmd->opcode | cmd_mask, sock->addr + SOCK_MMCSD_COMMAND);
+}
+
+static void tifm_sd_fetch_resp(struct mmc_command *cmd, struct tifm_dev *sock)
+{
+       cmd->resp[0] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x1c) << 16)
+                      | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x18);
+       cmd->resp[1] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x14) << 16)
+                      | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x10);
+       cmd->resp[2] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x0c) << 16)
+                      | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x08);
+       cmd->resp[3] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x04) << 16)
+                      | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x00);
+}
+
+static void tifm_sd_check_status(struct tifm_sd *host)
+{
+       struct tifm_dev *sock = host->dev;
+       struct mmc_command *cmd = host->req->cmd;
+
+       if (cmd->error != MMC_ERR_NONE)
+               goto finish_request;
+
+       if (!(host->cmd_flags & CMD_READY))
+               return;
+
+       if (cmd->data) {
+               if (cmd->data->error != MMC_ERR_NONE) {
+                       if ((host->cmd_flags & SCMD_ACTIVE)
+                           && !(host->cmd_flags & SCMD_READY))
+                               return;
+
+                       goto finish_request;
+               }
+
+               if (!(host->cmd_flags & BRS_READY))
+                       return;
+
+               if (!(host->no_dma || (host->cmd_flags & FIFO_READY)))
+                       return;
+
+               if (cmd->data->flags & MMC_DATA_WRITE) {
+                       if (host->req->stop) {
+                               if (!(host->cmd_flags & SCMD_ACTIVE)) {
+                                       host->cmd_flags |= SCMD_ACTIVE;
+                                       writel(TIFM_MMCSD_EOFB
+                                              | readl(sock->addr
+                                                      + SOCK_MMCSD_INT_ENABLE),
+                                              sock->addr
+                                              + SOCK_MMCSD_INT_ENABLE);
+                                       tifm_sd_exec(host, host->req->stop);
+                                       return;
+                               } else {
+                                       if (!(host->cmd_flags & SCMD_READY)
+                                           || (host->cmd_flags & CARD_BUSY))
+                                               return;
+                                       writel((~TIFM_MMCSD_EOFB)
+                                              & readl(sock->addr
+                                                      + SOCK_MMCSD_INT_ENABLE),
+                                              sock->addr
+                                              + SOCK_MMCSD_INT_ENABLE);
+                               }
+                       } else {
+                               if (host->cmd_flags & CARD_BUSY)
+                                       return;
+                               writel((~TIFM_MMCSD_EOFB)
+                                      & readl(sock->addr
+                                              + SOCK_MMCSD_INT_ENABLE),
+                                      sock->addr + SOCK_MMCSD_INT_ENABLE);
+                       }
+               } else {
+                       if (host->req->stop) {
+                               if (!(host->cmd_flags & SCMD_ACTIVE)) {
+                                       host->cmd_flags |= SCMD_ACTIVE;
+                                       tifm_sd_exec(host, host->req->stop);
+                                       return;
+                               } else {
+                                       if (!(host->cmd_flags & SCMD_READY))
+                                               return;
+                               }
+                       }
+               }
+       }
+finish_request:
+       tasklet_schedule(&host->finish_tasklet);
+}
+
+/* Called from interrupt handler */
+static void tifm_sd_data_event(struct tifm_dev *sock)
+{
+       struct tifm_sd *host;
+       unsigned int fifo_status = 0;
+       struct mmc_data *r_data = NULL;
+
+       spin_lock(&sock->lock);
+       host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock));
+       fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS);
+       dev_dbg(&sock->dev, "data event: fifo_status %x, flags %x\n",
+               fifo_status, host->cmd_flags);
+
+       if (host->req) {
+               r_data = host->req->cmd->data;
+
+               if (r_data && (fifo_status & TIFM_FIFO_READY)) {
+                       if (tifm_sd_set_dma_data(host, r_data)) {
+                               host->cmd_flags |= FIFO_READY;
+                               tifm_sd_check_status(host);
+                       }
+               }
+       }
+
+       writel(fifo_status, sock->addr + SOCK_DMA_FIFO_STATUS);
+       spin_unlock(&sock->lock);
+}
+
+/* Called from interrupt handler */
+static void tifm_sd_card_event(struct tifm_dev *sock)
+{
+       struct tifm_sd *host;
+       unsigned int host_status = 0;
+       int cmd_error = MMC_ERR_NONE;
+       struct mmc_command *cmd = NULL;
+       unsigned long flags;
+
+       spin_lock(&sock->lock);
+       host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock));
+       host_status = readl(sock->addr + SOCK_MMCSD_STATUS);
+       dev_dbg(&sock->dev, "host event: host_status %x, flags %x\n",
+               host_status, host->cmd_flags);
+
+       if (host->req) {
+               cmd = host->req->cmd;
+
+               if (host_status & TIFM_MMCSD_ERRMASK) {
+                       writel(host_status & TIFM_MMCSD_ERRMASK,
+                              sock->addr + SOCK_MMCSD_STATUS);
+                       if (host_status & TIFM_MMCSD_CTO)
+                               cmd_error = MMC_ERR_TIMEOUT;
+                       else if (host_status & TIFM_MMCSD_CCRC)
+                               cmd_error = MMC_ERR_BADCRC;
+
+                       if (cmd->data) {
+                               if (host_status & TIFM_MMCSD_DTO)
+                                       cmd->data->error = MMC_ERR_TIMEOUT;
+                               else if (host_status & TIFM_MMCSD_DCRC)
+                                       cmd->data->error = MMC_ERR_BADCRC;
+                       }
+
+                       writel(TIFM_FIFO_INT_SETALL,
+                              sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
+                       writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
+
+                       if (host->req->stop) {
+                               if (host->cmd_flags & SCMD_ACTIVE) {
+                                       host->req->stop->error = cmd_error;
+                                       host->cmd_flags |= SCMD_READY;
+                               } else {
+                                       cmd->error = cmd_error;
+                                       host->cmd_flags |= SCMD_ACTIVE;
+                                       tifm_sd_exec(host, host->req->stop);
+                                       goto done;
+                               }
+                       } else
+                               cmd->error = cmd_error;
+               } else {
+                       if (host_status & (TIFM_MMCSD_EOC | TIFM_MMCSD_CERR)) {
+                               if (!(host->cmd_flags & CMD_READY)) {
+                                       host->cmd_flags |= CMD_READY;
+                                       tifm_sd_fetch_resp(cmd, sock);
+                               } else if (host->cmd_flags & SCMD_ACTIVE) {
+                                       host->cmd_flags |= SCMD_READY;
+                                       tifm_sd_fetch_resp(host->req->stop,
+                                                          sock);
+                               }
+                       }
+                       if (host_status & TIFM_MMCSD_BRS)
+                               host->cmd_flags |= BRS_READY;
+               }
+
+               if (host->no_dma && cmd->data) {
+                       if (host_status & TIFM_MMCSD_AE)
+                               writel(host_status & TIFM_MMCSD_AE,
+                                      sock->addr + SOCK_MMCSD_STATUS);
+
+                       if (host_status & (TIFM_MMCSD_AE | TIFM_MMCSD_AF
+                                          | TIFM_MMCSD_BRS)) {
+                               local_irq_save(flags);
+                               tifm_sd_transfer_data(host);
+                               local_irq_restore(flags);
+                               host_status &= ~TIFM_MMCSD_AE;
+                       }
+               }
+
+               if (host_status & TIFM_MMCSD_EOFB)
+                       host->cmd_flags &= ~CARD_BUSY;
+               else if (host_status & TIFM_MMCSD_CB)
+                       host->cmd_flags |= CARD_BUSY;
+
+               tifm_sd_check_status(host);
+       }
+done:
+       writel(host_status, sock->addr + SOCK_MMCSD_STATUS);
+       spin_unlock(&sock->lock);
+}
+
+static void tifm_sd_set_data_timeout(struct tifm_sd *host,
+                                    struct mmc_data *data)
+{
+       struct tifm_dev *sock = host->dev;
+       unsigned int data_timeout = data->timeout_clks;
+
+       if (fixed_timeout)
+               return;
+
+       data_timeout += data->timeout_ns /
+                       ((1000000000UL / host->clk_freq) * host->clk_div);
+
+       if (data_timeout < 0xffff) {
+               writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO);
+               writel((~TIFM_MMCSD_DPE)
+                      & readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG),
+                      sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG);
+       } else {
+               data_timeout = (data_timeout >> 10) + 1;
+               if (data_timeout > 0xffff)
+                       data_timeout = 0;       /* set to unlimited */
+               writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO);
+               writel(TIFM_MMCSD_DPE
+                      | readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG),
+                      sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG);
+       }
+}
+
+static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+       struct tifm_sd *host = mmc_priv(mmc);
+       struct tifm_dev *sock = host->dev;
+       unsigned long flags;
+       struct mmc_data *r_data = mrq->cmd->data;
+
+       spin_lock_irqsave(&sock->lock, flags);
+       if (host->eject) {
+               spin_unlock_irqrestore(&sock->lock, flags);
+               goto err_out;
+       }
+
+       if (host->req) {
+               printk(KERN_ERR "%s : unfinished request detected\n",
+                      sock->dev.bus_id);
+               spin_unlock_irqrestore(&sock->lock, flags);
+               goto err_out;
+       }
+
+       host->cmd_flags = 0;
+       host->block_pos = 0;
+       host->sg_pos = 0;
+
+       if (r_data) {
+               tifm_sd_set_data_timeout(host, r_data);
+
+               if ((r_data->flags & MMC_DATA_WRITE) && !mrq->stop)
+                        writel(TIFM_MMCSD_EOFB
+                               | readl(sock->addr + SOCK_MMCSD_INT_ENABLE),
+                               sock->addr + SOCK_MMCSD_INT_ENABLE);
+
+               if (host->no_dma) {
+                       writel(TIFM_MMCSD_BUFINT
+                              | readl(sock->addr + SOCK_MMCSD_INT_ENABLE),
+                              sock->addr + SOCK_MMCSD_INT_ENABLE);
+                       writel(((TIFM_MMCSD_FIFO_SIZE - 1) << 8)
+                              | (TIFM_MMCSD_FIFO_SIZE - 1),
+                              sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
+
+                       host->sg_len = r_data->sg_len;
+               } else {
+                       sg_init_one(&host->bounce_buf, host->bounce_buf_data,
+                                   r_data->blksz);
+
+                       if(1 != tifm_map_sg(sock, &host->bounce_buf, 1,
+                                           r_data->flags & MMC_DATA_WRITE
+                                           ? PCI_DMA_TODEVICE
+                                           : PCI_DMA_FROMDEVICE)) {
+                               printk(KERN_ERR "%s : scatterlist map failed\n",
+                                      sock->dev.bus_id);
+                               spin_unlock_irqrestore(&sock->lock, flags);
+                               goto err_out;
+                       }
+                       host->sg_len = tifm_map_sg(sock, r_data->sg,
+                                                  r_data->sg_len,
+                                                  r_data->flags
+                                                  & MMC_DATA_WRITE
+                                                  ? PCI_DMA_TODEVICE
+                                                  : PCI_DMA_FROMDEVICE);
+                       if (host->sg_len < 1) {
+                               printk(KERN_ERR "%s : scatterlist map failed\n",
+                                      sock->dev.bus_id);
+                               tifm_unmap_sg(sock, &host->bounce_buf, 1,
+                                             r_data->flags & MMC_DATA_WRITE
+                                             ? PCI_DMA_TODEVICE
+                                             : PCI_DMA_FROMDEVICE);
+                               spin_unlock_irqrestore(&sock->lock, flags);
+                               goto err_out;
+                       }
+
+                       writel(TIFM_FIFO_INT_SETALL,
+                              sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
+                       writel(ilog2(r_data->blksz) - 2,
+                              sock->addr + SOCK_FIFO_PAGE_SIZE);
+                       writel(TIFM_FIFO_ENABLE,
+                              sock->addr + SOCK_FIFO_CONTROL);
+                       writel(TIFM_FIFO_INTMASK,
+                              sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
+
+                       if (r_data->flags & MMC_DATA_WRITE)
+                               writel(TIFM_MMCSD_TXDE,
+                                      sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
+                       else
+                               writel(TIFM_MMCSD_RXDE,
+                                      sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
+
+                       tifm_sd_set_dma_data(host, r_data);
+               }
+
+               writel(r_data->blocks - 1,
+                      sock->addr + SOCK_MMCSD_NUM_BLOCKS);
+               writel(r_data->blksz - 1,
+                      sock->addr + SOCK_MMCSD_BLOCK_LEN);
+       }
+
+       host->req = mrq;
+       mod_timer(&host->timer, jiffies + host->timeout_jiffies);
+       writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL),
+              sock->addr + SOCK_CONTROL);
+       tifm_sd_exec(host, mrq->cmd);
+       spin_unlock_irqrestore(&sock->lock, flags);
+       return;
+
+err_out:
+       mrq->cmd->error = MMC_ERR_TIMEOUT;
+       mmc_request_done(mmc, mrq);
+}
+
+static void tifm_sd_end_cmd(unsigned long data)
+{
+       struct tifm_sd *host = (struct tifm_sd*)data;
+       struct tifm_dev *sock = host->dev;
+       struct mmc_host *mmc = tifm_get_drvdata(sock);
+       struct mmc_request *mrq;
+       struct mmc_data *r_data = NULL;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sock->lock, flags);
+
+       del_timer(&host->timer);
+       mrq = host->req;
+       host->req = NULL;
+
+       if (!mrq) {
+               printk(KERN_ERR " %s : no request to complete?\n",
+                      sock->dev.bus_id);
+               spin_unlock_irqrestore(&sock->lock, flags);
+               return;
+       }
+
+       r_data = mrq->cmd->data;
+       if (r_data) {
+               if (host->no_dma) {
+                       writel((~TIFM_MMCSD_BUFINT)
+                              & readl(sock->addr + SOCK_MMCSD_INT_ENABLE),
+                              sock->addr + SOCK_MMCSD_INT_ENABLE);
+               } else {
+                       tifm_unmap_sg(sock, &host->bounce_buf, 1,
+                                     (r_data->flags & MMC_DATA_WRITE)
+                                     ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
+                       tifm_unmap_sg(sock, r_data->sg, r_data->sg_len,
+                                     (r_data->flags & MMC_DATA_WRITE)
+                                     ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
+               }
+
+               r_data->bytes_xfered = r_data->blocks
+                       - readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1;
+               r_data->bytes_xfered *= r_data->blksz;
+               r_data->bytes_xfered += r_data->blksz
+                       - readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1;
+       }
+
+       writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
+              sock->addr + SOCK_CONTROL);
+
+       spin_unlock_irqrestore(&sock->lock, flags);
+       mmc_request_done(mmc, mrq);
+}
+
+static void tifm_sd_abort(unsigned long data)
+{
+       struct tifm_sd *host = (struct tifm_sd*)data;
+
+       printk(KERN_ERR
+              "%s : card failed to respond for a long period of time "
+              "(%x, %x)\n",
+              host->dev->dev.bus_id, host->req->cmd->opcode, host->cmd_flags);
+
+       tifm_eject(host->dev);
+}
+
+static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+       struct tifm_sd *host = mmc_priv(mmc);
+       struct tifm_dev *sock = host->dev;
+       unsigned int clk_div1, clk_div2;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sock->lock, flags);
+
+       dev_dbg(&sock->dev, "ios: clock = %u, vdd = %x, bus_mode = %x, "
+               "chip_select = %x, power_mode = %x, bus_width = %x\n",
+               ios->clock, ios->vdd, ios->bus_mode, ios->chip_select,
+               ios->power_mode, ios->bus_width);
+
+       if (ios->bus_width == MMC_BUS_WIDTH_4) {
+               writel(TIFM_MMCSD_4BBUS | readl(sock->addr + SOCK_MMCSD_CONFIG),
+                      sock->addr + SOCK_MMCSD_CONFIG);
+       } else {
+               writel((~TIFM_MMCSD_4BBUS)
+                      & readl(sock->addr + SOCK_MMCSD_CONFIG),
+                      sock->addr + SOCK_MMCSD_CONFIG);
+       }
+
+       if (ios->clock) {
+               clk_div1 = 20000000 / ios->clock;
+               if (!clk_div1)
+                       clk_div1 = 1;
+
+               clk_div2 = 24000000 / ios->clock;
+               if (!clk_div2)
+                       clk_div2 = 1;
+
+               if ((20000000 / clk_div1) > ios->clock)
+                       clk_div1++;
+               if ((24000000 / clk_div2) > ios->clock)
+                       clk_div2++;
+               if ((20000000 / clk_div1) > (24000000 / clk_div2)) {
+                       host->clk_freq = 20000000;
+                       host->clk_div = clk_div1;
+                       writel((~TIFM_CTRL_FAST_CLK)
+                              & readl(sock->addr + SOCK_CONTROL),
+                              sock->addr + SOCK_CONTROL);
+               } else {
+                       host->clk_freq = 24000000;
+                       host->clk_div = clk_div2;
+                       writel(TIFM_CTRL_FAST_CLK
+                              | readl(sock->addr + SOCK_CONTROL),
+                              sock->addr + SOCK_CONTROL);
+               }
+       } else {
+               host->clk_div = 0;
+       }
+       host->clk_div &= TIFM_MMCSD_CLKMASK;
+       writel(host->clk_div
+              | ((~TIFM_MMCSD_CLKMASK)
+                 & readl(sock->addr + SOCK_MMCSD_CONFIG)),
+              sock->addr + SOCK_MMCSD_CONFIG);
+
+       host->open_drain = (ios->bus_mode == MMC_BUSMODE_OPENDRAIN);
+
+       /* chip_select : maybe later */
+       //vdd
+       //power is set before probe / after remove
+
+       spin_unlock_irqrestore(&sock->lock, flags);
+}
+
+static int tifm_sd_ro(struct mmc_host *mmc)
+{
+       int rc = 0;
+       struct tifm_sd *host = mmc_priv(mmc);
+       struct tifm_dev *sock = host->dev;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sock->lock, flags);
+       if (TIFM_MMCSD_CARD_RO & readl(sock->addr + SOCK_PRESENT_STATE))
+               rc = 1;
+       spin_unlock_irqrestore(&sock->lock, flags);
+       return rc;
+}
+
+static const struct mmc_host_ops tifm_sd_ops = {
+       .request = tifm_sd_request,
+       .set_ios = tifm_sd_ios,
+       .get_ro  = tifm_sd_ro
+};
+
+static int tifm_sd_initialize_host(struct tifm_sd *host)
+{
+       int rc;
+       unsigned int host_status = 0;
+       struct tifm_dev *sock = host->dev;
+
+       writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
+       mmiowb();
+       host->clk_div = 61;
+       host->clk_freq = 20000000;
+       writel(TIFM_MMCSD_RESET, sock->addr + SOCK_MMCSD_SYSTEM_CONTROL);
+       writel(host->clk_div | TIFM_MMCSD_POWER,
+              sock->addr + SOCK_MMCSD_CONFIG);
+
+       /* wait up to 0.51 sec for reset */
+       for (rc = 32; rc <= 256; rc <<= 1) {
+               if (1 & readl(sock->addr + SOCK_MMCSD_SYSTEM_STATUS)) {
+                       rc = 0;
+                       break;
+               }
+               msleep(rc);
+       }
+
+       if (rc) {
+               printk(KERN_ERR "%s : controller failed to reset\n",
+                      sock->dev.bus_id);
+               return -ENODEV;
+       }
+
+       writel(0, sock->addr + SOCK_MMCSD_NUM_BLOCKS);
+       writel(host->clk_div | TIFM_MMCSD_POWER,
+              sock->addr + SOCK_MMCSD_CONFIG);
+       writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
+
+       // command timeout fixed to 64 clocks for now
+       writel(64, sock->addr + SOCK_MMCSD_COMMAND_TO);
+       writel(TIFM_MMCSD_INAB, sock->addr + SOCK_MMCSD_COMMAND);
+
+       for (rc = 16; rc <= 64; rc <<= 1) {
+               host_status = readl(sock->addr + SOCK_MMCSD_STATUS);
+               writel(host_status, sock->addr + SOCK_MMCSD_STATUS);
+               if (!(host_status & TIFM_MMCSD_ERRMASK)
+                   && (host_status & TIFM_MMCSD_EOC)) {
+                       rc = 0;
+                       break;
+               }
+               msleep(rc);
+       }
+
+       if (rc) {
+               printk(KERN_ERR
+                      "%s : card not ready - probe failed on initialization\n",
+                      sock->dev.bus_id);
+               return -ENODEV;
+       }
+
+       writel(TIFM_MMCSD_CERR | TIFM_MMCSD_BRS | TIFM_MMCSD_EOC
+              | TIFM_MMCSD_ERRMASK,
+              sock->addr + SOCK_MMCSD_INT_ENABLE);
+       mmiowb();
+
+       return 0;
+}
+
+static int tifm_sd_probe(struct tifm_dev *sock)
+{
+       struct mmc_host *mmc;
+       struct tifm_sd *host;
+       int rc = -EIO;
+
+       if (!(TIFM_SOCK_STATE_OCCUPIED
+             & readl(sock->addr + SOCK_PRESENT_STATE))) {
+               printk(KERN_WARNING "%s : card gone, unexpectedly\n",
+                      sock->dev.bus_id);
+               return rc;
+       }
+
+       mmc = mmc_alloc_host(sizeof(struct tifm_sd), &sock->dev);
+       if (!mmc)
+               return -ENOMEM;
+
+       host = mmc_priv(mmc);
+       host->no_dma = no_dma;
+       tifm_set_drvdata(sock, mmc);
+       host->dev = sock;
+       host->timeout_jiffies = msecs_to_jiffies(1000);
+
+       tasklet_init(&host->finish_tasklet, tifm_sd_end_cmd,
+                    (unsigned long)host);
+       setup_timer(&host->timer, tifm_sd_abort, (unsigned long)host);
+
+       mmc->ops = &tifm_sd_ops;
+       mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+       mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE;
+       mmc->f_min = 20000000 / 60;
+       mmc->f_max = 24000000;
+
+       mmc->max_blk_count = 2048;
+       mmc->max_hw_segs = mmc->max_blk_count;
+       mmc->max_blk_size = min(TIFM_MMCSD_MAX_BLOCK_SIZE, PAGE_SIZE);
+       mmc->max_seg_size = mmc->max_blk_count * mmc->max_blk_size;
+       mmc->max_req_size = mmc->max_seg_size;
+       mmc->max_phys_segs = mmc->max_hw_segs;
+
+       sock->card_event = tifm_sd_card_event;
+       sock->data_event = tifm_sd_data_event;
+       rc = tifm_sd_initialize_host(host);
+
+       if (!rc)
+               rc = mmc_add_host(mmc);
+       if (!rc)
+               return 0;
+
+       mmc_free_host(mmc);
+       return rc;
+}
+
+static void tifm_sd_remove(struct tifm_dev *sock)
+{
+       struct mmc_host *mmc = tifm_get_drvdata(sock);
+       struct tifm_sd *host = mmc_priv(mmc);
+       unsigned long flags;
+
+       spin_lock_irqsave(&sock->lock, flags);
+       host->eject = 1;
+       writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
+       mmiowb();
+       spin_unlock_irqrestore(&sock->lock, flags);
+
+       tasklet_kill(&host->finish_tasklet);
+
+       spin_lock_irqsave(&sock->lock, flags);
+       if (host->req) {
+               writel(TIFM_FIFO_INT_SETALL,
+                      sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
+               writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
+               host->req->cmd->error = MMC_ERR_TIMEOUT;
+               if (host->req->stop)
+                       host->req->stop->error = MMC_ERR_TIMEOUT;
+               tasklet_schedule(&host->finish_tasklet);
+       }
+       spin_unlock_irqrestore(&sock->lock, flags);
+       mmc_remove_host(mmc);
+       dev_dbg(&sock->dev, "after remove\n");
+
+       /* The meaning of the bit majority in this constant is unknown. */
+       writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
+              sock->addr + SOCK_CONTROL);
+
+       mmc_free_host(mmc);
+}
+
+#ifdef CONFIG_PM
+
+static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state)
+{
+       struct mmc_host *mmc = tifm_get_drvdata(sock);
+       int rc;
+
+       rc = mmc_suspend_host(mmc, state);
+       /* The meaning of the bit majority in this constant is unknown. */
+       writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
+              sock->addr + SOCK_CONTROL);
+       return rc;
+}
+
+static int tifm_sd_resume(struct tifm_dev *sock)
+{
+       struct mmc_host *mmc = tifm_get_drvdata(sock);
+       struct tifm_sd *host = mmc_priv(mmc);
+       int rc;
+
+       rc = tifm_sd_initialize_host(host);
+       dev_dbg(&sock->dev, "resume initialize %d\n", rc);
+
+       if (rc)
+               host->eject = 1;
+       else
+               rc = mmc_resume_host(mmc);
+
+       return rc;
+}
+
+#else
+
+#define tifm_sd_suspend NULL
+#define tifm_sd_resume NULL
+
+#endif /* CONFIG_PM */
+
+static struct tifm_device_id tifm_sd_id_tbl[] = {
+       { TIFM_TYPE_SD }, { }
+};
+
+static struct tifm_driver tifm_sd_driver = {
+       .driver = {
+               .name  = DRIVER_NAME,
+               .owner = THIS_MODULE
+       },
+       .id_table = tifm_sd_id_tbl,
+       .probe    = tifm_sd_probe,
+       .remove   = tifm_sd_remove,
+       .suspend  = tifm_sd_suspend,
+       .resume   = tifm_sd_resume
+};
+
+static int __init tifm_sd_init(void)
+{
+       return tifm_register_driver(&tifm_sd_driver);
+}
+
+static void __exit tifm_sd_exit(void)
+{
+       tifm_unregister_driver(&tifm_sd_driver);
+}
+
+MODULE_AUTHOR("Alex Dubov");
+MODULE_DESCRIPTION("TI FlashMedia SD driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(tifm, tifm_sd_id_tbl);
+MODULE_VERSION(DRIVER_VERSION);
+
+module_init(tifm_sd_init);
+module_exit(tifm_sd_exit);
similarity index 93%
rename from drivers/mmc/wbsd.c
rename to drivers/mmc/host/wbsd.c
index 05ccfc4..867ca6a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/mmc/wbsd.c - Winbond W83L51xD SD/MMC driver
  *
- *  Copyright (C) 2004-2006 Pierre Ossman, All Rights Reserved.
+ *  Copyright (C) 2004-2007 Pierre Ossman, 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
@@ -33,7 +33,6 @@
 #include <linux/pnp.h>
 #include <linux/highmem.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -178,9 +177,8 @@ static void wbsd_init_device(struct wbsd_host *host)
        ier = 0;
        ier |= WBSD_EINT_CARD;
        ier |= WBSD_EINT_FIFO_THRE;
-       ier |= WBSD_EINT_CCRC;
-       ier |= WBSD_EINT_TIMEOUT;
        ier |= WBSD_EINT_CRC;
+       ier |= WBSD_EINT_TIMEOUT;
        ier |= WBSD_EINT_TC;
 
        outb(ier, host->base + WBSD_EIR);
@@ -278,90 +276,36 @@ static inline char *wbsd_sg_to_buffer(struct wbsd_host *host)
 
 static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data)
 {
-       unsigned int len, i, size;
+       unsigned int len, i;
        struct scatterlist *sg;
        char *dmabuf = host->dma_buffer;
        char *sgbuf;
 
-       size = host->size;
-
        sg = data->sg;
        len = data->sg_len;
 
-       /*
-        * Just loop through all entries. Size might not
-        * be the entire list though so make sure that
-        * we do not transfer too much.
-        */
        for (i = 0; i < len; i++) {
                sgbuf = page_address(sg[i].page) + sg[i].offset;
-               if (size < sg[i].length)
-                       memcpy(dmabuf, sgbuf, size);
-               else
-                       memcpy(dmabuf, sgbuf, sg[i].length);
+               memcpy(dmabuf, sgbuf, sg[i].length);
                dmabuf += sg[i].length;
-
-               if (size < sg[i].length)
-                       size = 0;
-               else
-                       size -= sg[i].length;
-
-               if (size == 0)
-                       break;
        }
-
-       /*
-        * Check that we didn't get a request to transfer
-        * more data than can fit into the SG list.
-        */
-
-       BUG_ON(size != 0);
-
-       host->size -= size;
 }
 
 static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data)
 {
-       unsigned int len, i, size;
+       unsigned int len, i;
        struct scatterlist *sg;
        char *dmabuf = host->dma_buffer;
        char *sgbuf;
 
-       size = host->size;
-
        sg = data->sg;
        len = data->sg_len;
 
-       /*
-        * Just loop through all entries. Size might not
-        * be the entire list though so make sure that
-        * we do not transfer too much.
-        */
        for (i = 0; i < len; i++) {
                sgbuf = page_address(sg[i].page) + sg[i].offset;
-               if (size < sg[i].length)
-                       memcpy(sgbuf, dmabuf, size);
-               else
-                       memcpy(sgbuf, dmabuf, sg[i].length);
+               memcpy(sgbuf, dmabuf, sg[i].length);
                dmabuf += sg[i].length;
-
-               if (size < sg[i].length)
-                       size = 0;
-               else
-                       size -= sg[i].length;
-
-               if (size == 0)
-                       break;
        }
-
-       /*
-        * Check that we didn't get a request to transfer
-        * more data than can fit into the SG list.
-        */
-
-       BUG_ON(size != 0);
-
-       host->size -= size;
 }
 
 /*
@@ -484,7 +428,7 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
        /*
         * Handle excessive data.
         */
-       if (data->bytes_xfered == host->size)
+       if (host->num_sg == 0)
                return;
 
        buffer = wbsd_sg_to_buffer(host) + host->offset;
@@ -514,31 +458,14 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
                        data->bytes_xfered++;
 
                        /*
-                        * Transfer done?
-                        */
-                       if (data->bytes_xfered == host->size)
-                               return;
-
-                       /*
                         * End of scatter list entry?
                         */
                        if (host->remain == 0) {
                                /*
                                 * Get next entry. Check if last.
                                 */
-                               if (!wbsd_next_sg(host)) {
-                                       /*
-                                        * We should never reach this point.
-                                        * It means that we're trying to
-                                        * transfer more blocks than can fit
-                                        * into the scatter list.
-                                        */
-                                       BUG_ON(1);
-
-                                       host->size = data->bytes_xfered;
-
+                               if (!wbsd_next_sg(host))
                                        return;
-                               }
 
                                buffer = wbsd_sg_to_buffer(host);
                        }
@@ -550,7 +477,7 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
         * hardware problem. The chip doesn't trigger
         * FIFO threshold interrupts properly.
         */
-       if ((host->size - data->bytes_xfered) < 16)
+       if ((data->blocks * data->blksz - data->bytes_xfered) < 16)
                tasklet_schedule(&host->fifo_tasklet);
 }
 
@@ -564,7 +491,7 @@ static void wbsd_fill_fifo(struct wbsd_host *host)
         * Check that we aren't being called after the
         * entire buffer has been transfered.
         */
-       if (data->bytes_xfered == host->size)
+       if (host->num_sg == 0)
                return;
 
        buffer = wbsd_sg_to_buffer(host) + host->offset;
@@ -594,31 +521,14 @@ static void wbsd_fill_fifo(struct wbsd_host *host)
                        data->bytes_xfered++;
 
                        /*
-                        * Transfer done?
-                        */
-                       if (data->bytes_xfered == host->size)
-                               return;
-
-                       /*
                         * End of scatter list entry?
                         */
                        if (host->remain == 0) {
                                /*
                                 * Get next entry. Check if last.
                                 */
-                               if (!wbsd_next_sg(host)) {
-                                       /*
-                                        * We should never reach this point.
-                                        * It means that we're trying to
-                                        * transfer more blocks than can fit
-                                        * into the scatter list.
-                                        */
-                                       BUG_ON(1);
-
-                                       host->size = data->bytes_xfered;
-
+                               if (!wbsd_next_sg(host))
                                        return;
-                               }
 
                                buffer = wbsd_sg_to_buffer(host);
                        }
@@ -638,6 +548,7 @@ static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data)
        u16 blksize;
        u8 setup;
        unsigned long dmaflags;
+       unsigned int size;
 
        DBGF("blksz %04x blks %04x flags %08x\n",
                data->blksz, data->blocks, data->flags);
@@ -647,7 +558,7 @@ static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data)
        /*
         * Calculate size.
         */
-       host->size = data->blocks * data->blksz;
+       size = data->blocks * data->blksz;
 
        /*
         * Check timeout values for overflow.
@@ -705,8 +616,8 @@ static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data)
                /*
                 * The buffer for DMA is only 64 kB.
                 */
-               BUG_ON(host->size > 0x10000);
-               if (host->size > 0x10000) {
+               BUG_ON(size > 0x10000);
+               if (size > 0x10000) {
                        data->error = MMC_ERR_INVALID;
                        return;
                }
@@ -729,7 +640,7 @@ static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data)
                else
                        set_dma_mode(host->dma, DMA_MODE_WRITE & ~0x40);
                set_dma_addr(host->dma, host->dma_addr);
-               set_dma_count(host->dma, host->size);
+               set_dma_count(host->dma, size);
 
                enable_dma(host->dma);
                release_dma_lock(dmaflags);
@@ -812,6 +723,10 @@ static void wbsd_finish_data(struct wbsd_host *host, struct mmc_data *data)
                count = get_dma_residue(host->dma);
                release_dma_lock(dmaflags);
 
+               data->bytes_xfered = host->mrq->data->blocks *
+                       host->mrq->data->blksz - count;
+               data->bytes_xfered -= data->bytes_xfered % data->blksz;
+
                /*
                 * Any leftover data?
                 */
@@ -820,7 +735,8 @@ static void wbsd_finish_data(struct wbsd_host *host, struct mmc_data *data)
                                "%d bytes left.\n",
                                mmc_hostname(host->mmc), count);
 
-                       data->error = MMC_ERR_FAILED;
+                       if (data->error == MMC_ERR_NONE)
+                               data->error = MMC_ERR_FAILED;
                } else {
                        /*
                         * Transfer data from DMA buffer to
@@ -828,8 +744,11 @@ static void wbsd_finish_data(struct wbsd_host *host, struct mmc_data *data)
                         */
                        if (data->flags & MMC_DATA_READ)
                                wbsd_dma_to_sg(host, data);
+               }
 
-                       data->bytes_xfered = host->size;
+               if (data->error != MMC_ERR_NONE) {
+                       if (data->bytes_xfered)
+                               data->bytes_xfered -= data->blksz;
                }
        }
 
@@ -869,24 +788,7 @@ static void wbsd_request(struct mmc_host *mmc, struct mmc_request *mrq)
                goto done;
        }
 
-       /*
-        * Does the request include data?
-        */
        if (cmd->data) {
-               wbsd_prepare_data(host, cmd->data);
-
-               if (cmd->data->error != MMC_ERR_NONE)
-                       goto done;
-       }
-
-       wbsd_send_command(host, cmd);
-
-       /*
-        * If this is a data transfer the request
-        * will be finished after the data has
-        * transfered.
-        */
-       if (cmd->data && (cmd->error == MMC_ERR_NONE)) {
                /*
                 * The hardware is so delightfully stupid that it has a list
                 * of "data" commands. If a command isn't on this list, it'll
@@ -918,14 +820,30 @@ static void wbsd_request(struct mmc_host *mmc, struct mmc_request *mrq)
                                "supported by this controller.\n",
                                mmc_hostname(host->mmc), cmd->opcode);
 #endif
-                       cmd->data->error = MMC_ERR_INVALID;
-
-                       if (cmd->data->stop)
-                               wbsd_send_command(host, cmd->data->stop);
+                       cmd->error = MMC_ERR_INVALID;
 
                        goto done;
                };
+       }
+
+       /*
+        * Does the request include data?
+        */
+       if (cmd->data) {
+               wbsd_prepare_data(host, cmd->data);
+
+               if (cmd->data->error != MMC_ERR_NONE)
+                       goto done;
+       }
+
+       wbsd_send_command(host, cmd);
 
+       /*
+        * If this is a data transfer the request
+        * will be finished after the data has
+        * transfered.
+        */
+       if (cmd->data && (cmd->error == MMC_ERR_NONE)) {
                /*
                 * Dirty fix for hardware bug.
                 */
@@ -1167,7 +1085,7 @@ static void wbsd_tasklet_fifo(unsigned long param)
        /*
         * Done?
         */
-       if (host->size == data->bytes_xfered) {
+       if (host->num_sg == 0) {
                wbsd_write_index(host, WBSD_IDX_FIFOEN, 0);
                tasklet_schedule(&host->finish_tasklet);
        }
@@ -1245,30 +1163,6 @@ end:
        spin_unlock(&host->lock);
 }
 
-static void wbsd_tasklet_block(unsigned long param)
-{
-       struct wbsd_host *host = (struct wbsd_host *)param;
-       struct mmc_data *data;
-
-       spin_lock(&host->lock);
-
-       if ((wbsd_read_index(host, WBSD_IDX_CRCSTATUS) & WBSD_CRC_MASK) !=
-               WBSD_CRC_OK) {
-               data = wbsd_get_data(host);
-               if (!data)
-                       goto end;
-
-               DBGF("CRC error\n");
-
-               data->error = MMC_ERR_BADCRC;
-
-               tasklet_schedule(&host->finish_tasklet);
-       }
-
-end:
-       spin_unlock(&host->lock);
-}
-
 /*
  * Interrupt handling
  */
@@ -1299,8 +1193,6 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id)
                tasklet_hi_schedule(&host->crc_tasklet);
        if (isr & WBSD_INT_TIMEOUT)
                tasklet_hi_schedule(&host->timeout_tasklet);
-       if (isr & WBSD_INT_BUSYEND)
-               tasklet_hi_schedule(&host->block_tasklet);
        if (isr & WBSD_INT_TC)
                tasklet_schedule(&host->finish_tasklet);
 
@@ -1601,8 +1493,6 @@ static int __devinit wbsd_request_irq(struct wbsd_host *host, int irq)
                        (unsigned long)host);
        tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish,
                        (unsigned long)host);
-       tasklet_init(&host->block_tasklet, wbsd_tasklet_block,
-                       (unsigned long)host);
 
        return 0;
 }
@@ -1621,7 +1511,6 @@ static void __devexit wbsd_release_irq(struct wbsd_host *host)
        tasklet_kill(&host->crc_tasklet);
        tasklet_kill(&host->timeout_tasklet);
        tasklet_kill(&host->finish_tasklet);
-       tasklet_kill(&host->block_tasklet);
 }
 
 /*
similarity index 95%
rename from drivers/mmc/wbsd.h
rename to drivers/mmc/host/wbsd.h
index d06718b..873bda1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/mmc/wbsd.h - Winbond W83L51xD SD/MMC driver
  *
- *  Copyright (C) 2004-2005 Pierre Ossman, All Rights Reserved.
+ *  Copyright (C) 2004-2007 Pierre Ossman, 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
 
 #define WBSD_EINT_CARD         0x40
 #define WBSD_EINT_FIFO_THRE    0x20
-#define WBSD_EINT_CCRC         0x10
+#define WBSD_EINT_CRC          0x10
 #define WBSD_EINT_TIMEOUT      0x08
 #define WBSD_EINT_PROGEND      0x04
-#define WBSD_EINT_CRC          0x02
+#define WBSD_EINT_BUSYEND      0x02
 #define WBSD_EINT_TC           0x01
 
 #define WBSD_INT_PENDING       0x80
@@ -158,8 +158,6 @@ struct wbsd_host
        unsigned int            offset;         /* Offset into current entry */
        unsigned int            remain;         /* Data left in curren entry */
 
-       int                     size;           /* Total size of transfer */
-
        char*                   dma_buffer;     /* ISA DMA buffer */
        dma_addr_t              dma_addr;       /* Physical address for same */
 
@@ -182,7 +180,6 @@ struct wbsd_host
        struct tasklet_struct   crc_tasklet;
        struct tasklet_struct   timeout_tasklet;
        struct tasklet_struct   finish_tasklet;
-       struct tasklet_struct   block_tasklet;
 
        struct timer_list       ignore_timer;   /* Ignore detection timer */
 };
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
deleted file mode 100644 (file)
index 4a73e8b..0000000
+++ /dev/null
@@ -1,1724 +0,0 @@
-/*
- *  linux/drivers/mmc/mmc.c
- *
- *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
- *  SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
- *  SD support Copyright (C) 2005 Pierre Ossman, All Rights Reserved.
- *  MMCv4 support Copyright (C) 2006 Philip Langdale, 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 version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/completion.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/pagemap.h>
-#include <linux/err.h>
-#include <asm/scatterlist.h>
-#include <linux/scatterlist.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
-
-#include "mmc.h"
-
-#define CMD_RETRIES    3
-
-/*
- * OCR Bit positions to 10s of Vdd mV.
- */
-static const unsigned short mmc_ocr_bit_to_vdd[] = {
-       150,    155,    160,    165,    170,    180,    190,    200,
-       210,    220,    230,    240,    250,    260,    270,    280,
-       290,    300,    310,    320,    330,    340,    350,    360
-};
-
-static const unsigned int tran_exp[] = {
-       10000,          100000,         1000000,        10000000,
-       0,              0,              0,              0
-};
-
-static const unsigned char tran_mant[] = {
-       0,      10,     12,     13,     15,     20,     25,     30,
-       35,     40,     45,     50,     55,     60,     70,     80,
-};
-
-static const unsigned int tacc_exp[] = {
-       1,      10,     100,    1000,   10000,  100000, 1000000, 10000000,
-};
-
-static const unsigned int tacc_mant[] = {
-       0,      10,     12,     13,     15,     20,     25,     30,
-       35,     40,     45,     50,     55,     60,     70,     80,
-};
-
-
-/**
- *     mmc_request_done - finish processing an MMC request
- *     @host: MMC host which completed request
- *     @mrq: MMC request which request
- *
- *     MMC drivers should call this function when they have completed
- *     their processing of a request.
- */
-void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
-{
-       struct mmc_command *cmd = mrq->cmd;
-       int err = cmd->error;
-
-       pr_debug("%s: req done (CMD%u): %d/%d/%d: %08x %08x %08x %08x\n",
-                mmc_hostname(host), cmd->opcode, err,
-                mrq->data ? mrq->data->error : 0,
-                mrq->stop ? mrq->stop->error : 0,
-                cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
-
-       if (err && cmd->retries) {
-               cmd->retries--;
-               cmd->error = 0;
-               host->ops->request(host, mrq);
-       } else if (mrq->done) {
-               mrq->done(mrq);
-       }
-}
-
-EXPORT_SYMBOL(mmc_request_done);
-
-/**
- *     mmc_start_request - start a command on a host
- *     @host: MMC host to start command on
- *     @mrq: MMC request to start
- *
- *     Queue a command on the specified host.  We expect the
- *     caller to be holding the host lock with interrupts disabled.
- */
-void
-mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
-{
-       pr_debug("%s: starting CMD%u arg %08x flags %08x\n",
-                mmc_hostname(host), mrq->cmd->opcode,
-                mrq->cmd->arg, mrq->cmd->flags);
-
-       WARN_ON(!host->claimed);
-
-       mrq->cmd->error = 0;
-       mrq->cmd->mrq = mrq;
-       if (mrq->data) {
-               BUG_ON(mrq->data->blksz > host->max_blk_size);
-               BUG_ON(mrq->data->blocks > host->max_blk_count);
-               BUG_ON(mrq->data->blocks * mrq->data->blksz >
-                       host->max_req_size);
-
-               mrq->cmd->data = mrq->data;
-               mrq->data->error = 0;
-               mrq->data->mrq = mrq;
-               if (mrq->stop) {
-                       mrq->data->stop = mrq->stop;
-                       mrq->stop->error = 0;
-                       mrq->stop->mrq = mrq;
-               }
-       }
-       host->ops->request(host, mrq);
-}
-
-EXPORT_SYMBOL(mmc_start_request);
-
-static void mmc_wait_done(struct mmc_request *mrq)
-{
-       complete(mrq->done_data);
-}
-
-int mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
-{
-       DECLARE_COMPLETION_ONSTACK(complete);
-
-       mrq->done_data = &complete;
-       mrq->done = mmc_wait_done;
-
-       mmc_start_request(host, mrq);
-
-       wait_for_completion(&complete);
-
-       return 0;
-}
-
-EXPORT_SYMBOL(mmc_wait_for_req);
-
-/**
- *     mmc_wait_for_cmd - start a command and wait for completion
- *     @host: MMC host to start command
- *     @cmd: MMC command to start
- *     @retries: maximum number of retries
- *
- *     Start a new MMC command for a host, and wait for the command
- *     to complete.  Return any error that occurred while the command
- *     was executing.  Do not attempt to parse the response.
- */
-int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries)
-{
-       struct mmc_request mrq;
-
-       BUG_ON(!host->claimed);
-
-       memset(&mrq, 0, sizeof(struct mmc_request));
-
-       memset(cmd->resp, 0, sizeof(cmd->resp));
-       cmd->retries = retries;
-
-       mrq.cmd = cmd;
-       cmd->data = NULL;
-
-       mmc_wait_for_req(host, &mrq);
-
-       return cmd->error;
-}
-
-EXPORT_SYMBOL(mmc_wait_for_cmd);
-
-/**
- *     mmc_wait_for_app_cmd - start an application command and wait for
-                              completion
- *     @host: MMC host to start command
- *     @rca: RCA to send MMC_APP_CMD to
- *     @cmd: MMC command to start
- *     @retries: maximum number of retries
- *
- *     Sends a MMC_APP_CMD, checks the card response, sends the command
- *     in the parameter and waits for it to complete. Return any error
- *     that occurred while the command was executing.  Do not attempt to
- *     parse the response.
- */
-int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca,
-       struct mmc_command *cmd, int retries)
-{
-       struct mmc_request mrq;
-       struct mmc_command appcmd;
-
-       int i, err;
-
-       BUG_ON(!host->claimed);
-       BUG_ON(retries < 0);
-
-       err = MMC_ERR_INVALID;
-
-       /*
-        * We have to resend MMC_APP_CMD for each attempt so
-        * we cannot use the retries field in mmc_command.
-        */
-       for (i = 0;i <= retries;i++) {
-               memset(&mrq, 0, sizeof(struct mmc_request));
-
-               appcmd.opcode = MMC_APP_CMD;
-               appcmd.arg = rca << 16;
-               appcmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-               appcmd.retries = 0;
-               memset(appcmd.resp, 0, sizeof(appcmd.resp));
-               appcmd.data = NULL;
-
-               mrq.cmd = &appcmd;
-               appcmd.data = NULL;
-
-               mmc_wait_for_req(host, &mrq);
-
-               if (appcmd.error) {
-                       err = appcmd.error;
-                       continue;
-               }
-
-               /* Check that card supported application commands */
-               if (!(appcmd.resp[0] & R1_APP_CMD))
-                       return MMC_ERR_FAILED;
-
-               memset(&mrq, 0, sizeof(struct mmc_request));
-
-               memset(cmd->resp, 0, sizeof(cmd->resp));
-               cmd->retries = 0;
-
-               mrq.cmd = cmd;
-               cmd->data = NULL;
-
-               mmc_wait_for_req(host, &mrq);
-
-               err = cmd->error;
-               if (cmd->error == MMC_ERR_NONE)
-                       break;
-       }
-
-       return err;
-}
-
-EXPORT_SYMBOL(mmc_wait_for_app_cmd);
-
-/**
- *     mmc_set_data_timeout - set the timeout for a data command
- *     @data: data phase for command
- *     @card: the MMC card associated with the data transfer
- *     @write: flag to differentiate reads from writes
- */
-void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card,
-                         int write)
-{
-       unsigned int mult;
-
-       /*
-        * SD cards use a 100 multiplier rather than 10
-        */
-       mult = mmc_card_sd(card) ? 100 : 10;
-
-       /*
-        * Scale up the multiplier (and therefore the timeout) by
-        * the r2w factor for writes.
-        */
-       if (write)
-               mult <<= card->csd.r2w_factor;
-
-       data->timeout_ns = card->csd.tacc_ns * mult;
-       data->timeout_clks = card->csd.tacc_clks * mult;
-
-       /*
-        * SD cards also have an upper limit on the timeout.
-        */
-       if (mmc_card_sd(card)) {
-               unsigned int timeout_us, limit_us;
-
-               timeout_us = data->timeout_ns / 1000;
-               timeout_us += data->timeout_clks * 1000 /
-                       (card->host->ios.clock / 1000);
-
-               if (write)
-                       limit_us = 250000;
-               else
-                       limit_us = 100000;
-
-               /*
-                * SDHC cards always use these fixed values.
-                */
-               if (timeout_us > limit_us || mmc_card_blockaddr(card)) {
-                       data->timeout_ns = limit_us * 1000;
-                       data->timeout_clks = 0;
-               }
-       }
-}
-EXPORT_SYMBOL(mmc_set_data_timeout);
-
-static int mmc_select_card(struct mmc_host *host, struct mmc_card *card);
-
-/**
- *     __mmc_claim_host - exclusively claim a host
- *     @host: mmc host to claim
- *     @card: mmc card to claim host for
- *
- *     Claim a host for a set of operations.  If a valid card
- *     is passed and this wasn't the last card selected, select
- *     the card before returning.
- *
- *     Note: you should use mmc_card_claim_host or mmc_claim_host.
- */
-int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card)
-{
-       DECLARE_WAITQUEUE(wait, current);
-       unsigned long flags;
-       int err = 0;
-
-       add_wait_queue(&host->wq, &wait);
-       spin_lock_irqsave(&host->lock, flags);
-       while (1) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               if (!host->claimed)
-                       break;
-               spin_unlock_irqrestore(&host->lock, flags);
-               schedule();
-               spin_lock_irqsave(&host->lock, flags);
-       }
-       set_current_state(TASK_RUNNING);
-       host->claimed = 1;
-       spin_unlock_irqrestore(&host->lock, flags);
-       remove_wait_queue(&host->wq, &wait);
-
-       if (card != (void *)-1) {
-               err = mmc_select_card(host, card);
-               if (err != MMC_ERR_NONE)
-                       return err;
-       }
-
-       return err;
-}
-
-EXPORT_SYMBOL(__mmc_claim_host);
-
-/**
- *     mmc_release_host - release a host
- *     @host: mmc host to release
- *
- *     Release a MMC host, allowing others to claim the host
- *     for their operations.
- */
-void mmc_release_host(struct mmc_host *host)
-{
-       unsigned long flags;
-
-       BUG_ON(!host->claimed);
-
-       spin_lock_irqsave(&host->lock, flags);
-       host->claimed = 0;
-       spin_unlock_irqrestore(&host->lock, flags);
-
-       wake_up(&host->wq);
-}
-
-EXPORT_SYMBOL(mmc_release_host);
-
-static inline void mmc_set_ios(struct mmc_host *host)
-{
-       struct mmc_ios *ios = &host->ios;
-
-       pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u "
-               "width %u timing %u\n",
-                mmc_hostname(host), ios->clock, ios->bus_mode,
-                ios->power_mode, ios->chip_select, ios->vdd,
-                ios->bus_width, ios->timing);
-
-       host->ops->set_ios(host, ios);
-}
-
-static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
-{
-       int err;
-       struct mmc_command cmd;
-
-       BUG_ON(!host->claimed);
-
-       if (host->card_selected == card)
-               return MMC_ERR_NONE;
-
-       host->card_selected = card;
-
-       cmd.opcode = MMC_SELECT_CARD;
-       cmd.arg = card->rca << 16;
-       cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-       err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-       if (err != MMC_ERR_NONE)
-               return err;
-
-       /*
-        * We can only change the bus width of SD cards when
-        * they are selected so we have to put the handling
-        * here.
-        *
-        * The card is in 1 bit mode by default so
-        * we only need to change if it supports the
-        * wider version.
-        */
-       if (mmc_card_sd(card) &&
-               (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
-
-               /*
-               * Default bus width is 1 bit.
-               */
-               host->ios.bus_width = MMC_BUS_WIDTH_1;
-
-               if (host->caps & MMC_CAP_4_BIT_DATA) {
-                       struct mmc_command cmd;
-                       cmd.opcode = SD_APP_SET_BUS_WIDTH;
-                       cmd.arg = SD_BUS_WIDTH_4;
-                       cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-                       err = mmc_wait_for_app_cmd(host, card->rca, &cmd,
-                               CMD_RETRIES);
-                       if (err != MMC_ERR_NONE)
-                               return err;
-
-                       host->ios.bus_width = MMC_BUS_WIDTH_4;
-               }
-       }
-
-       mmc_set_ios(host);
-
-       return MMC_ERR_NONE;
-}
-
-/*
- * Ensure that no card is selected.
- */
-static void mmc_deselect_cards(struct mmc_host *host)
-{
-       struct mmc_command cmd;
-
-       if (host->card_selected) {
-               host->card_selected = NULL;
-
-               cmd.opcode = MMC_SELECT_CARD;
-               cmd.arg = 0;
-               cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
-
-               mmc_wait_for_cmd(host, &cmd, 0);
-       }
-}
-
-
-static inline void mmc_delay(unsigned int ms)
-{
-       if (ms < 1000 / HZ) {
-               cond_resched();
-               mdelay(ms);
-       } else {
-               msleep(ms);
-       }
-}
-
-/*
- * Mask off any voltages we don't support and select
- * the lowest voltage
- */
-static u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
-{
-       int bit;
-
-       ocr &= host->ocr_avail;
-
-       bit = ffs(ocr);
-       if (bit) {
-               bit -= 1;
-
-               ocr &= 3 << bit;
-
-               host->ios.vdd = bit;
-               mmc_set_ios(host);
-       } else {
-               ocr = 0;
-       }
-
-       return ocr;
-}
-
-#define UNSTUFF_BITS(resp,start,size)                                  \
-       ({                                                              \
-               const int __size = size;                                \
-               const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \
-               const int __off = 3 - ((start) / 32);                   \
-               const int __shft = (start) & 31;                        \
-               u32 __res;                                              \
-                                                                       \
-               __res = resp[__off] >> __shft;                          \
-               if (__size + __shft > 32)                               \
-                       __res |= resp[__off-1] << ((32 - __shft) % 32); \
-               __res & __mask;                                         \
-       })
-
-/*
- * Given the decoded CSD structure, decode the raw CID to our CID structure.
- */
-static void mmc_decode_cid(struct mmc_card *card)
-{
-       u32 *resp = card->raw_cid;
-
-       memset(&card->cid, 0, sizeof(struct mmc_cid));
-
-       if (mmc_card_sd(card)) {
-               /*
-                * SD doesn't currently have a version field so we will
-                * have to assume we can parse this.
-                */
-               card->cid.manfid                = UNSTUFF_BITS(resp, 120, 8);
-               card->cid.oemid                 = UNSTUFF_BITS(resp, 104, 16);
-               card->cid.prod_name[0]          = UNSTUFF_BITS(resp, 96, 8);
-               card->cid.prod_name[1]          = UNSTUFF_BITS(resp, 88, 8);
-               card->cid.prod_name[2]          = UNSTUFF_BITS(resp, 80, 8);
-               card->cid.prod_name[3]          = UNSTUFF_BITS(resp, 72, 8);
-               card->cid.prod_name[4]          = UNSTUFF_BITS(resp, 64, 8);
-               card->cid.hwrev                 = UNSTUFF_BITS(resp, 60, 4);
-               card->cid.fwrev                 = UNSTUFF_BITS(resp, 56, 4);
-               card->cid.serial                = UNSTUFF_BITS(resp, 24, 32);
-               card->cid.year                  = UNSTUFF_BITS(resp, 12, 8);
-               card->cid.month                 = UNSTUFF_BITS(resp, 8, 4);
-
-               card->cid.year += 2000; /* SD cards year offset */
-       } else {
-               /*
-                * The selection of the format here is based upon published
-                * specs from sandisk and from what people have reported.
-                */
-               switch (card->csd.mmca_vsn) {
-               case 0: /* MMC v1.0 - v1.2 */
-               case 1: /* MMC v1.4 */
-                       card->cid.manfid        = UNSTUFF_BITS(resp, 104, 24);
-                       card->cid.prod_name[0]  = UNSTUFF_BITS(resp, 96, 8);
-                       card->cid.prod_name[1]  = UNSTUFF_BITS(resp, 88, 8);
-                       card->cid.prod_name[2]  = UNSTUFF_BITS(resp, 80, 8);
-                       card->cid.prod_name[3]  = UNSTUFF_BITS(resp, 72, 8);
-                       card->cid.prod_name[4]  = UNSTUFF_BITS(resp, 64, 8);
-                       card->cid.prod_name[5]  = UNSTUFF_BITS(resp, 56, 8);
-                       card->cid.prod_name[6]  = UNSTUFF_BITS(resp, 48, 8);
-                       card->cid.hwrev         = UNSTUFF_BITS(resp, 44, 4);
-                       card->cid.fwrev         = UNSTUFF_BITS(resp, 40, 4);
-                       card->cid.serial        = UNSTUFF_BITS(resp, 16, 24);
-                       card->cid.month         = UNSTUFF_BITS(resp, 12, 4);
-                       card->cid.year          = UNSTUFF_BITS(resp, 8, 4) + 1997;
-                       break;
-
-               case 2: /* MMC v2.0 - v2.2 */
-               case 3: /* MMC v3.1 - v3.3 */
-               case 4: /* MMC v4 */
-                       card->cid.manfid        = UNSTUFF_BITS(resp, 120, 8);
-                       card->cid.oemid         = UNSTUFF_BITS(resp, 104, 16);
-                       card->cid.prod_name[0]  = UNSTUFF_BITS(resp, 96, 8);
-                       card->cid.prod_name[1]  = UNSTUFF_BITS(resp, 88, 8);
-                       card->cid.prod_name[2]  = UNSTUFF_BITS(resp, 80, 8);
-                       card->cid.prod_name[3]  = UNSTUFF_BITS(resp, 72, 8);
-                       card->cid.prod_name[4]  = UNSTUFF_BITS(resp, 64, 8);
-                       card->cid.prod_name[5]  = UNSTUFF_BITS(resp, 56, 8);
-                       card->cid.serial        = UNSTUFF_BITS(resp, 16, 32);
-                       card->cid.month         = UNSTUFF_BITS(resp, 12, 4);
-                       card->cid.year          = UNSTUFF_BITS(resp, 8, 4) + 1997;
-                       break;
-
-               default:
-                       printk("%s: card has unknown MMCA version %d\n",
-                               mmc_hostname(card->host), card->csd.mmca_vsn);
-                       mmc_card_set_bad(card);
-                       break;
-               }
-       }
-}
-
-/*
- * Given a 128-bit response, decode to our card CSD structure.
- */
-static void mmc_decode_csd(struct mmc_card *card)
-{
-       struct mmc_csd *csd = &card->csd;
-       unsigned int e, m, csd_struct;
-       u32 *resp = card->raw_csd;
-
-       if (mmc_card_sd(card)) {
-               csd_struct = UNSTUFF_BITS(resp, 126, 2);
-
-               switch (csd_struct) {
-               case 0:
-                       m = UNSTUFF_BITS(resp, 115, 4);
-                       e = UNSTUFF_BITS(resp, 112, 3);
-                       csd->tacc_ns     = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
-                       csd->tacc_clks   = UNSTUFF_BITS(resp, 104, 8) * 100;
-
-                       m = UNSTUFF_BITS(resp, 99, 4);
-                       e = UNSTUFF_BITS(resp, 96, 3);
-                       csd->max_dtr      = tran_exp[e] * tran_mant[m];
-                       csd->cmdclass     = UNSTUFF_BITS(resp, 84, 12);
-
-                       e = UNSTUFF_BITS(resp, 47, 3);
-                       m = UNSTUFF_BITS(resp, 62, 12);
-                       csd->capacity     = (1 + m) << (e + 2);
-
-                       csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
-                       csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
-                       csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
-                       csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
-                       csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
-                       csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
-                       csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
-                       break;
-               case 1:
-                       /*
-                        * This is a block-addressed SDHC card. Most
-                        * interesting fields are unused and have fixed
-                        * values. To avoid getting tripped by buggy cards,
-                        * we assume those fixed values ourselves.
-                        */
-                       mmc_card_set_blockaddr(card);
-
-                       csd->tacc_ns     = 0; /* Unused */
-                       csd->tacc_clks   = 0; /* Unused */
-
-                       m = UNSTUFF_BITS(resp, 99, 4);
-                       e = UNSTUFF_BITS(resp, 96, 3);
-                       csd->max_dtr      = tran_exp[e] * tran_mant[m];
-                       csd->cmdclass     = UNSTUFF_BITS(resp, 84, 12);
-
-                       m = UNSTUFF_BITS(resp, 48, 22);
-                       csd->capacity     = (1 + m) << 10;
-
-                       csd->read_blkbits = 9;
-                       csd->read_partial = 0;
-                       csd->write_misalign = 0;
-                       csd->read_misalign = 0;
-                       csd->r2w_factor = 4; /* Unused */
-                       csd->write_blkbits = 9;
-                       csd->write_partial = 0;
-                       break;
-               default:
-                       printk("%s: unrecognised CSD structure version %d\n",
-                               mmc_hostname(card->host), csd_struct);
-                       mmc_card_set_bad(card);
-                       return;
-               }
-       } else {
-               /*
-                * We only understand CSD structure v1.1 and v1.2.
-                * v1.2 has extra information in bits 15, 11 and 10.
-                */
-               csd_struct = UNSTUFF_BITS(resp, 126, 2);
-               if (csd_struct != 1 && csd_struct != 2) {
-                       printk("%s: unrecognised CSD structure version %d\n",
-                               mmc_hostname(card->host), csd_struct);
-                       mmc_card_set_bad(card);
-                       return;
-               }
-
-               csd->mmca_vsn    = UNSTUFF_BITS(resp, 122, 4);
-               m = UNSTUFF_BITS(resp, 115, 4);
-               e = UNSTUFF_BITS(resp, 112, 3);
-               csd->tacc_ns     = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
-               csd->tacc_clks   = UNSTUFF_BITS(resp, 104, 8) * 100;
-
-               m = UNSTUFF_BITS(resp, 99, 4);
-               e = UNSTUFF_BITS(resp, 96, 3);
-               csd->max_dtr      = tran_exp[e] * tran_mant[m];
-               csd->cmdclass     = UNSTUFF_BITS(resp, 84, 12);
-
-               e = UNSTUFF_BITS(resp, 47, 3);
-               m = UNSTUFF_BITS(resp, 62, 12);
-               csd->capacity     = (1 + m) << (e + 2);
-
-               csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
-               csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
-               csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
-               csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
-               csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
-               csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
-               csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
-       }
-}
-
-/*
- * Given a 64-bit response, decode to our card SCR structure.
- */
-static void mmc_decode_scr(struct mmc_card *card)
-{
-       struct sd_scr *scr = &card->scr;
-       unsigned int scr_struct;
-       u32 resp[4];
-
-       BUG_ON(!mmc_card_sd(card));
-
-       resp[3] = card->raw_scr[1];
-       resp[2] = card->raw_scr[0];
-
-       scr_struct = UNSTUFF_BITS(resp, 60, 4);
-       if (scr_struct != 0) {
-               printk("%s: unrecognised SCR structure version %d\n",
-                       mmc_hostname(card->host), scr_struct);
-               mmc_card_set_bad(card);
-               return;
-       }
-
-       scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4);
-       scr->bus_widths = UNSTUFF_BITS(resp, 48, 4);
-}
-
-/*
- * Locate a MMC card on this MMC host given a raw CID.
- */
-static struct mmc_card *mmc_find_card(struct mmc_host *host, u32 *raw_cid)
-{
-       struct mmc_card *card;
-
-       list_for_each_entry(card, &host->cards, node) {
-               if (memcmp(card->raw_cid, raw_cid, sizeof(card->raw_cid)) == 0)
-                       return card;
-       }
-       return NULL;
-}
-
-/*
- * Allocate a new MMC card, and assign a unique RCA.
- */
-static struct mmc_card *
-mmc_alloc_card(struct mmc_host *host, u32 *raw_cid, unsigned int *frca)
-{
-       struct mmc_card *card, *c;
-       unsigned int rca = *frca;
-
-       card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
-       if (!card)
-               return ERR_PTR(-ENOMEM);
-
-       mmc_init_card(card, host);
-       memcpy(card->raw_cid, raw_cid, sizeof(card->raw_cid));
-
- again:
-       list_for_each_entry(c, &host->cards, node)
-               if (c->rca == rca) {
-                       rca++;
-                       goto again;
-               }
-
-       card->rca = rca;
-
-       *frca = rca;
-
-       return card;
-}
-
-/*
- * Tell attached cards to go to IDLE state
- */
-static void mmc_idle_cards(struct mmc_host *host)
-{
-       struct mmc_command cmd;
-
-       host->ios.chip_select = MMC_CS_HIGH;
-       mmc_set_ios(host);
-
-       mmc_delay(1);
-
-       cmd.opcode = MMC_GO_IDLE_STATE;
-       cmd.arg = 0;
-       cmd.flags = MMC_RSP_NONE | MMC_CMD_BC;
-
-       mmc_wait_for_cmd(host, &cmd, 0);
-
-       mmc_delay(1);
-
-       host->ios.chip_select = MMC_CS_DONTCARE;
-       mmc_set_ios(host);
-
-       mmc_delay(1);
-}
-
-/*
- * Apply power to the MMC stack.  This is a two-stage process.
- * First, we enable power to the card without the clock running.
- * We then wait a bit for the power to stabilise.  Finally,
- * enable the bus drivers and clock to the card.
- *
- * We must _NOT_ enable the clock prior to power stablising.
- *
- * If a host does all the power sequencing itself, ignore the
- * initial MMC_POWER_UP stage.
- */
-static void mmc_power_up(struct mmc_host *host)
-{
-       int bit = fls(host->ocr_avail) - 1;
-
-       host->ios.vdd = bit;
-       host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
-       host->ios.chip_select = MMC_CS_DONTCARE;
-       host->ios.power_mode = MMC_POWER_UP;
-       host->ios.bus_width = MMC_BUS_WIDTH_1;
-       host->ios.timing = MMC_TIMING_LEGACY;
-       mmc_set_ios(host);
-
-       mmc_delay(1);
-
-       host->ios.clock = host->f_min;
-       host->ios.power_mode = MMC_POWER_ON;
-       mmc_set_ios(host);
-
-       mmc_delay(2);
-}
-
-static void mmc_power_off(struct mmc_host *host)
-{
-       host->ios.clock = 0;
-       host->ios.vdd = 0;
-       host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
-       host->ios.chip_select = MMC_CS_DONTCARE;
-       host->ios.power_mode = MMC_POWER_OFF;
-       host->ios.bus_width = MMC_BUS_WIDTH_1;
-       host->ios.timing = MMC_TIMING_LEGACY;
-       mmc_set_ios(host);
-}
-
-static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
-{
-       struct mmc_command cmd;
-       int i, err = 0;
-
-       cmd.opcode = MMC_SEND_OP_COND;
-       cmd.arg = ocr;
-       cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
-
-       for (i = 100; i; i--) {
-               err = mmc_wait_for_cmd(host, &cmd, 0);
-               if (err != MMC_ERR_NONE)
-                       break;
-
-               if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
-                       break;
-
-               err = MMC_ERR_TIMEOUT;
-
-               mmc_delay(10);
-       }
-
-       if (rocr)
-               *rocr = cmd.resp[0];
-
-       return err;
-}
-
-static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
-{
-       struct mmc_command cmd;
-       int i, err = 0;
-
-       cmd.opcode = SD_APP_OP_COND;
-       cmd.arg = ocr;
-       cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
-
-       for (i = 100; i; i--) {
-               err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES);
-               if (err != MMC_ERR_NONE)
-                       break;
-
-               if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
-                       break;
-
-               err = MMC_ERR_TIMEOUT;
-
-               mmc_delay(10);
-       }
-
-       if (rocr)
-               *rocr = cmd.resp[0];
-
-       return err;
-}
-
-static int mmc_send_if_cond(struct mmc_host *host, u32 ocr, int *rsd2)
-{
-       struct mmc_command cmd;
-       int err, sd2;
-       static const u8 test_pattern = 0xAA;
-
-       /*
-       * To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND
-       * before SD_APP_OP_COND. This command will harmlessly fail for
-       * SD 1.0 cards.
-       */
-       cmd.opcode = SD_SEND_IF_COND;
-       cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern;
-       cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR;
-
-       err = mmc_wait_for_cmd(host, &cmd, 0);
-       if (err == MMC_ERR_NONE) {
-               if ((cmd.resp[0] & 0xFF) == test_pattern) {
-                       sd2 = 1;
-               } else {
-                       sd2 = 0;
-                       err = MMC_ERR_FAILED;
-               }
-       } else {
-               /*
-                * Treat errors as SD 1.0 card.
-                */
-               sd2 = 0;
-               err = MMC_ERR_NONE;
-       }
-       if (rsd2)
-               *rsd2 = sd2;
-       return err;
-}
-
-/*
- * Discover cards by requesting their CID.  If this command
- * times out, it is not an error; there are no further cards
- * to be discovered.  Add new cards to the list.
- *
- * Create a mmc_card entry for each discovered card, assigning
- * it an RCA, and save the raw CID for decoding later.
- */
-static void mmc_discover_cards(struct mmc_host *host)
-{
-       struct mmc_card *card;
-       unsigned int first_rca = 1, err;
-
-       while (1) {
-               struct mmc_command cmd;
-
-               cmd.opcode = MMC_ALL_SEND_CID;
-               cmd.arg = 0;
-               cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
-
-               err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-               if (err == MMC_ERR_TIMEOUT) {
-                       err = MMC_ERR_NONE;
-                       break;
-               }
-               if (err != MMC_ERR_NONE) {
-                       printk(KERN_ERR "%s: error requesting CID: %d\n",
-                               mmc_hostname(host), err);
-                       break;
-               }
-
-               card = mmc_find_card(host, cmd.resp);
-               if (!card) {
-                       card = mmc_alloc_card(host, cmd.resp, &first_rca);
-                       if (IS_ERR(card)) {
-                               err = PTR_ERR(card);
-                               break;
-                       }
-                       list_add(&card->node, &host->cards);
-               }
-
-               card->state &= ~MMC_STATE_DEAD;
-
-               if (host->mode == MMC_MODE_SD) {
-                       mmc_card_set_sd(card);
-
-                       cmd.opcode = SD_SEND_RELATIVE_ADDR;
-                       cmd.arg = 0;
-                       cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
-
-                       err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-                       if (err != MMC_ERR_NONE)
-                               mmc_card_set_dead(card);
-                       else {
-                               card->rca = cmd.resp[0] >> 16;
-
-                               if (!host->ops->get_ro) {
-                                       printk(KERN_WARNING "%s: host does not "
-                                               "support reading read-only "
-                                               "switch. assuming write-enable.\n",
-                                               mmc_hostname(host));
-                               } else {
-                                       if (host->ops->get_ro(host))
-                                               mmc_card_set_readonly(card);
-                               }
-                       }
-               } else {
-                       cmd.opcode = MMC_SET_RELATIVE_ADDR;
-                       cmd.arg = card->rca << 16;
-                       cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-                       err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-                       if (err != MMC_ERR_NONE)
-                               mmc_card_set_dead(card);
-               }
-       }
-}
-
-static void mmc_read_csds(struct mmc_host *host)
-{
-       struct mmc_card *card;
-
-       list_for_each_entry(card, &host->cards, node) {
-               struct mmc_command cmd;
-               int err;
-
-               if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
-                       continue;
-
-               cmd.opcode = MMC_SEND_CSD;
-               cmd.arg = card->rca << 16;
-               cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;
-
-               err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-               if (err != MMC_ERR_NONE) {
-                       mmc_card_set_dead(card);
-                       continue;
-               }
-
-               memcpy(card->raw_csd, cmd.resp, sizeof(card->raw_csd));
-
-               mmc_decode_csd(card);
-               mmc_decode_cid(card);
-       }
-}
-
-static void mmc_process_ext_csds(struct mmc_host *host)
-{
-       int err;
-       struct mmc_card *card;
-
-       struct mmc_request mrq;
-       struct mmc_command cmd;
-       struct mmc_data data;
-
-       struct scatterlist sg;
-
-       /*
-        * As the ext_csd is so large and mostly unused, we don't store the
-        * raw block in mmc_card.
-        */
-       u8 *ext_csd;
-       ext_csd = kmalloc(512, GFP_KERNEL);
-       if (!ext_csd) {
-               printk("%s: could not allocate a buffer to receive the ext_csd."
-                      "mmc v4 cards will be treated as v3.\n",
-                       mmc_hostname(host));
-               return;
-       }
-
-       list_for_each_entry(card, &host->cards, node) {
-               if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
-                       continue;
-               if (mmc_card_sd(card))
-                       continue;
-               if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
-                       continue;
-
-               err = mmc_select_card(host, card);
-               if (err != MMC_ERR_NONE) {
-                       mmc_card_set_dead(card);
-                       continue;
-               }
-
-               memset(&cmd, 0, sizeof(struct mmc_command));
-
-               cmd.opcode = MMC_SEND_EXT_CSD;
-               cmd.arg = 0;
-               cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-
-               memset(&data, 0, sizeof(struct mmc_data));
-
-               mmc_set_data_timeout(&data, card, 0);
-
-               data.blksz = 512;
-               data.blocks = 1;
-               data.flags = MMC_DATA_READ;
-               data.sg = &sg;
-               data.sg_len = 1;
-
-               memset(&mrq, 0, sizeof(struct mmc_request));
-
-               mrq.cmd = &cmd;
-               mrq.data = &data;
-
-               sg_init_one(&sg, ext_csd, 512);
-
-               mmc_wait_for_req(host, &mrq);
-
-               if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
-                       printk("%s: unable to read EXT_CSD, performance "
-                               "might suffer.\n", mmc_hostname(card->host));
-                       continue;
-               }
-
-               switch (ext_csd[EXT_CSD_CARD_TYPE]) {
-               case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
-                       card->ext_csd.hs_max_dtr = 52000000;
-                       break;
-               case EXT_CSD_CARD_TYPE_26:
-                       card->ext_csd.hs_max_dtr = 26000000;
-                       break;
-               default:
-                       /* MMC v4 spec says this cannot happen */
-                       printk("%s: card is mmc v4 but doesn't support "
-                              "any high-speed modes.\n",
-                               mmc_hostname(card->host));
-                       continue;
-               }
-
-               if (host->caps & MMC_CAP_MMC_HIGHSPEED) {
-                       /* Activate highspeed support. */
-                       cmd.opcode = MMC_SWITCH;
-                       cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
-                                 (EXT_CSD_HS_TIMING << 16) |
-                                 (1 << 8) |
-                                 EXT_CSD_CMD_SET_NORMAL;
-                       cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
-
-                       err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-                       if (err != MMC_ERR_NONE) {
-                               printk("%s: failed to switch card to mmc v4 "
-                                      "high-speed mode.\n",
-                                      mmc_hostname(card->host));
-                               continue;
-                       }
-
-                       mmc_card_set_highspeed(card);
-
-                       host->ios.timing = MMC_TIMING_SD_HS;
-                       mmc_set_ios(host);
-               }
-
-               /* Check for host support for wide-bus modes. */
-               if (host->caps & MMC_CAP_4_BIT_DATA) {
-                       /* Activate 4-bit support. */
-                       cmd.opcode = MMC_SWITCH;
-                       cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
-                                 (EXT_CSD_BUS_WIDTH << 16) |
-                                 (EXT_CSD_BUS_WIDTH_4 << 8) |
-                                 EXT_CSD_CMD_SET_NORMAL;
-                       cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
-
-                       err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-                       if (err != MMC_ERR_NONE) {
-                               printk("%s: failed to switch card to "
-                                      "mmc v4 4-bit bus mode.\n",
-                                      mmc_hostname(card->host));
-                               continue;
-                       }
-
-                       host->ios.bus_width = MMC_BUS_WIDTH_4;
-                       mmc_set_ios(host);
-               }
-       }
-
-       kfree(ext_csd);
-
-       mmc_deselect_cards(host);
-}
-
-static void mmc_read_scrs(struct mmc_host *host)
-{
-       int err;
-       struct mmc_card *card;
-       struct mmc_request mrq;
-       struct mmc_command cmd;
-       struct mmc_data data;
-       struct scatterlist sg;
-
-       list_for_each_entry(card, &host->cards, node) {
-               if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
-                       continue;
-               if (!mmc_card_sd(card))
-                       continue;
-
-               err = mmc_select_card(host, card);
-               if (err != MMC_ERR_NONE) {
-                       mmc_card_set_dead(card);
-                       continue;
-               }
-
-               memset(&cmd, 0, sizeof(struct mmc_command));
-
-               cmd.opcode = MMC_APP_CMD;
-               cmd.arg = card->rca << 16;
-               cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-               err = mmc_wait_for_cmd(host, &cmd, 0);
-               if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD)) {
-                       mmc_card_set_dead(card);
-                       continue;
-               }
-
-               memset(&cmd, 0, sizeof(struct mmc_command));
-
-               cmd.opcode = SD_APP_SEND_SCR;
-               cmd.arg = 0;
-               cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-
-               memset(&data, 0, sizeof(struct mmc_data));
-
-               mmc_set_data_timeout(&data, card, 0);
-
-               data.blksz = 1 << 3;
-               data.blocks = 1;
-               data.flags = MMC_DATA_READ;
-               data.sg = &sg;
-               data.sg_len = 1;
-
-               memset(&mrq, 0, sizeof(struct mmc_request));
-
-               mrq.cmd = &cmd;
-               mrq.data = &data;
-
-               sg_init_one(&sg, (u8*)card->raw_scr, 8);
-
-               mmc_wait_for_req(host, &mrq);
-
-               if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
-                       mmc_card_set_dead(card);
-                       continue;
-               }
-
-               card->raw_scr[0] = ntohl(card->raw_scr[0]);
-               card->raw_scr[1] = ntohl(card->raw_scr[1]);
-
-               mmc_decode_scr(card);
-       }
-
-       mmc_deselect_cards(host);
-}
-
-static void mmc_read_switch_caps(struct mmc_host *host)
-{
-       int err;
-       struct mmc_card *card;
-       struct mmc_request mrq;
-       struct mmc_command cmd;
-       struct mmc_data data;
-       unsigned char *status;
-       struct scatterlist sg;
-
-       if (!(host->caps & MMC_CAP_SD_HIGHSPEED))
-               return;
-
-       status = kmalloc(64, GFP_KERNEL);
-       if (!status) {
-               printk(KERN_WARNING "%s: Unable to allocate buffer for "
-                       "reading switch capabilities.\n",
-                       mmc_hostname(host));
-               return;
-       }
-
-       list_for_each_entry(card, &host->cards, node) {
-               if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
-                       continue;
-               if (!mmc_card_sd(card))
-                       continue;
-               if (card->scr.sda_vsn < SCR_SPEC_VER_1)
-                       continue;
-
-               err = mmc_select_card(host, card);
-               if (err != MMC_ERR_NONE) {
-                       mmc_card_set_dead(card);
-                       continue;
-               }
-
-               memset(&cmd, 0, sizeof(struct mmc_command));
-
-               cmd.opcode = SD_SWITCH;
-               cmd.arg = 0x00FFFFF1;
-               cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-
-               memset(&data, 0, sizeof(struct mmc_data));
-
-               mmc_set_data_timeout(&data, card, 0);
-
-               data.blksz = 64;
-               data.blocks = 1;
-               data.flags = MMC_DATA_READ;
-               data.sg = &sg;
-               data.sg_len = 1;
-
-               memset(&mrq, 0, sizeof(struct mmc_request));
-
-               mrq.cmd = &cmd;
-               mrq.data = &data;
-
-               sg_init_one(&sg, status, 64);
-
-               mmc_wait_for_req(host, &mrq);
-
-               if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
-                       printk("%s: unable to read switch capabilities, "
-                               "performance might suffer.\n",
-                               mmc_hostname(card->host));
-                       continue;
-               }
-
-               if (status[13] & 0x02)
-                       card->sw_caps.hs_max_dtr = 50000000;
-
-               memset(&cmd, 0, sizeof(struct mmc_command));
-
-               cmd.opcode = SD_SWITCH;
-               cmd.arg = 0x80FFFFF1;
-               cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-
-               memset(&data, 0, sizeof(struct mmc_data));
-
-               mmc_set_data_timeout(&data, card, 0);
-
-               data.blksz = 64;
-               data.blocks = 1;
-               data.flags = MMC_DATA_READ;
-               data.sg = &sg;
-               data.sg_len = 1;
-
-               memset(&mrq, 0, sizeof(struct mmc_request));
-
-               mrq.cmd = &cmd;
-               mrq.data = &data;
-
-               sg_init_one(&sg, status, 64);
-
-               mmc_wait_for_req(host, &mrq);
-
-               if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE ||
-                       (status[16] & 0xF) != 1) {
-                       printk(KERN_WARNING "%s: Problem switching card "
-                               "into high-speed mode!\n",
-                               mmc_hostname(host));
-                       continue;
-               }
-
-               mmc_card_set_highspeed(card);
-
-               host->ios.timing = MMC_TIMING_SD_HS;
-               mmc_set_ios(host);
-       }
-
-       kfree(status);
-
-       mmc_deselect_cards(host);
-}
-
-static unsigned int mmc_calculate_clock(struct mmc_host *host)
-{
-       struct mmc_card *card;
-       unsigned int max_dtr = host->f_max;
-
-       list_for_each_entry(card, &host->cards, node)
-               if (!mmc_card_dead(card)) {
-                       if (mmc_card_highspeed(card) && mmc_card_sd(card)) {
-                               if (max_dtr > card->sw_caps.hs_max_dtr)
-                                       max_dtr = card->sw_caps.hs_max_dtr;
-                       } else if (mmc_card_highspeed(card) && !mmc_card_sd(card)) {
-                               if (max_dtr > card->ext_csd.hs_max_dtr)
-                                       max_dtr = card->ext_csd.hs_max_dtr;
-                       } else if (max_dtr > card->csd.max_dtr) {
-                               max_dtr = card->csd.max_dtr;
-                       }
-               }
-
-       pr_debug("%s: selected %d.%03dMHz transfer rate\n",
-                mmc_hostname(host),
-                max_dtr / 1000000, (max_dtr / 1000) % 1000);
-
-       return max_dtr;
-}
-
-/*
- * Check whether cards we already know about are still present.
- * We do this by requesting status, and checking whether a card
- * responds.
- *
- * A request for status does not cause a state change in data
- * transfer mode.
- */
-static void mmc_check_cards(struct mmc_host *host)
-{
-       struct list_head *l, *n;
-
-       mmc_deselect_cards(host);
-
-       list_for_each_safe(l, n, &host->cards) {
-               struct mmc_card *card = mmc_list_to_card(l);
-               struct mmc_command cmd;
-               int err;
-
-               cmd.opcode = MMC_SEND_STATUS;
-               cmd.arg = card->rca << 16;
-               cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-               err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-               if (err == MMC_ERR_NONE)
-                       continue;
-
-               mmc_card_set_dead(card);
-       }
-}
-
-static void mmc_setup(struct mmc_host *host)
-{
-       if (host->ios.power_mode != MMC_POWER_ON) {
-               int err;
-               u32 ocr;
-
-               host->mode = MMC_MODE_SD;
-
-               mmc_power_up(host);
-               mmc_idle_cards(host);
-
-               err = mmc_send_if_cond(host, host->ocr_avail, NULL);
-               if (err != MMC_ERR_NONE) {
-                       return;
-               }
-               err = mmc_send_app_op_cond(host, 0, &ocr);
-
-               /*
-                * If we fail to detect any SD cards then try
-                * searching for MMC cards.
-                */
-               if (err != MMC_ERR_NONE) {
-                       host->mode = MMC_MODE_MMC;
-
-                       err = mmc_send_op_cond(host, 0, &ocr);
-                       if (err != MMC_ERR_NONE)
-                               return;
-               }
-
-               host->ocr = mmc_select_voltage(host, ocr);
-
-               /*
-                * Since we're changing the OCR value, we seem to
-                * need to tell some cards to go back to the idle
-                * state.  We wait 1ms to give cards time to
-                * respond.
-                */
-               if (host->ocr)
-                       mmc_idle_cards(host);
-       } else {
-               host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
-               host->ios.clock = host->f_min;
-               mmc_set_ios(host);
-
-               /*
-                * We should remember the OCR mask from the existing
-                * cards, and detect the new cards OCR mask, combine
-                * the two and re-select the VDD.  However, if we do
-                * change VDD, we should do an idle, and then do a
-                * full re-initialisation.  We would need to notify
-                * drivers so that they can re-setup the cards as
-                * well, while keeping their queues at bay.
-                *
-                * For the moment, we take the easy way out - if the
-                * new cards don't like our currently selected VDD,
-                * they drop off the bus.
-                */
-       }
-
-       if (host->ocr == 0)
-               return;
-
-       /*
-        * Send the selected OCR multiple times... until the cards
-        * all get the idea that they should be ready for CMD2.
-        * (My SanDisk card seems to need this.)
-        */
-       if (host->mode == MMC_MODE_SD) {
-               int err, sd2;
-               err = mmc_send_if_cond(host, host->ocr, &sd2);
-               if (err == MMC_ERR_NONE) {
-                       /*
-                       * If SD_SEND_IF_COND indicates an SD 2.0
-                       * compliant card and we should set bit 30
-                       * of the ocr to indicate that we can handle
-                       * block-addressed SDHC cards.
-                       */
-                       mmc_send_app_op_cond(host, host->ocr | (sd2 << 30), NULL);
-               }
-       } else {
-               mmc_send_op_cond(host, host->ocr, NULL);
-       }
-
-       mmc_discover_cards(host);
-
-       /*
-        * Ok, now switch to push-pull mode.
-        */
-       host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
-       mmc_set_ios(host);
-
-       mmc_read_csds(host);
-
-       if (host->mode == MMC_MODE_SD) {
-               mmc_read_scrs(host);
-               mmc_read_switch_caps(host);
-       } else
-               mmc_process_ext_csds(host);
-}
-
-
-/**
- *     mmc_detect_change - process change of state on a MMC socket
- *     @host: host which changed state.
- *     @delay: optional delay to wait before detection (jiffies)
- *
- *     All we know is that card(s) have been inserted or removed
- *     from the socket(s).  We don't know which socket or cards.
- */
-void mmc_detect_change(struct mmc_host *host, unsigned long delay)
-{
-       mmc_schedule_delayed_work(&host->detect, delay);
-}
-
-EXPORT_SYMBOL(mmc_detect_change);
-
-
-static void mmc_rescan(struct work_struct *work)
-{
-       struct mmc_host *host =
-               container_of(work, struct mmc_host, detect.work);
-       struct list_head *l, *n;
-       unsigned char power_mode;
-
-       mmc_claim_host(host);
-
-       /*
-        * Check for removed cards and newly inserted ones. We check for
-        * removed cards first so we can intelligently re-select the VDD.
-        */
-       power_mode = host->ios.power_mode;
-       if (power_mode == MMC_POWER_ON)
-               mmc_check_cards(host);
-
-       mmc_setup(host);
-
-       /*
-        * Some broken cards process CMD1 even in stand-by state. There is
-        * no reply, but an ILLEGAL_COMMAND error is cached and returned
-        * after next command. We poll for card status here to clear any
-        * possibly pending error.
-        */
-       if (power_mode == MMC_POWER_ON)
-               mmc_check_cards(host);
-
-       if (!list_empty(&host->cards)) {
-               /*
-                * (Re-)calculate the fastest clock rate which the
-                * attached cards and the host support.
-                */
-               host->ios.clock = mmc_calculate_clock(host);
-               mmc_set_ios(host);
-       }
-
-       mmc_release_host(host);
-
-       list_for_each_safe(l, n, &host->cards) {
-               struct mmc_card *card = mmc_list_to_card(l);
-
-               /*
-                * If this is a new and good card, register it.
-                */
-               if (!mmc_card_present(card) && !mmc_card_dead(card)) {
-                       if (mmc_register_card(card))
-                               mmc_card_set_dead(card);
-                       else
-                               mmc_card_set_present(card);
-               }
-
-               /*
-                * If this card is dead, destroy it.
-                */
-               if (mmc_card_dead(card)) {
-                       list_del(&card->node);
-                       mmc_remove_card(card);
-               }
-       }
-
-       /*
-        * If we discover that there are no cards on the
-        * bus, turn off the clock and power down.
-        */
-       if (list_empty(&host->cards))
-               mmc_power_off(host);
-}
-
-
-/**
- *     mmc_alloc_host - initialise the per-host structure.
- *     @extra: sizeof private data structure
- *     @dev: pointer to host device model structure
- *
- *     Initialise the per-host structure.
- */
-struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
-{
-       struct mmc_host *host;
-
-       host = mmc_alloc_host_sysfs(extra, dev);
-       if (host) {
-               spin_lock_init(&host->lock);
-               init_waitqueue_head(&host->wq);
-               INIT_LIST_HEAD(&host->cards);
-               INIT_DELAYED_WORK(&host->detect, mmc_rescan);
-
-               /*
-                * By default, hosts do not support SGIO or large requests.
-                * They have to set these according to their abilities.
-                */
-               host->max_hw_segs = 1;
-               host->max_phys_segs = 1;
-               host->max_seg_size = PAGE_CACHE_SIZE;
-
-               host->max_req_size = PAGE_CACHE_SIZE;
-               host->max_blk_size = 512;
-               host->max_blk_count = PAGE_CACHE_SIZE / 512;
-       }
-
-       return host;
-}
-
-EXPORT_SYMBOL(mmc_alloc_host);
-
-/**
- *     mmc_add_host - initialise host hardware
- *     @host: mmc host
- */
-int mmc_add_host(struct mmc_host *host)
-{
-       int ret;
-
-       ret = mmc_add_host_sysfs(host);
-       if (ret == 0) {
-               mmc_power_off(host);
-               mmc_detect_change(host, 0);
-       }
-
-       return ret;
-}
-
-EXPORT_SYMBOL(mmc_add_host);
-
-/**
- *     mmc_remove_host - remove host hardware
- *     @host: mmc host
- *
- *     Unregister and remove all cards associated with this host,
- *     and power down the MMC bus.
- */
-void mmc_remove_host(struct mmc_host *host)
-{
-       struct list_head *l, *n;
-
-       list_for_each_safe(l, n, &host->cards) {
-               struct mmc_card *card = mmc_list_to_card(l);
-
-               mmc_remove_card(card);
-       }
-
-       mmc_power_off(host);
-       mmc_remove_host_sysfs(host);
-}
-
-EXPORT_SYMBOL(mmc_remove_host);
-
-/**
- *     mmc_free_host - free the host structure
- *     @host: mmc host
- *
- *     Free the host once all references to it have been dropped.
- */
-void mmc_free_host(struct mmc_host *host)
-{
-       mmc_flush_scheduled_work();
-       mmc_free_host_sysfs(host);
-}
-
-EXPORT_SYMBOL(mmc_free_host);
-
-#ifdef CONFIG_PM
-
-/**
- *     mmc_suspend_host - suspend a host
- *     @host: mmc host
- *     @state: suspend mode (PM_SUSPEND_xxx)
- */
-int mmc_suspend_host(struct mmc_host *host, pm_message_t state)
-{
-       mmc_claim_host(host);
-       mmc_deselect_cards(host);
-       mmc_power_off(host);
-       mmc_release_host(host);
-
-       return 0;
-}
-
-EXPORT_SYMBOL(mmc_suspend_host);
-
-/**
- *     mmc_resume_host - resume a previously suspended host
- *     @host: mmc host
- */
-int mmc_resume_host(struct mmc_host *host)
-{
-       mmc_rescan(&host->detect.work);
-
-       return 0;
-}
-
-EXPORT_SYMBOL(mmc_resume_host);
-
-#endif
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/tifm_sd.c b/drivers/mmc/tifm_sd.c
deleted file mode 100644 (file)
index 0581d09..0000000
+++ /dev/null
@@ -1,987 +0,0 @@
-/*
- *  tifm_sd.c - TI FlashMedia driver
- *
- *  Copyright (C) 2006 Alex Dubov <oakad@yahoo.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-
-#include <linux/tifm.h>
-#include <linux/mmc/protocol.h>
-#include <linux/mmc/host.h>
-#include <linux/highmem.h>
-#include <asm/io.h>
-
-#define DRIVER_NAME "tifm_sd"
-#define DRIVER_VERSION "0.7"
-
-static int no_dma = 0;
-static int fixed_timeout = 0;
-module_param(no_dma, bool, 0644);
-module_param(fixed_timeout, bool, 0644);
-
-/* Constants here are mostly from OMAP5912 datasheet */
-#define TIFM_MMCSD_RESET      0x0002
-#define TIFM_MMCSD_CLKMASK    0x03ff
-#define TIFM_MMCSD_POWER      0x0800
-#define TIFM_MMCSD_4BBUS      0x8000
-#define TIFM_MMCSD_RXDE       0x8000   /* rx dma enable */
-#define TIFM_MMCSD_TXDE       0x0080   /* tx dma enable */
-#define TIFM_MMCSD_BUFINT     0x0c00   /* set bits: AE, AF */
-#define TIFM_MMCSD_DPE        0x0020   /* data timeout counted in kilocycles */
-#define TIFM_MMCSD_INAB       0x0080   /* abort / initialize command */
-#define TIFM_MMCSD_READ       0x8000
-
-#define TIFM_MMCSD_DATAMASK   0x401d   /* set bits: CERR, EOFB, BRS, CB, EOC */
-#define TIFM_MMCSD_ERRMASK    0x01e0   /* set bits: CCRC, CTO, DCRC, DTO */
-#define TIFM_MMCSD_EOC        0x0001   /* end of command phase  */
-#define TIFM_MMCSD_CB         0x0004   /* card enter busy state */
-#define TIFM_MMCSD_BRS        0x0008   /* block received/sent   */
-#define TIFM_MMCSD_EOFB       0x0010   /* card exit busy state  */
-#define TIFM_MMCSD_DTO        0x0020   /* data time-out         */
-#define TIFM_MMCSD_DCRC       0x0040   /* data crc error        */
-#define TIFM_MMCSD_CTO        0x0080   /* command time-out      */
-#define TIFM_MMCSD_CCRC       0x0100   /* command crc error     */
-#define TIFM_MMCSD_AF         0x0400   /* fifo almost full      */
-#define TIFM_MMCSD_AE         0x0800   /* fifo almost empty     */
-#define TIFM_MMCSD_CERR       0x4000   /* card status error     */
-
-#define TIFM_MMCSD_FIFO_SIZE  0x0020
-
-#define TIFM_MMCSD_RSP_R0     0x0000
-#define TIFM_MMCSD_RSP_R1     0x0100
-#define TIFM_MMCSD_RSP_R2     0x0200
-#define TIFM_MMCSD_RSP_R3     0x0300
-#define TIFM_MMCSD_RSP_R4     0x0400
-#define TIFM_MMCSD_RSP_R5     0x0500
-#define TIFM_MMCSD_RSP_R6     0x0600
-
-#define TIFM_MMCSD_RSP_BUSY   0x0800
-
-#define TIFM_MMCSD_CMD_BC     0x0000
-#define TIFM_MMCSD_CMD_BCR    0x1000
-#define TIFM_MMCSD_CMD_AC     0x2000
-#define TIFM_MMCSD_CMD_ADTC   0x3000
-
-typedef enum {
-       IDLE = 0,
-       CMD,    /* main command ended                   */
-       BRS,    /* block transfer finished              */
-       SCMD,   /* stop command ended                   */
-       CARD,   /* card left busy state                 */
-       FIFO,   /* FIFO operation completed (uncertain) */
-       READY
-} card_state_t;
-
-enum {
-       FIFO_RDY   = 0x0001,     /* hardware dependent value */
-       EJECT      = 0x0004,
-       EJECT_DONE = 0x0008,
-       CARD_BUSY  = 0x0010,
-       OPENDRAIN  = 0x0040,     /* hardware dependent value */
-       CARD_EVENT = 0x0100,     /* hardware dependent value */
-       CARD_RO    = 0x0200,     /* hardware dependent value */
-       FIFO_EVENT = 0x10000 };  /* hardware dependent value */
-
-struct tifm_sd {
-       struct tifm_dev     *dev;
-
-       unsigned int        flags;
-       card_state_t        state;
-       unsigned int        clk_freq;
-       unsigned int        clk_div;
-       unsigned long       timeout_jiffies;
-
-       struct tasklet_struct finish_tasklet;
-       struct timer_list     timer;
-       struct mmc_request    *req;
-       wait_queue_head_t     notify;
-
-       size_t                written_blocks;
-       size_t                buffer_size;
-       size_t                buffer_pos;
-
-};
-
-static char* tifm_sd_data_buffer(struct mmc_data *data)
-{
-       return page_address(data->sg->page) + data->sg->offset;
-}
-
-static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host,
-                                unsigned int host_status)
-{
-       struct mmc_command *cmd = host->req->cmd;
-       unsigned int t_val = 0, cnt = 0;
-       char *buffer;
-
-       if (host_status & TIFM_MMCSD_BRS) {
-               /* in non-dma rx mode BRS fires when fifo is still not empty */
-               if (no_dma && (cmd->data->flags & MMC_DATA_READ)) {
-                       buffer = tifm_sd_data_buffer(host->req->data);
-                       while (host->buffer_size > host->buffer_pos) {
-                               t_val = readl(sock->addr + SOCK_MMCSD_DATA);
-                               buffer[host->buffer_pos++] = t_val & 0xff;
-                               buffer[host->buffer_pos++] =
-                                                       (t_val >> 8) & 0xff;
-                       }
-               }
-               return 1;
-       } else if (no_dma) {
-               buffer = tifm_sd_data_buffer(host->req->data);
-               if ((cmd->data->flags & MMC_DATA_READ) &&
-                               (host_status & TIFM_MMCSD_AF)) {
-                       for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) {
-                               t_val = readl(sock->addr + SOCK_MMCSD_DATA);
-                               if (host->buffer_size > host->buffer_pos) {
-                                       buffer[host->buffer_pos++] =
-                                                       t_val & 0xff;
-                                       buffer[host->buffer_pos++] =
-                                                       (t_val >> 8) & 0xff;
-                               }
-                       }
-               } else if ((cmd->data->flags & MMC_DATA_WRITE)
-                          && (host_status & TIFM_MMCSD_AE)) {
-                       for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) {
-                               if (host->buffer_size > host->buffer_pos) {
-                                       t_val = buffer[host->buffer_pos++]
-                                               & 0x00ff;
-                                       t_val |= ((buffer[host->buffer_pos++])
-                                                 << 8) & 0xff00;
-                                       writel(t_val,
-                                              sock->addr + SOCK_MMCSD_DATA);
-                               }
-                       }
-               }
-       }
-       return 0;
-}
-
-static unsigned int tifm_sd_op_flags(struct mmc_command *cmd)
-{
-       unsigned int rc = 0;
-
-       switch (mmc_resp_type(cmd)) {
-       case MMC_RSP_NONE:
-               rc |= TIFM_MMCSD_RSP_R0;
-               break;
-       case MMC_RSP_R1B:
-               rc |= TIFM_MMCSD_RSP_BUSY; // deliberate fall-through
-       case MMC_RSP_R1:
-               rc |= TIFM_MMCSD_RSP_R1;
-               break;
-       case MMC_RSP_R2:
-               rc |= TIFM_MMCSD_RSP_R2;
-               break;
-       case MMC_RSP_R3:
-               rc |= TIFM_MMCSD_RSP_R3;
-               break;
-       default:
-               BUG();
-       }
-
-       switch (mmc_cmd_type(cmd)) {
-       case MMC_CMD_BC:
-               rc |= TIFM_MMCSD_CMD_BC;
-               break;
-       case MMC_CMD_BCR:
-               rc |= TIFM_MMCSD_CMD_BCR;
-               break;
-       case MMC_CMD_AC:
-               rc |= TIFM_MMCSD_CMD_AC;
-               break;
-       case MMC_CMD_ADTC:
-               rc |= TIFM_MMCSD_CMD_ADTC;
-               break;
-       default:
-               BUG();
-       }
-       return rc;
-}
-
-static void tifm_sd_exec(struct tifm_sd *host, struct mmc_command *cmd)
-{
-       struct tifm_dev *sock = host->dev;
-       unsigned int cmd_mask = tifm_sd_op_flags(cmd) |
-                               (host->flags & OPENDRAIN);
-
-       if (cmd->data && (cmd->data->flags & MMC_DATA_READ))
-               cmd_mask |= TIFM_MMCSD_READ;
-
-       dev_dbg(&sock->dev, "executing opcode 0x%x, arg: 0x%x, mask: 0x%x\n",
-               cmd->opcode, cmd->arg, cmd_mask);
-
-       writel((cmd->arg >> 16) & 0xffff, sock->addr + SOCK_MMCSD_ARG_HIGH);
-       writel(cmd->arg & 0xffff, sock->addr + SOCK_MMCSD_ARG_LOW);
-       writel(cmd->opcode | cmd_mask, sock->addr + SOCK_MMCSD_COMMAND);
-}
-
-static void tifm_sd_fetch_resp(struct mmc_command *cmd, struct tifm_dev *sock)
-{
-       cmd->resp[0] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x1c) << 16)
-                      | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x18);
-       cmd->resp[1] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x14) << 16)
-                      | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x10);
-       cmd->resp[2] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x0c) << 16)
-                      | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x08);
-       cmd->resp[3] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x04) << 16)
-                      | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x00);
-}
-
-static void tifm_sd_process_cmd(struct tifm_dev *sock, struct tifm_sd *host,
-                                      unsigned int host_status)
-{
-       struct mmc_command *cmd = host->req->cmd;
-
-change_state:
-       switch (host->state) {
-       case IDLE:
-               return;
-       case CMD:
-               if (host_status & (TIFM_MMCSD_EOC | TIFM_MMCSD_CERR)) {
-                       tifm_sd_fetch_resp(cmd, sock);
-                       if (cmd->data) {
-                               host->state = BRS;
-                       } else {
-                               host->state = READY;
-                       }
-                       goto change_state;
-               }
-               break;
-       case BRS:
-               if (tifm_sd_transfer_data(sock, host, host_status)) {
-                       if (cmd->data->flags & MMC_DATA_WRITE) {
-                               host->state = CARD;
-                       } else {
-                               if (no_dma) {
-                                       if (host->req->stop) {
-                                               tifm_sd_exec(host, host->req->stop);
-                                               host->state = SCMD;
-                                       } else {
-                                               host->state = READY;
-                                       }
-                               } else {
-                                       host->state = FIFO;
-                               }
-                       }
-                       goto change_state;
-               }
-               break;
-       case SCMD:
-               if (host_status & TIFM_MMCSD_EOC) {
-                       tifm_sd_fetch_resp(host->req->stop, sock);
-                       host->state = READY;
-                       goto change_state;
-               }
-               break;
-       case CARD:
-               dev_dbg(&sock->dev, "waiting for CARD, have %zd blocks\n",
-                       host->written_blocks);
-               if (!(host->flags & CARD_BUSY)
-                   && (host->written_blocks == cmd->data->blocks)) {
-                       if (no_dma) {
-                               if (host->req->stop) {
-                                       tifm_sd_exec(host, host->req->stop);
-                                       host->state = SCMD;
-                               } else {
-                                       host->state = READY;
-                               }
-                       } else {
-                               host->state = FIFO;
-                       }
-                       goto change_state;
-               }
-               break;
-       case FIFO:
-               if (host->flags & FIFO_RDY) {
-                       host->flags &= ~FIFO_RDY;
-                       if (host->req->stop) {
-                               tifm_sd_exec(host, host->req->stop);
-                               host->state = SCMD;
-                       } else {
-                               host->state = READY;
-                       }
-                       goto change_state;
-               }
-               break;
-       case READY:
-               tasklet_schedule(&host->finish_tasklet);
-               return;
-       }
-
-}
-
-/* Called from interrupt handler */
-static void tifm_sd_signal_irq(struct tifm_dev *sock,
-                              unsigned int sock_irq_status)
-{
-       struct tifm_sd *host;
-       unsigned int host_status = 0, fifo_status = 0;
-       int error_code = 0;
-
-       spin_lock(&sock->lock);
-       host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock));
-
-       if (sock_irq_status & FIFO_EVENT) {
-               fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS);
-               writel(fifo_status, sock->addr + SOCK_DMA_FIFO_STATUS);
-
-               host->flags |= fifo_status & FIFO_RDY;
-       }
-
-       if (sock_irq_status & CARD_EVENT) {
-               host_status = readl(sock->addr + SOCK_MMCSD_STATUS);
-               writel(host_status, sock->addr + SOCK_MMCSD_STATUS);
-
-               if (!host->req)
-                       goto done;
-
-               if (host_status & TIFM_MMCSD_ERRMASK) {
-                       if (host_status & (TIFM_MMCSD_CTO | TIFM_MMCSD_DTO))
-                               error_code = MMC_ERR_TIMEOUT;
-                       else if (host_status
-                                & (TIFM_MMCSD_CCRC | TIFM_MMCSD_DCRC))
-                               error_code = MMC_ERR_BADCRC;
-
-                       writel(TIFM_FIFO_INT_SETALL,
-                              sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
-                       writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
-
-                       if (host->req->stop) {
-                               if (host->state == SCMD) {
-                                       host->req->stop->error = error_code;
-                               } else if (host->state == BRS
-                                          || host->state == CARD
-                                          || host->state == FIFO) {
-                                       host->req->cmd->error = error_code;
-                                       tifm_sd_exec(host, host->req->stop);
-                                       host->state = SCMD;
-                                       goto done;
-                               } else {
-                                       host->req->cmd->error = error_code;
-                               }
-                       } else {
-                               host->req->cmd->error = error_code;
-                       }
-                       host->state = READY;
-               }
-
-               if (host_status & TIFM_MMCSD_CB)
-                       host->flags |= CARD_BUSY;
-               if ((host_status & TIFM_MMCSD_EOFB)
-                   && (host->flags & CARD_BUSY)) {
-                       host->written_blocks++;
-                       host->flags &= ~CARD_BUSY;
-               }
-        }
-
-       if (host->req)
-               tifm_sd_process_cmd(sock, host, host_status);
-done:
-       dev_dbg(&sock->dev, "host_status %x, fifo_status %x\n",
-               host_status, fifo_status);
-       spin_unlock(&sock->lock);
-}
-
-static void tifm_sd_prepare_data(struct tifm_sd *host, struct mmc_command *cmd)
-{
-       struct tifm_dev *sock = host->dev;
-       unsigned int dest_cnt;
-
-       /* DMA style IO */
-       dev_dbg(&sock->dev, "setting dma for %d blocks\n",
-               cmd->data->blocks);
-       writel(TIFM_FIFO_INT_SETALL,
-              sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
-       writel(ilog2(cmd->data->blksz) - 2,
-              sock->addr + SOCK_FIFO_PAGE_SIZE);
-       writel(TIFM_FIFO_ENABLE, sock->addr + SOCK_FIFO_CONTROL);
-       writel(TIFM_FIFO_INTMASK, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
-
-       dest_cnt = (cmd->data->blocks) << 8;
-
-       writel(sg_dma_address(cmd->data->sg), sock->addr + SOCK_DMA_ADDRESS);
-
-       writel(cmd->data->blocks - 1, sock->addr + SOCK_MMCSD_NUM_BLOCKS);
-       writel(cmd->data->blksz - 1, sock->addr + SOCK_MMCSD_BLOCK_LEN);
-
-       if (cmd->data->flags & MMC_DATA_WRITE) {
-               writel(TIFM_MMCSD_TXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
-               writel(dest_cnt | TIFM_DMA_TX | TIFM_DMA_EN,
-                      sock->addr + SOCK_DMA_CONTROL);
-       } else {
-               writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
-               writel(dest_cnt | TIFM_DMA_EN, sock->addr + SOCK_DMA_CONTROL);
-       }
-}
-
-static void tifm_sd_set_data_timeout(struct tifm_sd *host,
-                                    struct mmc_data *data)
-{
-       struct tifm_dev *sock = host->dev;
-       unsigned int data_timeout = data->timeout_clks;
-
-       if (fixed_timeout)
-               return;
-
-       data_timeout += data->timeout_ns /
-                       ((1000000000UL / host->clk_freq) * host->clk_div);
-
-       if (data_timeout < 0xffff) {
-               writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO);
-               writel((~TIFM_MMCSD_DPE)
-                      & readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG),
-                      sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG);
-       } else {
-               data_timeout = (data_timeout >> 10) + 1;
-               if (data_timeout > 0xffff)
-                       data_timeout = 0;       /* set to unlimited */
-               writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO);
-               writel(TIFM_MMCSD_DPE
-                      | readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG),
-                      sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG);
-       }
-}
-
-static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq)
-{
-       struct tifm_sd *host = mmc_priv(mmc);
-       struct tifm_dev *sock = host->dev;
-       unsigned long flags;
-       int sg_count = 0;
-       struct mmc_data *r_data = mrq->cmd->data;
-
-       spin_lock_irqsave(&sock->lock, flags);
-       if (host->flags & EJECT) {
-               spin_unlock_irqrestore(&sock->lock, flags);
-               goto err_out;
-       }
-
-       if (host->req) {
-               printk(KERN_ERR DRIVER_NAME ": unfinished request detected\n");
-               spin_unlock_irqrestore(&sock->lock, flags);
-               goto err_out;
-       }
-
-       if (r_data) {
-               tifm_sd_set_data_timeout(host, r_data);
-
-               sg_count = tifm_map_sg(sock, r_data->sg, r_data->sg_len,
-                                      mrq->cmd->flags & MMC_DATA_WRITE
-                                      ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-               if (sg_count != 1) {
-                       printk(KERN_ERR DRIVER_NAME
-                               ": scatterlist map failed\n");
-                       spin_unlock_irqrestore(&sock->lock, flags);
-                       goto err_out;
-               }
-
-               host->written_blocks = 0;
-               host->flags &= ~CARD_BUSY;
-               tifm_sd_prepare_data(host, mrq->cmd);
-       }
-
-       host->req = mrq;
-       mod_timer(&host->timer, jiffies + host->timeout_jiffies);
-       host->state = CMD;
-       writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL),
-              sock->addr + SOCK_CONTROL);
-       tifm_sd_exec(host, mrq->cmd);
-       spin_unlock_irqrestore(&sock->lock, flags);
-       return;
-
-err_out:
-       if (sg_count > 0)
-               tifm_unmap_sg(sock, r_data->sg, r_data->sg_len,
-                             (r_data->flags & MMC_DATA_WRITE)
-                             ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-
-       mrq->cmd->error = MMC_ERR_TIMEOUT;
-       mmc_request_done(mmc, mrq);
-}
-
-static void tifm_sd_end_cmd(unsigned long data)
-{
-       struct tifm_sd *host = (struct tifm_sd*)data;
-       struct tifm_dev *sock = host->dev;
-       struct mmc_host *mmc = tifm_get_drvdata(sock);
-       struct mmc_request *mrq;
-       struct mmc_data *r_data = NULL;
-       unsigned long flags;
-
-       spin_lock_irqsave(&sock->lock, flags);
-
-       del_timer(&host->timer);
-       mrq = host->req;
-       host->req = NULL;
-       host->state = IDLE;
-
-       if (!mrq) {
-               printk(KERN_ERR DRIVER_NAME ": no request to complete?\n");
-               spin_unlock_irqrestore(&sock->lock, flags);
-               return;
-       }
-
-       r_data = mrq->cmd->data;
-       if (r_data) {
-               if (r_data->flags & MMC_DATA_WRITE) {
-                       r_data->bytes_xfered = host->written_blocks
-                                              * r_data->blksz;
-               } else {
-                       r_data->bytes_xfered = r_data->blocks -
-                               readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1;
-                       r_data->bytes_xfered *= r_data->blksz;
-                       r_data->bytes_xfered += r_data->blksz -
-                               readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1;
-               }
-               tifm_unmap_sg(sock, r_data->sg, r_data->sg_len,
-                             (r_data->flags & MMC_DATA_WRITE)
-                             ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-       }
-
-       writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
-              sock->addr + SOCK_CONTROL);
-
-       spin_unlock_irqrestore(&sock->lock, flags);
-       mmc_request_done(mmc, mrq);
-}
-
-static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq)
-{
-       struct tifm_sd *host = mmc_priv(mmc);
-       struct tifm_dev *sock = host->dev;
-       unsigned long flags;
-       struct mmc_data *r_data = mrq->cmd->data;
-
-       spin_lock_irqsave(&sock->lock, flags);
-       if (host->flags & EJECT) {
-               spin_unlock_irqrestore(&sock->lock, flags);
-               goto err_out;
-       }
-
-       if (host->req) {
-               printk(KERN_ERR DRIVER_NAME ": unfinished request detected\n");
-               spin_unlock_irqrestore(&sock->lock, flags);
-               goto err_out;
-       }
-
-       if (r_data) {
-               tifm_sd_set_data_timeout(host, r_data);
-
-               host->buffer_size = mrq->cmd->data->blocks
-                                   * mrq->cmd->data->blksz;
-
-               writel(TIFM_MMCSD_BUFINT
-                      | readl(sock->addr + SOCK_MMCSD_INT_ENABLE),
-                      sock->addr + SOCK_MMCSD_INT_ENABLE);
-               writel(((TIFM_MMCSD_FIFO_SIZE - 1) << 8)
-                      | (TIFM_MMCSD_FIFO_SIZE - 1),
-                      sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
-
-               host->written_blocks = 0;
-               host->flags &= ~CARD_BUSY;
-               host->buffer_pos = 0;
-               writel(r_data->blocks - 1, sock->addr + SOCK_MMCSD_NUM_BLOCKS);
-               writel(r_data->blksz - 1, sock->addr + SOCK_MMCSD_BLOCK_LEN);
-       }
-
-       host->req = mrq;
-       mod_timer(&host->timer, jiffies + host->timeout_jiffies);
-       host->state = CMD;
-       writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL),
-              sock->addr + SOCK_CONTROL);
-       tifm_sd_exec(host, mrq->cmd);
-       spin_unlock_irqrestore(&sock->lock, flags);
-       return;
-
-err_out:
-       mrq->cmd->error = MMC_ERR_TIMEOUT;
-       mmc_request_done(mmc, mrq);
-}
-
-static void tifm_sd_end_cmd_nodma(unsigned long data)
-{
-       struct tifm_sd *host = (struct tifm_sd*)data;
-       struct tifm_dev *sock = host->dev;
-       struct mmc_host *mmc = tifm_get_drvdata(sock);
-       struct mmc_request *mrq;
-       struct mmc_data *r_data = NULL;
-       unsigned long flags;
-
-       spin_lock_irqsave(&sock->lock, flags);
-
-       del_timer(&host->timer);
-       mrq = host->req;
-       host->req = NULL;
-       host->state = IDLE;
-
-       if (!mrq) {
-               printk(KERN_ERR DRIVER_NAME ": no request to complete?\n");
-               spin_unlock_irqrestore(&sock->lock, flags);
-               return;
-       }
-
-       r_data = mrq->cmd->data;
-       if (r_data) {
-               writel((~TIFM_MMCSD_BUFINT) &
-                       readl(sock->addr + SOCK_MMCSD_INT_ENABLE),
-                       sock->addr + SOCK_MMCSD_INT_ENABLE);
-
-               if (r_data->flags & MMC_DATA_WRITE) {
-                       r_data->bytes_xfered = host->written_blocks
-                                              * r_data->blksz;
-               } else {
-                       r_data->bytes_xfered = r_data->blocks -
-                               readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1;
-                       r_data->bytes_xfered *= r_data->blksz;
-                       r_data->bytes_xfered += r_data->blksz -
-                               readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1;
-               }
-               host->buffer_pos = 0;
-               host->buffer_size = 0;
-       }
-
-       writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
-              sock->addr + SOCK_CONTROL);
-
-       spin_unlock_irqrestore(&sock->lock, flags);
-
-       mmc_request_done(mmc, mrq);
-}
-
-static void tifm_sd_terminate(struct tifm_sd *host)
-{
-       struct tifm_dev *sock = host->dev;
-       unsigned long flags;
-
-       writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
-       mmiowb();
-       spin_lock_irqsave(&sock->lock, flags);
-       host->flags |= EJECT;
-       if (host->req) {
-               writel(TIFM_FIFO_INT_SETALL,
-                      sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
-               writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
-               tasklet_schedule(&host->finish_tasklet);
-       }
-       spin_unlock_irqrestore(&sock->lock, flags);
-}
-
-static void tifm_sd_abort(unsigned long data)
-{
-       struct tifm_sd *host = (struct tifm_sd*)data;
-
-       printk(KERN_ERR DRIVER_NAME
-              ": card failed to respond for a long period of time");
-
-       tifm_sd_terminate(host);
-       tifm_eject(host->dev);
-}
-
-static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-{
-       struct tifm_sd *host = mmc_priv(mmc);
-       struct tifm_dev *sock = host->dev;
-       unsigned int clk_div1, clk_div2;
-       unsigned long flags;
-
-       spin_lock_irqsave(&sock->lock, flags);
-
-       dev_dbg(&sock->dev, "Setting bus width %d, power %d\n", ios->bus_width,
-               ios->power_mode);
-       if (ios->bus_width == MMC_BUS_WIDTH_4) {
-               writel(TIFM_MMCSD_4BBUS | readl(sock->addr + SOCK_MMCSD_CONFIG),
-                      sock->addr + SOCK_MMCSD_CONFIG);
-       } else {
-               writel((~TIFM_MMCSD_4BBUS)
-                      & readl(sock->addr + SOCK_MMCSD_CONFIG),
-                      sock->addr + SOCK_MMCSD_CONFIG);
-       }
-
-       if (ios->clock) {
-               clk_div1 = 20000000 / ios->clock;
-               if (!clk_div1)
-                       clk_div1 = 1;
-
-               clk_div2 = 24000000 / ios->clock;
-               if (!clk_div2)
-                       clk_div2 = 1;
-
-               if ((20000000 / clk_div1) > ios->clock)
-                       clk_div1++;
-               if ((24000000 / clk_div2) > ios->clock)
-                       clk_div2++;
-               if ((20000000 / clk_div1) > (24000000 / clk_div2)) {
-                       host->clk_freq = 20000000;
-                       host->clk_div = clk_div1;
-                       writel((~TIFM_CTRL_FAST_CLK)
-                              & readl(sock->addr + SOCK_CONTROL),
-                              sock->addr + SOCK_CONTROL);
-               } else {
-                       host->clk_freq = 24000000;
-                       host->clk_div = clk_div2;
-                       writel(TIFM_CTRL_FAST_CLK
-                              | readl(sock->addr + SOCK_CONTROL),
-                              sock->addr + SOCK_CONTROL);
-               }
-       } else {
-               host->clk_div = 0;
-       }
-       host->clk_div &= TIFM_MMCSD_CLKMASK;
-       writel(host->clk_div
-              | ((~TIFM_MMCSD_CLKMASK)
-                 & readl(sock->addr + SOCK_MMCSD_CONFIG)),
-              sock->addr + SOCK_MMCSD_CONFIG);
-
-       if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
-               host->flags |= OPENDRAIN;
-       else
-               host->flags &= ~OPENDRAIN;
-
-       /* chip_select : maybe later */
-       //vdd
-       //power is set before probe / after remove
-       //I believe, power_off when already marked for eject is sufficient to
-       // allow removal.
-       if ((host->flags & EJECT) && ios->power_mode == MMC_POWER_OFF) {
-               host->flags |= EJECT_DONE;
-               wake_up_all(&host->notify);
-       }
-
-       spin_unlock_irqrestore(&sock->lock, flags);
-}
-
-static int tifm_sd_ro(struct mmc_host *mmc)
-{
-       int rc;
-       struct tifm_sd *host = mmc_priv(mmc);
-       struct tifm_dev *sock = host->dev;
-       unsigned long flags;
-
-       spin_lock_irqsave(&sock->lock, flags);
-
-       host->flags |= (CARD_RO & readl(sock->addr + SOCK_PRESENT_STATE));
-       rc = (host->flags & CARD_RO) ? 1 : 0;
-
-       spin_unlock_irqrestore(&sock->lock, flags);
-       return rc;
-}
-
-static struct mmc_host_ops tifm_sd_ops = {
-       .request = tifm_sd_request,
-       .set_ios = tifm_sd_ios,
-       .get_ro  = tifm_sd_ro
-};
-
-static int tifm_sd_initialize_host(struct tifm_sd *host)
-{
-       int rc;
-       unsigned int host_status = 0;
-       struct tifm_dev *sock = host->dev;
-
-       writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
-       mmiowb();
-       host->clk_div = 61;
-       host->clk_freq = 20000000;
-       writel(TIFM_MMCSD_RESET, sock->addr + SOCK_MMCSD_SYSTEM_CONTROL);
-       writel(host->clk_div | TIFM_MMCSD_POWER,
-              sock->addr + SOCK_MMCSD_CONFIG);
-
-       /* wait up to 0.51 sec for reset */
-       for (rc = 2; rc <= 256; rc <<= 1) {
-               if (1 & readl(sock->addr + SOCK_MMCSD_SYSTEM_STATUS)) {
-                       rc = 0;
-                       break;
-               }
-               msleep(rc);
-       }
-
-       if (rc) {
-               printk(KERN_ERR DRIVER_NAME
-                      ": controller failed to reset\n");
-               return -ENODEV;
-       }
-
-       writel(0, sock->addr + SOCK_MMCSD_NUM_BLOCKS);
-       writel(host->clk_div | TIFM_MMCSD_POWER,
-              sock->addr + SOCK_MMCSD_CONFIG);
-       writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
-
-       // command timeout fixed to 64 clocks for now
-       writel(64, sock->addr + SOCK_MMCSD_COMMAND_TO);
-       writel(TIFM_MMCSD_INAB, sock->addr + SOCK_MMCSD_COMMAND);
-
-       /* INAB should take much less than reset */
-       for (rc = 1; rc <= 16; rc <<= 1) {
-               host_status = readl(sock->addr + SOCK_MMCSD_STATUS);
-               writel(host_status, sock->addr + SOCK_MMCSD_STATUS);
-               if (!(host_status & TIFM_MMCSD_ERRMASK)
-                   && (host_status & TIFM_MMCSD_EOC)) {
-                       rc = 0;
-                       break;
-               }
-               msleep(rc);
-       }
-
-       if (rc) {
-               printk(KERN_ERR DRIVER_NAME
-                      ": card not ready - probe failed on initialization\n");
-               return -ENODEV;
-       }
-
-       writel(TIFM_MMCSD_DATAMASK | TIFM_MMCSD_ERRMASK,
-              sock->addr + SOCK_MMCSD_INT_ENABLE);
-       mmiowb();
-
-       return 0;
-}
-
-static int tifm_sd_probe(struct tifm_dev *sock)
-{
-       struct mmc_host *mmc;
-       struct tifm_sd *host;
-       int rc = -EIO;
-
-       if (!(TIFM_SOCK_STATE_OCCUPIED
-             & readl(sock->addr + SOCK_PRESENT_STATE))) {
-               printk(KERN_WARNING DRIVER_NAME ": card gone, unexpectedly\n");
-               return rc;
-       }
-
-       mmc = mmc_alloc_host(sizeof(struct tifm_sd), &sock->dev);
-       if (!mmc)
-               return -ENOMEM;
-
-       host = mmc_priv(mmc);
-       tifm_set_drvdata(sock, mmc);
-       host->dev = sock;
-       host->timeout_jiffies = msecs_to_jiffies(1000);
-
-       init_waitqueue_head(&host->notify);
-       tasklet_init(&host->finish_tasklet,
-                    no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd,
-                    (unsigned long)host);
-       setup_timer(&host->timer, tifm_sd_abort, (unsigned long)host);
-
-       tifm_sd_ops.request = no_dma ? tifm_sd_request_nodma : tifm_sd_request;
-       mmc->ops = &tifm_sd_ops;
-       mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-       mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE;
-       mmc->f_min = 20000000 / 60;
-       mmc->f_max = 24000000;
-       mmc->max_hw_segs = 1;
-       mmc->max_phys_segs = 1;
-       // limited by DMA counter - it's safer to stick with
-       // block counter has 11 bits though
-       mmc->max_blk_count = 256;
-       // 2k maximum hw block length
-       mmc->max_blk_size = 2048;
-       mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
-       mmc->max_seg_size = mmc->max_req_size;
-       sock->signal_irq = tifm_sd_signal_irq;
-       rc = tifm_sd_initialize_host(host);
-
-       if (!rc)
-               rc = mmc_add_host(mmc);
-       if (rc)
-               goto out_free_mmc;
-
-       return 0;
-out_free_mmc:
-       mmc_free_host(mmc);
-       return rc;
-}
-
-static void tifm_sd_remove(struct tifm_dev *sock)
-{
-       struct mmc_host *mmc = tifm_get_drvdata(sock);
-       struct tifm_sd *host = mmc_priv(mmc);
-
-       del_timer_sync(&host->timer);
-       tifm_sd_terminate(host);
-       wait_event_timeout(host->notify, host->flags & EJECT_DONE,
-                          host->timeout_jiffies);
-       tasklet_kill(&host->finish_tasklet);
-       mmc_remove_host(mmc);
-
-       /* The meaning of the bit majority in this constant is unknown. */
-       writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
-              sock->addr + SOCK_CONTROL);
-
-       tifm_set_drvdata(sock, NULL);
-       mmc_free_host(mmc);
-}
-
-#ifdef CONFIG_PM
-
-static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state)
-{
-       struct mmc_host *mmc = tifm_get_drvdata(sock);
-       int rc;
-
-       rc = mmc_suspend_host(mmc, state);
-       /* The meaning of the bit majority in this constant is unknown. */
-       writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
-              sock->addr + SOCK_CONTROL);
-       return rc;
-}
-
-static int tifm_sd_resume(struct tifm_dev *sock)
-{
-       struct mmc_host *mmc = tifm_get_drvdata(sock);
-       struct tifm_sd *host = mmc_priv(mmc);
-
-       if (sock->media_id != FM_SD
-           || tifm_sd_initialize_host(host)) {
-               tifm_eject(sock);
-               return 0;
-       } else {
-               return mmc_resume_host(mmc);
-       }
-}
-
-#else
-
-#define tifm_sd_suspend NULL
-#define tifm_sd_resume NULL
-
-#endif /* CONFIG_PM */
-
-static tifm_media_id tifm_sd_id_tbl[] = {
-       FM_SD, 0
-};
-
-static struct tifm_driver tifm_sd_driver = {
-       .driver = {
-               .name  = DRIVER_NAME,
-               .owner = THIS_MODULE
-       },
-       .id_table = tifm_sd_id_tbl,
-       .probe    = tifm_sd_probe,
-       .remove   = tifm_sd_remove,
-       .suspend  = tifm_sd_suspend,
-       .resume   = tifm_sd_resume
-};
-
-static int __init tifm_sd_init(void)
-{
-       return tifm_register_driver(&tifm_sd_driver);
-}
-
-static void __exit tifm_sd_exit(void)
-{
-       tifm_unregister_driver(&tifm_sd_driver);
-}
-
-MODULE_AUTHOR("Alex Dubov");
-MODULE_DESCRIPTION("TI FlashMedia SD driver");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(tifm, tifm_sd_id_tbl);
-MODULE_VERSION(DRIVER_VERSION);
-
-module_init(tifm_sd_init);
-module_exit(tifm_sd_exit);
index 8a0c4de..c73e96b 100644 (file)
@@ -13,7 +13,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/miscdevice.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
index 6f368ae..6413efc 100644 (file)
@@ -13,7 +13,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/miscdevice.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/init.h>
index 88ba82d..2b30b58 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/miscdevice.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/init.h>
index 52b5d63..fd8a8da 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/miscdevice.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/init.h>
index acf3ba2..ecac0e4 100644 (file)
@@ -31,7 +31,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/miscdevice.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/init.h>
index 8296305..89deff0 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand_ecc.h>
index e6ef7d7..0c9ce19 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/miscdevice.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/init.h>
index d396f99..0877fc3 100644 (file)
@@ -565,9 +565,9 @@ int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
         ib->btx_ring [entry].length = (-len) | 0xf000;
         ib->btx_ring [entry].misc = 0;
 
-       if (skb->len < ETH_ZLEN)
-               memset((char *)&ib->tx_buf[entry][0], 0, ETH_ZLEN);
-        skb_copy_from_linear_data(skb, &ib->tx_buf[entry][0], skblen);
+       if (skb->len < ETH_ZLEN)
+               memset((void *)&ib->tx_buf[entry][0], 0, ETH_ZLEN);
+        skb_copy_from_linear_data(skb, (void *)&ib->tx_buf[entry][0], skblen);
 
         /* Now, give the packet to the lance */
         ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN);
index dcdad21..69dba62 100644 (file)
@@ -311,7 +311,7 @@ config MAC8390
 
 config MAC89x0
        tristate "Macintosh CS89x0 based ethernet cards"
-       depends on NET_ETHERNET && MAC && BROKEN
+       depends on NET_ETHERNET && MAC
        ---help---
          Support for CS89x0 chipset based Ethernet cards.  If you have a
          Nubus or LC-PDS network (Ethernet) card of this type, say Y and
@@ -337,8 +337,8 @@ config MACSONIC
          be called macsonic.
 
 config MACMACE
-       bool "Macintosh (AV) onboard MACE ethernet (EXPERIMENTAL)"
-       depends on NET_ETHERNET && MAC && EXPERIMENTAL
+       bool "Macintosh (AV) onboard MACE ethernet"
+       depends on NET_ETHERNET && MAC
        select CRC32
        help
          Support for the onboard AMD 79C940 MACE Ethernet controller used in
index dd8ed45..1c3e293 100644 (file)
@@ -83,7 +83,6 @@ extern struct net_device *bagetlance_probe(int unit);
 extern struct net_device *mvme147lance_probe(int unit);
 extern struct net_device *tc515_probe(int unit);
 extern struct net_device *lance_probe(int unit);
-extern struct net_device *mace_probe(int unit);
 extern struct net_device *mac8390_probe(int unit);
 extern struct net_device *mac89x0_probe(int unit);
 extern struct net_device *mc32_probe(int unit);
@@ -274,9 +273,6 @@ static struct devprobe2 m68k_probes[] __initdata = {
 #ifdef CONFIG_MVME147_NET      /* MVME147 internal Ethernet */
        {mvme147lance_probe, 0},
 #endif
-#ifdef CONFIG_MACMACE          /* Mac 68k Quadra AV builtin Ethernet */
-       {mace_probe, 0},
-#endif
 #ifdef CONFIG_MAC8390           /* NuBus NS8390-based cards */
        {mac8390_probe, 0},
 #endif
index 1226cbb..81d5a37 100644 (file)
@@ -562,7 +562,6 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
        volatile struct lance_init_block *ib = lp->init_block;
        int entry, skblen, len;
        int status = 0;
-       static int outs;
        unsigned long flags;
 
        skblen = skb->len;
@@ -598,17 +597,16 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
        ib->btx_ring [entry].length = (-len) | 0xf000;
        ib->btx_ring [entry].misc = 0;
 
-       skb_copy_from_linear_data(skb, &ib->tx_buf [entry][0], skblen);
+       skb_copy_from_linear_data(skb, (void *)&ib->tx_buf [entry][0], skblen);
 
        /* Clear the slack of the packet, do I need this? */
        if (len != skblen)
-               memset ((char *) &ib->tx_buf [entry][skblen], 0, len - skblen);
+               memset ((void *) &ib->tx_buf [entry][skblen], 0, len - skblen);
 
        /* Now, give the packet to the lance */
        ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN);
        lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask;
-
-       outs++;
+       lp->stats.tx_bytes += skblen;
 
        if (TX_BUFFS_AVAIL <= 0)
                netif_stop_queue(dev);
index a0e68e7..a241ae7 100644 (file)
@@ -677,6 +677,7 @@ static int ariadne_start_xmit(struct sk_buff *skb, struct net_device *dev)
        priv->cur_tx -= TX_RING_SIZE;
        priv->dirty_tx -= TX_RING_SIZE;
     }
+    priv->stats.tx_bytes += len;
 
     /* Trigger an immediate send poll. */
     lance->RAP = CSR0;         /* PCnet-ISA Controller Status */
index c407214..bcd0bd8 100644 (file)
@@ -22,7 +22,6 @@
  */
 
 #include <linux/types.h>
-#include <linux/pci.h>
 #include <linux/moduleparam.h>
 #include "atl1.h"
 
index d10fb80..c39ab80 100644 (file)
@@ -45,7 +45,6 @@
 #include <linux/bitops.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
index f98a220..88b33c6 100644 (file)
@@ -1,6 +1,6 @@
 /* bnx2.c: Broadcom NX2 network driver.
  *
- * Copyright (c) 2004, 2005, 2006 Broadcom Corporation
+ * Copyright (c) 2004-2007 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -54,8 +54,8 @@
 
 #define DRV_MODULE_NAME                "bnx2"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "1.5.8"
-#define DRV_MODULE_RELDATE     "April 24, 2007"
+#define DRV_MODULE_VERSION     "1.5.10"
+#define DRV_MODULE_RELDATE     "May 1, 2007"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -84,6 +84,7 @@ typedef enum {
        BCM5708,
        BCM5708S,
        BCM5709,
+       BCM5709S,
 } board_t;
 
 /* indexed by board_t, above */
@@ -98,6 +99,7 @@ static const struct {
        { "Broadcom NetXtreme II BCM5708 1000Base-T" },
        { "Broadcom NetXtreme II BCM5708 1000Base-SX" },
        { "Broadcom NetXtreme II BCM5709 1000Base-T" },
+       { "Broadcom NetXtreme II BCM5709 1000Base-SX" },
        };
 
 static struct pci_device_id bnx2_pci_tbl[] = {
@@ -117,6 +119,8 @@ static struct pci_device_id bnx2_pci_tbl[] = {
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5708S },
        { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5709 },
+       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709S,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5709S },
        { 0, }
 };
 
@@ -230,21 +234,29 @@ static inline u32 bnx2_tx_avail(struct bnx2 *bp)
 static u32
 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset)
 {
+       u32 val;
+
+       spin_lock_bh(&bp->indirect_lock);
        REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
-       return (REG_RD(bp, BNX2_PCICFG_REG_WINDOW));
+       val = REG_RD(bp, BNX2_PCICFG_REG_WINDOW);
+       spin_unlock_bh(&bp->indirect_lock);
+       return val;
 }
 
 static void
 bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val)
 {
+       spin_lock_bh(&bp->indirect_lock);
        REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
        REG_WR(bp, BNX2_PCICFG_REG_WINDOW, val);
+       spin_unlock_bh(&bp->indirect_lock);
 }
 
 static void
 bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val)
 {
        offset += cid_addr;
+       spin_lock_bh(&bp->indirect_lock);
        if (CHIP_NUM(bp) == CHIP_NUM_5709) {
                int i;
 
@@ -262,6 +274,7 @@ bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val)
                REG_WR(bp, BNX2_CTX_DATA_ADR, offset);
                REG_WR(bp, BNX2_CTX_DATA, val);
        }
+       spin_unlock_bh(&bp->indirect_lock);
 }
 
 static int
@@ -572,8 +585,8 @@ bnx2_report_fw_link(struct bnx2 *bp)
                if (bp->autoneg) {
                        fw_link_status |= BNX2_LINK_STATUS_AN_ENABLED;
 
-                       bnx2_read_phy(bp, MII_BMSR, &bmsr);
-                       bnx2_read_phy(bp, MII_BMSR, &bmsr);
+                       bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
+                       bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
 
                        if (!(bmsr & BMSR_ANEGCOMPLETE) ||
                            bp->phy_flags & PHY_PARALLEL_DETECT_FLAG)
@@ -654,8 +667,8 @@ bnx2_resolve_flow_ctrl(struct bnx2 *bp)
                return;
        }
 
-       bnx2_read_phy(bp, MII_ADVERTISE, &local_adv);
-       bnx2_read_phy(bp, MII_LPA, &remote_adv);
+       bnx2_read_phy(bp, bp->mii_adv, &local_adv);
+       bnx2_read_phy(bp, bp->mii_lpa, &remote_adv);
 
        if (bp->phy_flags & PHY_SERDES_FLAG) {
                u32 new_local_adv = 0;
@@ -700,6 +713,45 @@ bnx2_resolve_flow_ctrl(struct bnx2 *bp)
 }
 
 static int
+bnx2_5709s_linkup(struct bnx2 *bp)
+{
+       u32 val, speed;
+
+       bp->link_up = 1;
+
+       bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_GP_STATUS);
+       bnx2_read_phy(bp, MII_BNX2_GP_TOP_AN_STATUS1, &val);
+       bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
+
+       if ((bp->autoneg & AUTONEG_SPEED) == 0) {
+               bp->line_speed = bp->req_line_speed;
+               bp->duplex = bp->req_duplex;
+               return 0;
+       }
+       speed = val & MII_BNX2_GP_TOP_AN_SPEED_MSK;
+       switch (speed) {
+               case MII_BNX2_GP_TOP_AN_SPEED_10:
+                       bp->line_speed = SPEED_10;
+                       break;
+               case MII_BNX2_GP_TOP_AN_SPEED_100:
+                       bp->line_speed = SPEED_100;
+                       break;
+               case MII_BNX2_GP_TOP_AN_SPEED_1G:
+               case MII_BNX2_GP_TOP_AN_SPEED_1GKV:
+                       bp->line_speed = SPEED_1000;
+                       break;
+               case MII_BNX2_GP_TOP_AN_SPEED_2_5G:
+                       bp->line_speed = SPEED_2500;
+                       break;
+       }
+       if (val & MII_BNX2_GP_TOP_AN_FD)
+               bp->duplex = DUPLEX_FULL;
+       else
+               bp->duplex = DUPLEX_HALF;
+       return 0;
+}
+
+static int
 bnx2_5708s_linkup(struct bnx2 *bp)
 {
        u32 val;
@@ -736,7 +788,7 @@ bnx2_5706s_linkup(struct bnx2 *bp)
        bp->link_up = 1;
        bp->line_speed = SPEED_1000;
 
-       bnx2_read_phy(bp, MII_BMCR, &bmcr);
+       bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
        if (bmcr & BMCR_FULLDPLX) {
                bp->duplex = DUPLEX_FULL;
        }
@@ -748,8 +800,8 @@ bnx2_5706s_linkup(struct bnx2 *bp)
                return 0;
        }
 
-       bnx2_read_phy(bp, MII_ADVERTISE, &local_adv);
-       bnx2_read_phy(bp, MII_LPA, &remote_adv);
+       bnx2_read_phy(bp, bp->mii_adv, &local_adv);
+       bnx2_read_phy(bp, bp->mii_lpa, &remote_adv);
 
        common = local_adv & remote_adv;
        if (common & (ADVERTISE_1000XHALF | ADVERTISE_1000XFULL)) {
@@ -770,7 +822,7 @@ bnx2_copper_linkup(struct bnx2 *bp)
 {
        u32 bmcr;
 
-       bnx2_read_phy(bp, MII_BMCR, &bmcr);
+       bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
        if (bmcr & BMCR_ANENABLE) {
                u32 local_adv, remote_adv, common;
 
@@ -787,8 +839,8 @@ bnx2_copper_linkup(struct bnx2 *bp)
                        bp->duplex = DUPLEX_HALF;
                }
                else {
-                       bnx2_read_phy(bp, MII_ADVERTISE, &local_adv);
-                       bnx2_read_phy(bp, MII_LPA, &remote_adv);
+                       bnx2_read_phy(bp, bp->mii_adv, &local_adv);
+                       bnx2_read_phy(bp, bp->mii_lpa, &remote_adv);
 
                        common = local_adv & remote_adv;
                        if (common & ADVERTISE_100FULL) {
@@ -898,6 +950,145 @@ bnx2_set_mac_link(struct bnx2 *bp)
        return 0;
 }
 
+static void
+bnx2_enable_bmsr1(struct bnx2 *bp)
+{
+       if ((bp->phy_flags & PHY_SERDES_FLAG) &&
+           (CHIP_NUM(bp) == CHIP_NUM_5709))
+               bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
+                              MII_BNX2_BLK_ADDR_GP_STATUS);
+}
+
+static void
+bnx2_disable_bmsr1(struct bnx2 *bp)
+{
+       if ((bp->phy_flags & PHY_SERDES_FLAG) &&
+           (CHIP_NUM(bp) == CHIP_NUM_5709))
+               bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
+                              MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
+}
+
+static int
+bnx2_test_and_enable_2g5(struct bnx2 *bp)
+{
+       u32 up1;
+       int ret = 1;
+
+       if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG))
+               return 0;
+
+       if (bp->autoneg & AUTONEG_SPEED)
+               bp->advertising |= ADVERTISED_2500baseX_Full;
+
+       if (CHIP_NUM(bp) == CHIP_NUM_5709)
+               bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G);
+
+       bnx2_read_phy(bp, bp->mii_up1, &up1);
+       if (!(up1 & BCM5708S_UP1_2G5)) {
+               up1 |= BCM5708S_UP1_2G5;
+               bnx2_write_phy(bp, bp->mii_up1, up1);
+               ret = 0;
+       }
+
+       if (CHIP_NUM(bp) == CHIP_NUM_5709)
+               bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
+                              MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
+
+       return ret;
+}
+
+static int
+bnx2_test_and_disable_2g5(struct bnx2 *bp)
+{
+       u32 up1;
+       int ret = 0;
+
+       if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG))
+               return 0;
+
+       if (CHIP_NUM(bp) == CHIP_NUM_5709)
+               bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G);
+
+       bnx2_read_phy(bp, bp->mii_up1, &up1);
+       if (up1 & BCM5708S_UP1_2G5) {
+               up1 &= ~BCM5708S_UP1_2G5;
+               bnx2_write_phy(bp, bp->mii_up1, up1);
+               ret = 1;
+       }
+
+       if (CHIP_NUM(bp) == CHIP_NUM_5709)
+               bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
+                              MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
+
+       return ret;
+}
+
+static void
+bnx2_enable_forced_2g5(struct bnx2 *bp)
+{
+       u32 bmcr;
+
+       if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG))
+               return;
+
+       if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+               u32 val;
+
+               bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
+                              MII_BNX2_BLK_ADDR_SERDES_DIG);
+               bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_MISC1, &val);
+               val &= ~MII_BNX2_SD_MISC1_FORCE_MSK;
+               val |= MII_BNX2_SD_MISC1_FORCE | MII_BNX2_SD_MISC1_FORCE_2_5G;
+               bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_MISC1, val);
+
+               bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
+                              MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
+               bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
+
+       } else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+               bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
+               bmcr |= BCM5708S_BMCR_FORCE_2500;
+       }
+
+       if (bp->autoneg & AUTONEG_SPEED) {
+               bmcr &= ~BMCR_ANENABLE;
+               if (bp->req_duplex == DUPLEX_FULL)
+                       bmcr |= BMCR_FULLDPLX;
+       }
+       bnx2_write_phy(bp, bp->mii_bmcr, bmcr);
+}
+
+static void
+bnx2_disable_forced_2g5(struct bnx2 *bp)
+{
+       u32 bmcr;
+
+       if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG))
+               return;
+
+       if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+               u32 val;
+
+               bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
+                              MII_BNX2_BLK_ADDR_SERDES_DIG);
+               bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_MISC1, &val);
+               val &= ~MII_BNX2_SD_MISC1_FORCE;
+               bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_MISC1, val);
+
+               bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
+                              MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
+               bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
+
+       } else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+               bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
+               bmcr &= ~BCM5708S_BMCR_FORCE_2500;
+       }
+
+       if (bp->autoneg & AUTONEG_SPEED)
+               bmcr |= BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_ANRESTART;
+       bnx2_write_phy(bp, bp->mii_bmcr, bmcr);
+}
+
 static int
 bnx2_set_link(struct bnx2 *bp)
 {
@@ -911,8 +1102,10 @@ bnx2_set_link(struct bnx2 *bp)
 
        link_up = bp->link_up;
 
-       bnx2_read_phy(bp, MII_BMSR, &bmsr);
-       bnx2_read_phy(bp, MII_BMSR, &bmsr);
+       bnx2_enable_bmsr1(bp);
+       bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr);
+       bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr);
+       bnx2_disable_bmsr1(bp);
 
        if ((bp->phy_flags & PHY_SERDES_FLAG) &&
            (CHIP_NUM(bp) == CHIP_NUM_5706)) {
@@ -933,6 +1126,8 @@ bnx2_set_link(struct bnx2 *bp)
                                bnx2_5706s_linkup(bp);
                        else if (CHIP_NUM(bp) == CHIP_NUM_5708)
                                bnx2_5708s_linkup(bp);
+                       else if (CHIP_NUM(bp) == CHIP_NUM_5709)
+                               bnx2_5709s_linkup(bp);
                }
                else {
                        bnx2_copper_linkup(bp);
@@ -941,17 +1136,9 @@ bnx2_set_link(struct bnx2 *bp)
        }
        else {
                if ((bp->phy_flags & PHY_SERDES_FLAG) &&
-                       (bp->autoneg & AUTONEG_SPEED)) {
+                   (bp->autoneg & AUTONEG_SPEED))
+                       bnx2_disable_forced_2g5(bp);
 
-                       u32 bmcr;
-
-                       bnx2_read_phy(bp, MII_BMCR, &bmcr);
-                       bmcr &= ~BCM5708S_BMCR_FORCE_2500;
-                       if (!(bmcr & BMCR_ANENABLE)) {
-                               bnx2_write_phy(bp, MII_BMCR, bmcr |
-                                       BMCR_ANENABLE);
-                       }
-               }
                bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG;
                bp->link_up = 0;
        }
@@ -971,13 +1158,13 @@ bnx2_reset_phy(struct bnx2 *bp)
        int i;
        u32 reg;
 
-        bnx2_write_phy(bp, MII_BMCR, BMCR_RESET);
+        bnx2_write_phy(bp, bp->mii_bmcr, BMCR_RESET);
 
 #define PHY_RESET_MAX_WAIT 100
        for (i = 0; i < PHY_RESET_MAX_WAIT; i++) {
                udelay(10);
 
-               bnx2_read_phy(bp, MII_BMCR, &reg);
+               bnx2_read_phy(bp, bp->mii_bmcr, &reg);
                if (!(reg & BMCR_RESET)) {
                        udelay(20);
                        break;
@@ -1026,34 +1213,40 @@ bnx2_phy_get_pause_adv(struct bnx2 *bp)
 static int
 bnx2_setup_serdes_phy(struct bnx2 *bp)
 {
-       u32 adv, bmcr, up1;
+       u32 adv, bmcr;
        u32 new_adv = 0;
 
        if (!(bp->autoneg & AUTONEG_SPEED)) {
                u32 new_bmcr;
                int force_link_down = 0;
 
-               bnx2_read_phy(bp, MII_ADVERTISE, &adv);
+               if (bp->req_line_speed == SPEED_2500) {
+                       if (!bnx2_test_and_enable_2g5(bp))
+                               force_link_down = 1;
+               } else if (bp->req_line_speed == SPEED_1000) {
+                       if (bnx2_test_and_disable_2g5(bp))
+                               force_link_down = 1;
+               }
+               bnx2_read_phy(bp, bp->mii_adv, &adv);
                adv &= ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF);
 
-               bnx2_read_phy(bp, MII_BMCR, &bmcr);
-               new_bmcr = bmcr & ~(BMCR_ANENABLE | BCM5708S_BMCR_FORCE_2500);
+               bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
+               new_bmcr = bmcr & ~BMCR_ANENABLE;
                new_bmcr |= BMCR_SPEED1000;
-               if (bp->req_line_speed == SPEED_2500) {
-                       new_bmcr |= BCM5708S_BMCR_FORCE_2500;
-                       bnx2_read_phy(bp, BCM5708S_UP1, &up1);
-                       if (!(up1 & BCM5708S_UP1_2G5)) {
-                               up1 |= BCM5708S_UP1_2G5;
-                               bnx2_write_phy(bp, BCM5708S_UP1, up1);
-                               force_link_down = 1;
+
+               if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+                       if (bp->req_line_speed == SPEED_2500)
+                               bnx2_enable_forced_2g5(bp);
+                       else if (bp->req_line_speed == SPEED_1000) {
+                               bnx2_disable_forced_2g5(bp);
+                               new_bmcr &= ~0x2000;
                        }
+
                } else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
-                       bnx2_read_phy(bp, BCM5708S_UP1, &up1);
-                       if (up1 & BCM5708S_UP1_2G5) {
-                               up1 &= ~BCM5708S_UP1_2G5;
-                               bnx2_write_phy(bp, BCM5708S_UP1, up1);
-                               force_link_down = 1;
-                       }
+                       if (bp->req_line_speed == SPEED_2500)
+                               new_bmcr |= BCM5708S_BMCR_FORCE_2500;
+                       else
+                               new_bmcr = bmcr & ~BCM5708S_BMCR_FORCE_2500;
                }
 
                if (bp->req_duplex == DUPLEX_FULL) {
@@ -1067,49 +1260,48 @@ bnx2_setup_serdes_phy(struct bnx2 *bp)
                if ((new_bmcr != bmcr) || (force_link_down)) {
                        /* Force a link down visible on the other side */
                        if (bp->link_up) {
-                               bnx2_write_phy(bp, MII_ADVERTISE, adv &
+                               bnx2_write_phy(bp, bp->mii_adv, adv &
                                               ~(ADVERTISE_1000XFULL |
                                                 ADVERTISE_1000XHALF));
-                               bnx2_write_phy(bp, MII_BMCR, bmcr |
+                               bnx2_write_phy(bp, bp->mii_bmcr, bmcr |
                                        BMCR_ANRESTART | BMCR_ANENABLE);
 
                                bp->link_up = 0;
                                netif_carrier_off(bp->dev);
-                               bnx2_write_phy(bp, MII_BMCR, new_bmcr);
+                               bnx2_write_phy(bp, bp->mii_bmcr, new_bmcr);
                                bnx2_report_link(bp);
                        }
-                       bnx2_write_phy(bp, MII_ADVERTISE, adv);
-                       bnx2_write_phy(bp, MII_BMCR, new_bmcr);
+                       bnx2_write_phy(bp, bp->mii_adv, adv);
+                       bnx2_write_phy(bp, bp->mii_bmcr, new_bmcr);
+               } else {
+                       bnx2_resolve_flow_ctrl(bp);
+                       bnx2_set_mac_link(bp);
                }
                return 0;
        }
 
-       if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) {
-               bnx2_read_phy(bp, BCM5708S_UP1, &up1);
-               up1 |= BCM5708S_UP1_2G5;
-               bnx2_write_phy(bp, BCM5708S_UP1, up1);
-       }
+       bnx2_test_and_enable_2g5(bp);
 
        if (bp->advertising & ADVERTISED_1000baseT_Full)
                new_adv |= ADVERTISE_1000XFULL;
 
        new_adv |= bnx2_phy_get_pause_adv(bp);
 
-       bnx2_read_phy(bp, MII_ADVERTISE, &adv);
-       bnx2_read_phy(bp, MII_BMCR, &bmcr);
+       bnx2_read_phy(bp, bp->mii_adv, &adv);
+       bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
 
        bp->serdes_an_pending = 0;
        if ((adv != new_adv) || ((bmcr & BMCR_ANENABLE) == 0)) {
                /* Force a link down visible on the other side */
                if (bp->link_up) {
-                       bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
+                       bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK);
                        spin_unlock_bh(&bp->phy_lock);
                        msleep(20);
                        spin_lock_bh(&bp->phy_lock);
                }
 
-               bnx2_write_phy(bp, MII_ADVERTISE, new_adv);
-               bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART |
+               bnx2_write_phy(bp, bp->mii_adv, new_adv);
+               bnx2_write_phy(bp, bp->mii_bmcr, bmcr | BMCR_ANRESTART |
                        BMCR_ANENABLE);
                /* Speed up link-up time when the link partner
                 * does not autonegotiate which is very common
@@ -1122,6 +1314,9 @@ bnx2_setup_serdes_phy(struct bnx2 *bp)
                bp->current_interval = SERDES_AN_TIMEOUT;
                bp->serdes_an_pending = 1;
                mod_timer(&bp->timer, jiffies + bp->current_interval);
+       } else {
+               bnx2_resolve_flow_ctrl(bp);
+               bnx2_set_mac_link(bp);
        }
 
        return 0;
@@ -1146,14 +1341,14 @@ bnx2_setup_copper_phy(struct bnx2 *bp)
        u32 bmcr;
        u32 new_bmcr;
 
-       bnx2_read_phy(bp, MII_BMCR, &bmcr);
+       bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
 
        if (bp->autoneg & AUTONEG_SPEED) {
                u32 adv_reg, adv1000_reg;
                u32 new_adv_reg = 0;
                u32 new_adv1000_reg = 0;
 
-               bnx2_read_phy(bp, MII_ADVERTISE, &adv_reg);
+               bnx2_read_phy(bp, bp->mii_adv, &adv_reg);
                adv_reg &= (PHY_ALL_10_100_SPEED | ADVERTISE_PAUSE_CAP |
                        ADVERTISE_PAUSE_ASYM);
 
@@ -1179,9 +1374,9 @@ bnx2_setup_copper_phy(struct bnx2 *bp)
                        (adv_reg != new_adv_reg) ||
                        ((bmcr & BMCR_ANENABLE) == 0)) {
 
-                       bnx2_write_phy(bp, MII_ADVERTISE, new_adv_reg);
+                       bnx2_write_phy(bp, bp->mii_adv, new_adv_reg);
                        bnx2_write_phy(bp, MII_CTRL1000, new_adv1000_reg);
-                       bnx2_write_phy(bp, MII_BMCR, BMCR_ANRESTART |
+                       bnx2_write_phy(bp, bp->mii_bmcr, BMCR_ANRESTART |
                                BMCR_ANENABLE);
                }
                else if (bp->link_up) {
@@ -1204,21 +1399,21 @@ bnx2_setup_copper_phy(struct bnx2 *bp)
        if (new_bmcr != bmcr) {
                u32 bmsr;
 
-               bnx2_read_phy(bp, MII_BMSR, &bmsr);
-               bnx2_read_phy(bp, MII_BMSR, &bmsr);
+               bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
+               bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
 
                if (bmsr & BMSR_LSTATUS) {
                        /* Force link down */
-                       bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
+                       bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK);
                        spin_unlock_bh(&bp->phy_lock);
                        msleep(50);
                        spin_lock_bh(&bp->phy_lock);
 
-                       bnx2_read_phy(bp, MII_BMSR, &bmsr);
-                       bnx2_read_phy(bp, MII_BMSR, &bmsr);
+                       bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
+                       bnx2_read_phy(bp, bp->mii_bmsr, &bmsr);
                }
 
-               bnx2_write_phy(bp, MII_BMCR, new_bmcr);
+               bnx2_write_phy(bp, bp->mii_bmcr, new_bmcr);
 
                /* Normally, the new speed is setup after the link has
                 * gone down and up again. In some cases, link will not go
@@ -1230,6 +1425,9 @@ bnx2_setup_copper_phy(struct bnx2 *bp)
                        bnx2_resolve_flow_ctrl(bp);
                        bnx2_set_mac_link(bp);
                }
+       } else {
+               bnx2_resolve_flow_ctrl(bp);
+               bnx2_set_mac_link(bp);
        }
        return 0;
 }
@@ -1249,10 +1447,63 @@ bnx2_setup_phy(struct bnx2 *bp)
 }
 
 static int
+bnx2_init_5709s_phy(struct bnx2 *bp)
+{
+       u32 val;
+
+       bp->mii_bmcr = MII_BMCR + 0x10;
+       bp->mii_bmsr = MII_BMSR + 0x10;
+       bp->mii_bmsr1 = MII_BNX2_GP_TOP_AN_STATUS1;
+       bp->mii_adv = MII_ADVERTISE + 0x10;
+       bp->mii_lpa = MII_LPA + 0x10;
+       bp->mii_up1 = MII_BNX2_OVER1G_UP1;
+
+       bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_AER);
+       bnx2_write_phy(bp, MII_BNX2_AER_AER, MII_BNX2_AER_AER_AN_MMD);
+
+       bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
+       bnx2_reset_phy(bp);
+
+       bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_SERDES_DIG);
+
+       bnx2_read_phy(bp, MII_BNX2_SERDES_DIG_1000XCTL1, &val);
+       val &= ~MII_BNX2_SD_1000XCTL1_AUTODET;
+       val |= MII_BNX2_SD_1000XCTL1_FIBER;
+       bnx2_write_phy(bp, MII_BNX2_SERDES_DIG_1000XCTL1, val);
+
+       bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G);
+       bnx2_read_phy(bp, MII_BNX2_OVER1G_UP1, &val);
+       if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)
+               val |= BCM5708S_UP1_2G5;
+       else
+               val &= ~BCM5708S_UP1_2G5;
+       bnx2_write_phy(bp, MII_BNX2_OVER1G_UP1, val);
+
+       bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_BAM_NXTPG);
+       bnx2_read_phy(bp, MII_BNX2_BAM_NXTPG_CTL, &val);
+       val |= MII_BNX2_NXTPG_CTL_T2 | MII_BNX2_NXTPG_CTL_BAM;
+       bnx2_write_phy(bp, MII_BNX2_BAM_NXTPG_CTL, val);
+
+       bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_CL73_USERB0);
+
+       val = MII_BNX2_CL73_BAM_EN | MII_BNX2_CL73_BAM_STA_MGR_EN |
+             MII_BNX2_CL73_BAM_NP_AFT_BP_EN;
+       bnx2_write_phy(bp, MII_BNX2_CL73_BAM_CTL1, val);
+
+       bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
+
+       return 0;
+}
+
+static int
 bnx2_init_5708s_phy(struct bnx2 *bp)
 {
        u32 val;
 
+       bnx2_reset_phy(bp);
+
+       bp->mii_up1 = BCM5708S_UP1;
+
        bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG3);
        bnx2_write_phy(bp, BCM5708S_DIG_3_0, BCM5708S_DIG_3_0_USE_IEEE);
        bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG);
@@ -1305,6 +1556,8 @@ bnx2_init_5708s_phy(struct bnx2 *bp)
 static int
 bnx2_init_5706s_phy(struct bnx2 *bp)
 {
+       bnx2_reset_phy(bp);
+
        bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG;
 
        if (CHIP_NUM(bp) == CHIP_NUM_5706)
@@ -1342,6 +1595,8 @@ bnx2_init_copper_phy(struct bnx2 *bp)
 {
        u32 val;
 
+       bnx2_reset_phy(bp);
+
        if (bp->phy_flags & PHY_CRC_FIX_FLAG) {
                bnx2_write_phy(bp, 0x18, 0x0c00);
                bnx2_write_phy(bp, 0x17, 0x000a);
@@ -1396,9 +1651,13 @@ bnx2_init_phy(struct bnx2 *bp)
        bp->phy_flags &= ~PHY_INT_MODE_MASK_FLAG;
        bp->phy_flags |= PHY_INT_MODE_LINK_READY_FLAG;
 
-        REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
+       bp->mii_bmcr = MII_BMCR;
+       bp->mii_bmsr = MII_BMSR;
+       bp->mii_bmsr1 = MII_BMSR;
+       bp->mii_adv = MII_ADVERTISE;
+       bp->mii_lpa = MII_LPA;
 
-       bnx2_reset_phy(bp);
+        REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
 
        bnx2_read_phy(bp, MII_PHYSID1, &val);
        bp->phy_id = val << 16;
@@ -1410,6 +1669,8 @@ bnx2_init_phy(struct bnx2 *bp)
                        rc = bnx2_init_5706s_phy(bp);
                else if (CHIP_NUM(bp) == CHIP_NUM_5708)
                        rc = bnx2_init_5708s_phy(bp);
+               else if (CHIP_NUM(bp) == CHIP_NUM_5709)
+                       rc = bnx2_init_5709s_phy(bp);
        }
        else {
                rc = bnx2_init_copper_phy(bp);
@@ -1442,7 +1703,7 @@ bnx2_set_phy_loopback(struct bnx2 *bp)
        int rc, i;
 
        spin_lock_bh(&bp->phy_lock);
-       rc = bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX |
+       rc = bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK | BMCR_FULLDPLX |
                            BMCR_SPEED1000);
        spin_unlock_bh(&bp->phy_lock);
        if (rc)
@@ -1681,25 +1942,33 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index)
        return 0;
 }
 
-static void
-bnx2_phy_int(struct bnx2 *bp)
+static int
+bnx2_phy_event_is_set(struct bnx2 *bp, u32 event)
 {
+       struct status_block *sblk = bp->status_blk;
        u32 new_link_state, old_link_state;
+       int is_set = 1;
 
-       new_link_state = bp->status_blk->status_attn_bits &
-               STATUS_ATTN_BITS_LINK_STATE;
-       old_link_state = bp->status_blk->status_attn_bits_ack &
-               STATUS_ATTN_BITS_LINK_STATE;
+       new_link_state = sblk->status_attn_bits & event;
+       old_link_state = sblk->status_attn_bits_ack & event;
        if (new_link_state != old_link_state) {
-               if (new_link_state) {
-                       REG_WR(bp, BNX2_PCICFG_STATUS_BIT_SET_CMD,
-                               STATUS_ATTN_BITS_LINK_STATE);
-               }
-               else {
-                       REG_WR(bp, BNX2_PCICFG_STATUS_BIT_CLEAR_CMD,
-                               STATUS_ATTN_BITS_LINK_STATE);
-               }
+               if (new_link_state)
+                       REG_WR(bp, BNX2_PCICFG_STATUS_BIT_SET_CMD, event);
+               else
+                       REG_WR(bp, BNX2_PCICFG_STATUS_BIT_CLEAR_CMD, event);
+       } else
+               is_set = 0;
+
+       return is_set;
+}
+
+static void
+bnx2_phy_int(struct bnx2 *bp)
+{
+       if (bnx2_phy_event_is_set(bp, STATUS_ATTN_BITS_LINK_STATE)) {
+               spin_lock(&bp->phy_lock);
                bnx2_set_link(bp);
+               spin_unlock(&bp->phy_lock);
        }
 }
 
@@ -1993,6 +2262,23 @@ bnx2_msi(int irq, void *dev_instance)
 }
 
 static irqreturn_t
+bnx2_msi_1shot(int irq, void *dev_instance)
+{
+       struct net_device *dev = dev_instance;
+       struct bnx2 *bp = netdev_priv(dev);
+
+       prefetch(bp->status_blk);
+
+       /* Return here if interrupt is disabled. */
+       if (unlikely(atomic_read(&bp->intr_sem) != 0))
+               return IRQ_HANDLED;
+
+       netif_rx_schedule(dev);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t
 bnx2_interrupt(int irq, void *dev_instance)
 {
        struct net_device *dev = dev_instance;
@@ -2022,6 +2308,8 @@ bnx2_interrupt(int irq, void *dev_instance)
        return IRQ_HANDLED;
 }
 
+#define STATUS_ATTN_EVENTS     STATUS_ATTN_BITS_LINK_STATE
+
 static inline int
 bnx2_has_work(struct bnx2 *bp)
 {
@@ -2031,8 +2319,8 @@ bnx2_has_work(struct bnx2 *bp)
            (sblk->status_tx_quick_consumer_index0 != bp->hw_tx_cons))
                return 1;
 
-       if ((sblk->status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) !=
-           (sblk->status_attn_bits_ack & STATUS_ATTN_BITS_LINK_STATE))
+       if ((sblk->status_attn_bits & STATUS_ATTN_EVENTS) !=
+           (sblk->status_attn_bits_ack & STATUS_ATTN_EVENTS))
                return 1;
 
        return 0;
@@ -2042,15 +2330,14 @@ static int
 bnx2_poll(struct net_device *dev, int *budget)
 {
        struct bnx2 *bp = netdev_priv(dev);
+       struct status_block *sblk = bp->status_blk;
+       u32 status_attn_bits = sblk->status_attn_bits;
+       u32 status_attn_bits_ack = sblk->status_attn_bits_ack;
 
-       if ((bp->status_blk->status_attn_bits &
-               STATUS_ATTN_BITS_LINK_STATE) !=
-               (bp->status_blk->status_attn_bits_ack &
-               STATUS_ATTN_BITS_LINK_STATE)) {
+       if ((status_attn_bits & STATUS_ATTN_EVENTS) !=
+           (status_attn_bits_ack & STATUS_ATTN_EVENTS)) {
 
-               spin_lock(&bp->phy_lock);
                bnx2_phy_int(bp);
-               spin_unlock(&bp->phy_lock);
 
                /* This is needed to take care of transient status
                 * during link changes.
@@ -3489,17 +3776,21 @@ bnx2_init_chip(struct bnx2 *bp)
        REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8);  /* 3ms */
 
        if (CHIP_ID(bp) == CHIP_ID_5706_A1)
-               REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_COLLECT_STATS);
+               val = BNX2_HC_CONFIG_COLLECT_STATS;
        else {
-               REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_RX_TMR_MODE |
-                      BNX2_HC_CONFIG_TX_TMR_MODE |
-                      BNX2_HC_CONFIG_COLLECT_STATS);
+               val = BNX2_HC_CONFIG_RX_TMR_MODE | BNX2_HC_CONFIG_TX_TMR_MODE |
+                     BNX2_HC_CONFIG_COLLECT_STATS;
        }
 
+       if (bp->flags & ONE_SHOT_MSI_FLAG)
+               val |= BNX2_HC_CONFIG_ONE_SHOT;
+
+       REG_WR(bp, BNX2_HC_CONFIG, val);
+
        /* Clear internal stats counters. */
        REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW);
 
-       REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_BITS_LINK_STATE);
+       REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_EVENTS);
 
        if (REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_FEATURE) &
            BNX2_PORT_FEATURE_ASF_ENABLED)
@@ -3763,10 +4054,11 @@ static int
 bnx2_test_registers(struct bnx2 *bp)
 {
        int ret;
-       int i;
+       int i, is_5709;
        static const struct {
                u16   offset;
                u16   flags;
+#define BNX2_FL_NOT_5709       1
                u32   rw_mask;
                u32   ro_mask;
        } reg_tbl[] = {
@@ -3774,26 +4066,26 @@ bnx2_test_registers(struct bnx2 *bp)
                { 0x0090, 0, 0xffffffff, 0x00000000 },
                { 0x0094, 0, 0x00000000, 0x00000000 },
 
-               { 0x0404, 0, 0x00003f00, 0x00000000 },
-               { 0x0418, 0, 0x00000000, 0xffffffff },
-               { 0x041c, 0, 0x00000000, 0xffffffff },
-               { 0x0420, 0, 0x00000000, 0x80ffffff },
-               { 0x0424, 0, 0x00000000, 0x00000000 },
-               { 0x0428, 0, 0x00000000, 0x00000001 },
-               { 0x0450, 0, 0x00000000, 0x0000ffff },
-               { 0x0454, 0, 0x00000000, 0xffffffff },
-               { 0x0458, 0, 0x00000000, 0xffffffff },
-
-               { 0x0808, 0, 0x00000000, 0xffffffff },
-               { 0x0854, 0, 0x00000000, 0xffffffff },
-               { 0x0868, 0, 0x00000000, 0x77777777 },
-               { 0x086c, 0, 0x00000000, 0x77777777 },
-               { 0x0870, 0, 0x00000000, 0x77777777 },
-               { 0x0874, 0, 0x00000000, 0x77777777 },
-
-               { 0x0c00, 0, 0x00000000, 0x00000001 },
-               { 0x0c04, 0, 0x00000000, 0x03ff0001 },
-               { 0x0c08, 0, 0x0f0ff073, 0x00000000 },
+               { 0x0404, BNX2_FL_NOT_5709, 0x00003f00, 0x00000000 },
+               { 0x0418, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
+               { 0x041c, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
+               { 0x0420, BNX2_FL_NOT_5709, 0x00000000, 0x80ffffff },
+               { 0x0424, BNX2_FL_NOT_5709, 0x00000000, 0x00000000 },
+               { 0x0428, BNX2_FL_NOT_5709, 0x00000000, 0x00000001 },
+               { 0x0450, BNX2_FL_NOT_5709, 0x00000000, 0x0000ffff },
+               { 0x0454, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
+               { 0x0458, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
+
+               { 0x0808, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
+               { 0x0854, BNX2_FL_NOT_5709, 0x00000000, 0xffffffff },
+               { 0x0868, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 },
+               { 0x086c, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 },
+               { 0x0870, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 },
+               { 0x0874, BNX2_FL_NOT_5709, 0x00000000, 0x77777777 },
+
+               { 0x0c00, BNX2_FL_NOT_5709, 0x00000000, 0x00000001 },
+               { 0x0c04, BNX2_FL_NOT_5709, 0x00000000, 0x03ff0001 },
+               { 0x0c08, BNX2_FL_NOT_5709,  0x0f0ff073, 0x00000000 },
 
                { 0x1000, 0, 0x00000000, 0x00000001 },
                { 0x1004, 0, 0x00000000, 0x000f0001 },
@@ -3840,7 +4132,6 @@ bnx2_test_registers(struct bnx2 *bp)
 
                { 0x5004, 0, 0x00000000, 0x0000007f },
                { 0x5008, 0, 0x0f0007ff, 0x00000000 },
-               { 0x500c, 0, 0xf800f800, 0x07ff07ff },
 
                { 0x5c00, 0, 0x00000000, 0x00000001 },
                { 0x5c04, 0, 0x00000000, 0x0003000f },
@@ -3880,8 +4171,16 @@ bnx2_test_registers(struct bnx2 *bp)
        };
 
        ret = 0;
+       is_5709 = 0;
+       if (CHIP_NUM(bp) == CHIP_NUM_5709)
+               is_5709 = 1;
+
        for (i = 0; reg_tbl[i].offset != 0xffff; i++) {
                u32 offset, rw_mask, ro_mask, save_val, val;
+               u16 flags = reg_tbl[i].flags;
+
+               if (is_5709 && (flags & BNX2_FL_NOT_5709))
+                       continue;
 
                offset = (u32) reg_tbl[i].offset;
                rw_mask = reg_tbl[i].rw_mask;
@@ -3950,10 +4249,10 @@ bnx2_test_memory(struct bnx2 *bp)
 {
        int ret = 0;
        int i;
-       static const struct {
+       static struct mem_entry {
                u32   offset;
                u32   len;
-       } mem_tbl[] = {
+       } mem_tbl_5706[] = {
                { 0x60000,  0x4000 },
                { 0xa0000,  0x3000 },
                { 0xe0000,  0x4000 },
@@ -3961,7 +4260,21 @@ bnx2_test_memory(struct bnx2 *bp)
                { 0x1a0000, 0x4000 },
                { 0x160000, 0x4000 },
                { 0xffffffff, 0    },
+       },
+       mem_tbl_5709[] = {
+               { 0x60000,  0x4000 },
+               { 0xa0000,  0x3000 },
+               { 0xe0000,  0x4000 },
+               { 0x120000, 0x4000 },
+               { 0x1a0000, 0x4000 },
+               { 0xffffffff, 0    },
        };
+       struct mem_entry *mem_tbl;
+
+       if (CHIP_NUM(bp) == CHIP_NUM_5709)
+               mem_tbl = mem_tbl_5709;
+       else
+               mem_tbl = mem_tbl_5706;
 
        for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) {
                if ((ret = bnx2_do_mem_test(bp, mem_tbl[i].offset,
@@ -4163,8 +4476,10 @@ bnx2_test_link(struct bnx2 *bp)
        u32 bmsr;
 
        spin_lock_bh(&bp->phy_lock);
-       bnx2_read_phy(bp, MII_BMSR, &bmsr);
-       bnx2_read_phy(bp, MII_BMSR, &bmsr);
+       bnx2_enable_bmsr1(bp);
+       bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr);
+       bnx2_read_phy(bp, bp->mii_bmsr1, &bmsr);
+       bnx2_disable_bmsr1(bp);
        spin_unlock_bh(&bp->phy_lock);
 
        if (bmsr & BMSR_LSTATUS) {
@@ -4214,7 +4529,7 @@ bnx2_5706_serdes_timer(struct bnx2 *bp)
 
                bp->current_interval = bp->timer_interval;
 
-               bnx2_read_phy(bp, MII_BMCR, &bmcr);
+               bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
 
                if (bmcr & BMCR_ANENABLE) {
                        u32 phy1, phy2;
@@ -4232,7 +4547,7 @@ bnx2_5706_serdes_timer(struct bnx2 *bp)
 
                                bmcr &= ~BMCR_ANENABLE;
                                bmcr |= BMCR_SPEED1000 | BMCR_FULLDPLX;
-                               bnx2_write_phy(bp, MII_BMCR, bmcr);
+                               bnx2_write_phy(bp, bp->mii_bmcr, bmcr);
                                bp->phy_flags |= PHY_PARALLEL_DETECT_FLAG;
                        }
                }
@@ -4246,9 +4561,9 @@ bnx2_5706_serdes_timer(struct bnx2 *bp)
                if (phy2 & 0x20) {
                        u32 bmcr;
 
-                       bnx2_read_phy(bp, MII_BMCR, &bmcr);
+                       bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
                        bmcr |= BMCR_ANENABLE;
-                       bnx2_write_phy(bp, MII_BMCR, bmcr);
+                       bnx2_write_phy(bp, bp->mii_bmcr, bmcr);
 
                        bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG;
                }
@@ -4272,17 +4587,12 @@ bnx2_5708_serdes_timer(struct bnx2 *bp)
        else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) {
                u32 bmcr;
 
-               bnx2_read_phy(bp, MII_BMCR, &bmcr);
-
+               bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
                if (bmcr & BMCR_ANENABLE) {
-                       bmcr &= ~BMCR_ANENABLE;
-                       bmcr |= BMCR_FULLDPLX | BCM5708S_BMCR_FORCE_2500;
-                       bnx2_write_phy(bp, MII_BMCR, bmcr);
+                       bnx2_enable_forced_2g5(bp);
                        bp->current_interval = SERDES_FORCED_TIMEOUT;
                } else {
-                       bmcr &= ~(BMCR_FULLDPLX | BCM5708S_BMCR_FORCE_2500);
-                       bmcr |= BMCR_ANENABLE;
-                       bnx2_write_phy(bp, MII_BMCR, bmcr);
+                       bnx2_disable_forced_2g5(bp);
                        bp->serdes_an_pending = 2;
                        bp->current_interval = bp->timer_interval;
                }
@@ -4313,7 +4623,7 @@ bnx2_timer(unsigned long data)
        if (bp->phy_flags & PHY_SERDES_FLAG) {
                if (CHIP_NUM(bp) == CHIP_NUM_5706)
                        bnx2_5706_serdes_timer(bp);
-               else if (CHIP_NUM(bp) == CHIP_NUM_5708)
+               else
                        bnx2_5708_serdes_timer(bp);
        }
 
@@ -4321,6 +4631,38 @@ bnx2_restart_timer:
        mod_timer(&bp->timer, jiffies + bp->current_interval);
 }
 
+static int
+bnx2_request_irq(struct bnx2 *bp)
+{
+       struct net_device *dev = bp->dev;
+       int rc = 0;
+
+       if (bp->flags & USING_MSI_FLAG) {
+               irq_handler_t   fn = bnx2_msi;
+
+               if (bp->flags & ONE_SHOT_MSI_FLAG)
+                       fn = bnx2_msi_1shot;
+
+               rc = request_irq(bp->pdev->irq, fn, 0, dev->name, dev);
+       } else
+               rc = request_irq(bp->pdev->irq, bnx2_interrupt,
+                                IRQF_SHARED, dev->name, dev);
+       return rc;
+}
+
+static void
+bnx2_free_irq(struct bnx2 *bp)
+{
+       struct net_device *dev = bp->dev;
+
+       if (bp->flags & USING_MSI_FLAG) {
+               free_irq(bp->pdev->irq, dev);
+               pci_disable_msi(bp->pdev);
+               bp->flags &= ~(USING_MSI_FLAG | ONE_SHOT_MSI_FLAG);
+       } else
+               free_irq(bp->pdev->irq, dev);
+}
+
 /* Called with rtnl_lock */
 static int
 bnx2_open(struct net_device *dev)
@@ -4328,6 +4670,8 @@ bnx2_open(struct net_device *dev)
        struct bnx2 *bp = netdev_priv(dev);
        int rc;
 
+       netif_carrier_off(dev);
+
        bnx2_set_power_state(bp, PCI_D0);
        bnx2_disable_int(bp);
 
@@ -4335,24 +4679,15 @@ bnx2_open(struct net_device *dev)
        if (rc)
                return rc;
 
-       if ((CHIP_ID(bp) != CHIP_ID_5706_A0) &&
-               (CHIP_ID(bp) != CHIP_ID_5706_A1) &&
-               !disable_msi) {
-
+       if ((bp->flags & MSI_CAP_FLAG) && !disable_msi) {
                if (pci_enable_msi(bp->pdev) == 0) {
                        bp->flags |= USING_MSI_FLAG;
-                       rc = request_irq(bp->pdev->irq, bnx2_msi, 0, dev->name,
-                                       dev);
-               }
-               else {
-                       rc = request_irq(bp->pdev->irq, bnx2_interrupt,
-                                       IRQF_SHARED, dev->name, dev);
+                       if (CHIP_NUM(bp) == CHIP_NUM_5709)
+                               bp->flags |= ONE_SHOT_MSI_FLAG;
                }
        }
-       else {
-               rc = request_irq(bp->pdev->irq, bnx2_interrupt, IRQF_SHARED,
-                               dev->name, dev);
-       }
+       rc = bnx2_request_irq(bp);
+
        if (rc) {
                bnx2_free_mem(bp);
                return rc;
@@ -4361,11 +4696,7 @@ bnx2_open(struct net_device *dev)
        rc = bnx2_init_nic(bp);
 
        if (rc) {
-               free_irq(bp->pdev->irq, dev);
-               if (bp->flags & USING_MSI_FLAG) {
-                       pci_disable_msi(bp->pdev);
-                       bp->flags &= ~USING_MSI_FLAG;
-               }
+               bnx2_free_irq(bp);
                bnx2_free_skbs(bp);
                bnx2_free_mem(bp);
                return rc;
@@ -4389,16 +4720,13 @@ bnx2_open(struct net_device *dev)
                               bp->dev->name);
 
                        bnx2_disable_int(bp);
-                       free_irq(bp->pdev->irq, dev);
-                       pci_disable_msi(bp->pdev);
-                       bp->flags &= ~USING_MSI_FLAG;
+                       bnx2_free_irq(bp);
 
                        rc = bnx2_init_nic(bp);
 
-                       if (!rc) {
-                               rc = request_irq(bp->pdev->irq, bnx2_interrupt,
-                                       IRQF_SHARED, dev->name, dev);
-                       }
+                       if (!rc)
+                               rc = bnx2_request_irq(bp);
+
                        if (rc) {
                                bnx2_free_skbs(bp);
                                bnx2_free_mem(bp);
@@ -4508,40 +4836,53 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
                vlan_tag_flags |=
                        (TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16));
        }
-       if ((mss = skb_shinfo(skb)->gso_size) &&
-               (skb->len > (bp->dev->mtu + ETH_HLEN))) {
+       if ((mss = skb_shinfo(skb)->gso_size)) {
                u32 tcp_opt_len, ip_tcp_len;
                struct iphdr *iph;
 
-               if (skb_header_cloned(skb) &&
-                   pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
-                       dev_kfree_skb(skb);
-                       return NETDEV_TX_OK;
-               }
-
                vlan_tag_flags |= TX_BD_FLAGS_SW_LSO;
 
-               tcp_opt_len = 0;
-               if (tcp_hdr(skb)->doff > 5)
-                       tcp_opt_len = tcp_optlen(skb);
+               tcp_opt_len = tcp_optlen(skb);
+
+               if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) {
+                       u32 tcp_off = skb_transport_offset(skb) -
+                                     sizeof(struct ipv6hdr) - ETH_HLEN;
 
-               ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
+                       vlan_tag_flags |= ((tcp_opt_len >> 2) << 8) |
+                                         TX_BD_FLAGS_SW_FLAGS;
+                       if (likely(tcp_off == 0))
+                               vlan_tag_flags &= ~TX_BD_FLAGS_TCP6_OFF0_MSK;
+                       else {
+                               tcp_off >>= 3;
+                               vlan_tag_flags |= ((tcp_off & 0x3) <<
+                                                  TX_BD_FLAGS_TCP6_OFF0_SHL) |
+                                                 ((tcp_off & 0x10) <<
+                                                  TX_BD_FLAGS_TCP6_OFF4_SHL);
+                               mss |= (tcp_off & 0xc) << TX_BD_TCP6_OFF2_SHL;
+                       }
+               } else {
+                       if (skb_header_cloned(skb) &&
+                           pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
+                               dev_kfree_skb(skb);
+                               return NETDEV_TX_OK;
+                       }
 
-               iph = ip_hdr(skb);
-               iph->check = 0;
-               iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
-               tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
-                                                        iph->daddr, 0,
-                                                        IPPROTO_TCP, 0);
-               if (tcp_opt_len || (iph->ihl > 5)) {
-                       vlan_tag_flags |= ((iph->ihl - 5) +
-                                          (tcp_opt_len >> 2)) << 8;
+                       ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
+
+                       iph = ip_hdr(skb);
+                       iph->check = 0;
+                       iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
+                       tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
+                                                                iph->daddr, 0,
+                                                                IPPROTO_TCP,
+                                                                0);
+                       if (tcp_opt_len || (iph->ihl > 5)) {
+                               vlan_tag_flags |= ((iph->ihl - 5) +
+                                                  (tcp_opt_len >> 2)) << 8;
+                       }
                }
-       }
-       else
-       {
+       } else
                mss = 0;
-       }
 
        mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
 
@@ -4622,11 +4963,7 @@ bnx2_close(struct net_device *dev)
        else
                reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
        bnx2_reset_chip(bp, reset_code);
-       free_irq(bp->pdev->irq, dev);
-       if (bp->flags & USING_MSI_FLAG) {
-               pci_disable_msi(bp->pdev);
-               bp->flags &= ~USING_MSI_FLAG;
-       }
+       bnx2_free_irq(bp);
        bnx2_free_skbs(bp);
        bnx2_free_mem(bp);
        bp->link_up = 0;
@@ -4735,6 +5072,8 @@ bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        if (bp->phy_flags & PHY_SERDES_FLAG) {
                cmd->supported |= SUPPORTED_1000baseT_Full |
                        SUPPORTED_FIBRE;
+               if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)
+                       cmd->supported |= SUPPORTED_2500baseX_Full;
 
                cmd->port = PORT_FIBRE;
        }
@@ -4798,8 +5137,10 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 
                        advertising = cmd->advertising;
 
-               }
-               else if (cmd->advertising == ADVERTISED_1000baseT_Full) {
+               } else if (cmd->advertising == ADVERTISED_2500baseX_Full) {
+                       if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG))
+                               return -EINVAL;
+               } else if (cmd->advertising == ADVERTISED_1000baseT_Full) {
                        advertising = cmd->advertising;
                }
                else if (cmd->advertising == ADVERTISED_1000baseT_Half) {
@@ -4975,7 +5316,7 @@ bnx2_nway_reset(struct net_device *dev)
 
        /* Force a link down visible on the other side */
        if (bp->phy_flags & PHY_SERDES_FLAG) {
-               bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
+               bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK);
                spin_unlock_bh(&bp->phy_lock);
 
                msleep(20);
@@ -4987,9 +5328,9 @@ bnx2_nway_reset(struct net_device *dev)
                mod_timer(&bp->timer, jiffies + bp->current_interval);
        }
 
-       bnx2_read_phy(bp, MII_BMCR, &bmcr);
+       bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
        bmcr &= ~BMCR_LOOPBACK;
-       bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART | BMCR_ANENABLE);
+       bnx2_write_phy(bp, bp->mii_bmcr, bmcr | BMCR_ANRESTART | BMCR_ANENABLE);
 
        spin_unlock_bh(&bp->phy_lock);
 
@@ -5209,10 +5550,15 @@ bnx2_set_rx_csum(struct net_device *dev, u32 data)
 static int
 bnx2_set_tso(struct net_device *dev, u32 data)
 {
-       if (data)
+       struct bnx2 *bp = netdev_priv(dev);
+
+       if (data) {
                dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
-       else
-               dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO_ECN);
+               if (CHIP_NUM(bp) == CHIP_NUM_5709)
+                       dev->features |= NETIF_F_TSO6;
+       } else
+               dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6 |
+                                  NETIF_F_TSO_ECN);
        return 0;
 }
 
@@ -5510,6 +5856,17 @@ bnx2_phys_id(struct net_device *dev, u32 data)
        return 0;
 }
 
+static int
+bnx2_set_tx_csum(struct net_device *dev, u32 data)
+{
+       struct bnx2 *bp = netdev_priv(dev);
+
+       if (CHIP_NUM(bp) == CHIP_NUM_5709)
+               return (ethtool_op_set_tx_hw_csum(dev, data));
+       else
+               return (ethtool_op_set_tx_csum(dev, data));
+}
+
 static const struct ethtool_ops bnx2_ethtool_ops = {
        .get_settings           = bnx2_get_settings,
        .set_settings           = bnx2_set_settings,
@@ -5532,7 +5889,7 @@ static const struct ethtool_ops bnx2_ethtool_ops = {
        .get_rx_csum            = bnx2_get_rx_csum,
        .set_rx_csum            = bnx2_set_rx_csum,
        .get_tx_csum            = ethtool_op_get_tx_csum,
-       .set_tx_csum            = ethtool_op_set_tx_csum,
+       .set_tx_csum            = bnx2_set_tx_csum,
        .get_sg                 = ethtool_op_get_sg,
        .set_sg                 = ethtool_op_set_sg,
        .get_tso                = ethtool_op_get_tso,
@@ -5562,6 +5919,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        case SIOCGMIIREG: {
                u32 mii_regval;
 
+               if (!netif_running(dev))
+                       return -EAGAIN;
+
                spin_lock_bh(&bp->phy_lock);
                err = bnx2_read_phy(bp, data->reg_num & 0x1f, &mii_regval);
                spin_unlock_bh(&bp->phy_lock);
@@ -5575,6 +5935,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
 
+               if (!netif_running(dev))
+                       return -EAGAIN;
+
                spin_lock_bh(&bp->phy_lock);
                err = bnx2_write_phy(bp, data->reg_num & 0x1f, data->val_in);
                spin_unlock_bh(&bp->phy_lock);
@@ -5676,6 +6039,58 @@ bnx2_get_5709_media(struct bnx2 *bp)
        }
 }
 
+static void __devinit
+bnx2_get_pci_speed(struct bnx2 *bp)
+{
+       u32 reg;
+
+       reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS);
+       if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) {
+               u32 clkreg;
+
+               bp->flags |= PCIX_FLAG;
+
+               clkreg = REG_RD(bp, BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS);
+
+               clkreg &= BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET;
+               switch (clkreg) {
+               case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ:
+                       bp->bus_speed_mhz = 133;
+                       break;
+
+               case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ:
+                       bp->bus_speed_mhz = 100;
+                       break;
+
+               case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ:
+               case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ:
+                       bp->bus_speed_mhz = 66;
+                       break;
+
+               case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ:
+               case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ:
+                       bp->bus_speed_mhz = 50;
+                       break;
+
+               case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW:
+               case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ:
+               case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ:
+                       bp->bus_speed_mhz = 33;
+                       break;
+               }
+       }
+       else {
+               if (reg & BNX2_PCICFG_MISC_STATUS_M66EN)
+                       bp->bus_speed_mhz = 66;
+               else
+                       bp->bus_speed_mhz = 33;
+       }
+
+       if (reg & BNX2_PCICFG_MISC_STATUS_32BIT_DET)
+               bp->flags |= PCI_32BIT_FLAG;
+
+}
+
 static int __devinit
 bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
 {
@@ -5683,6 +6098,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
        unsigned long mem_len;
        int rc;
        u32 reg;
+       u64 dma_mask, persist_dma_mask;
 
        SET_MODULE_OWNER(dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
@@ -5721,25 +6137,11 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
                goto err_out_release;
        }
 
-       if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) {
-               bp->flags |= USING_DAC_FLAG;
-               if (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) != 0) {
-                       dev_err(&pdev->dev,
-                               "pci_set_consistent_dma_mask failed, aborting.\n");
-                       rc = -EIO;
-                       goto err_out_release;
-               }
-       }
-       else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) {
-               dev_err(&pdev->dev, "System does not support DMA, aborting.\n");
-               rc = -EIO;
-               goto err_out_release;
-       }
-
        bp->dev = dev;
        bp->pdev = pdev;
 
        spin_lock_init(&bp->phy_lock);
+       spin_lock_init(&bp->indirect_lock);
        INIT_WORK(&bp->reset_task, bnx2_reset_task);
 
        dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0);
@@ -5767,7 +6169,15 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
 
        bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
 
-       if (CHIP_NUM(bp) != CHIP_NUM_5709) {
+       if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+               if (pci_find_capability(pdev, PCI_CAP_ID_EXP) == 0) {
+                       dev_err(&pdev->dev,
+                               "Cannot find PCIE capability, aborting.\n");
+                       rc = -EIO;
+                       goto err_out_unmap;
+               }
+               bp->flags |= PCIE_FLAG;
+       } else {
                bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
                if (bp->pcix_cap == 0) {
                        dev_err(&pdev->dev,
@@ -5777,51 +6187,33 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
                }
        }
 
-       /* Get bus information. */
-       reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS);
-       if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) {
-               u32 clkreg;
-
-               bp->flags |= PCIX_FLAG;
-
-               clkreg = REG_RD(bp, BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS);
-
-               clkreg &= BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET;
-               switch (clkreg) {
-               case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ:
-                       bp->bus_speed_mhz = 133;
-                       break;
-
-               case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ:
-                       bp->bus_speed_mhz = 100;
-                       break;
-
-               case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ:
-               case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ:
-                       bp->bus_speed_mhz = 66;
-                       break;
+       if (CHIP_ID(bp) != CHIP_ID_5706_A0 && CHIP_ID(bp) != CHIP_ID_5706_A1) {
+               if (pci_find_capability(pdev, PCI_CAP_ID_MSI))
+                       bp->flags |= MSI_CAP_FLAG;
+       }
 
-               case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ:
-               case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ:
-                       bp->bus_speed_mhz = 50;
-                       break;
+       /* 5708 cannot support DMA addresses > 40-bit.  */
+       if (CHIP_NUM(bp) == CHIP_NUM_5708)
+               persist_dma_mask = dma_mask = DMA_40BIT_MASK;
+       else
+               persist_dma_mask = dma_mask = DMA_64BIT_MASK;
 
-               case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW:
-               case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ:
-               case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ:
-                       bp->bus_speed_mhz = 33;
-                       break;
+       /* Configure DMA attributes. */
+       if (pci_set_dma_mask(pdev, dma_mask) == 0) {
+               dev->features |= NETIF_F_HIGHDMA;
+               rc = pci_set_consistent_dma_mask(pdev, persist_dma_mask);
+               if (rc) {
+                       dev_err(&pdev->dev,
+                               "pci_set_consistent_dma_mask failed, aborting.\n");
+                       goto err_out_unmap;
                }
-       }
-       else {
-               if (reg & BNX2_PCICFG_MISC_STATUS_M66EN)
-                       bp->bus_speed_mhz = 66;
-               else
-                       bp->bus_speed_mhz = 33;
+       } else if ((rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) != 0) {
+               dev_err(&pdev->dev, "System does not support DMA, aborting.\n");
+               goto err_out_unmap;
        }
 
-       if (reg & BNX2_PCICFG_MISC_STATUS_32BIT_DET)
-               bp->flags |= PCI_32BIT_FLAG;
+       if (!(bp->flags & PCIE_FLAG))
+               bnx2_get_pci_speed(bp);
 
        /* 5706A0 may falsely detect SERR and PERR. */
        if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
@@ -6005,6 +6397,26 @@ err_out:
        return rc;
 }
 
+static char * __devinit
+bnx2_bus_string(struct bnx2 *bp, char *str)
+{
+       char *s = str;
+
+       if (bp->flags & PCIE_FLAG) {
+               s += sprintf(s, "PCI Express");
+       } else {
+               s += sprintf(s, "PCI");
+               if (bp->flags & PCIX_FLAG)
+                       s += sprintf(s, "-X");
+               if (bp->flags & PCI_32BIT_FLAG)
+                       s += sprintf(s, " 32-bit");
+               else
+                       s += sprintf(s, " 64-bit");
+               s += sprintf(s, " %dMHz", bp->bus_speed_mhz);
+       }
+       return str;
+}
+
 static int __devinit
 bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -6012,6 +6424,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct net_device *dev = NULL;
        struct bnx2 *bp;
        int rc, i;
+       char str[40];
 
        if (version_printed++ == 0)
                printk(KERN_INFO "%s", version);
@@ -6052,6 +6465,23 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        dev->poll_controller = poll_bnx2;
 #endif
 
+       pci_set_drvdata(pdev, dev);
+
+       memcpy(dev->dev_addr, bp->mac_addr, 6);
+       memcpy(dev->perm_addr, bp->mac_addr, 6);
+       bp->name = board_info[ent->driver_data].name;
+
+       if (CHIP_NUM(bp) == CHIP_NUM_5709)
+               dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
+       else
+               dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+#ifdef BCM_VLAN
+       dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+#endif
+       dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
+       if (CHIP_NUM(bp) == CHIP_NUM_5709)
+               dev->features |= NETIF_F_TSO6;
+
        if ((rc = register_netdev(dev))) {
                dev_err(&pdev->dev, "Cannot register net device\n");
                if (bp->regview)
@@ -6063,20 +6493,13 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                return rc;
        }
 
-       pci_set_drvdata(pdev, dev);
-
-       memcpy(dev->dev_addr, bp->mac_addr, 6);
-       memcpy(dev->perm_addr, bp->mac_addr, 6);
-       bp->name = board_info[ent->driver_data].name,
-       printk(KERN_INFO "%s: %s (%c%d) PCI%s %s %dMHz found at mem %lx, "
+       printk(KERN_INFO "%s: %s (%c%d) %s found at mem %lx, "
                "IRQ %d, ",
                dev->name,
                bp->name,
                ((CHIP_ID(bp) & 0xf000) >> 12) + 'A',
                ((CHIP_ID(bp) & 0x0ff0) >> 4),
-               ((bp->flags & PCIX_FLAG) ? "-X" : ""),
-               ((bp->flags & PCI_32BIT_FLAG) ? "32-bit" : "64-bit"),
-               bp->bus_speed_mhz,
+               bnx2_bus_string(bp, str),
                dev->base_addr,
                bp->pdev->irq);
 
@@ -6085,17 +6508,6 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                printk("%2.2x", dev->dev_addr[i]);
        printk("\n");
 
-       dev->features |= NETIF_F_SG;
-       if (bp->flags & USING_DAC_FLAG)
-               dev->features |= NETIF_F_HIGHDMA;
-       dev->features |= NETIF_F_IP_CSUM;
-#ifdef BCM_VLAN
-       dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-#endif
-       dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
-
-       netif_carrier_off(bp->dev);
-
        return 0;
 }
 
@@ -6140,6 +6552,7 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state)
                reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
        bnx2_reset_chip(bp, reset_code);
        bnx2_free_skbs(bp);
+       pci_save_state(pdev);
        bnx2_set_power_state(bp, pci_choose_state(pdev, state));
        return 0;
 }
@@ -6153,6 +6566,7 @@ bnx2_resume(struct pci_dev *pdev)
        if (!netif_running(dev))
                return 0;
 
+       pci_restore_state(pdev);
        bnx2_set_power_state(bp, PCI_D0);
        netif_device_attach(dev);
        bnx2_init_nic(bp);
index 878eee5..bd6288d 100644 (file)
@@ -1,6 +1,6 @@
 /* bnx2.h: Broadcom NX2 network driver.
  *
- * Copyright (c) 2004, 2005, 2006 Broadcom Corporation
+ * Copyright (c) 2004-2007 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,8 +24,11 @@ struct tx_bd {
        u32 tx_bd_haddr_hi;
        u32 tx_bd_haddr_lo;
        u32 tx_bd_mss_nbytes;
+               #define TX_BD_TCP6_OFF2_SHL             (14)
        u32 tx_bd_vlan_tag_flags;
                #define TX_BD_FLAGS_CONN_FAULT          (1<<0)
+               #define TX_BD_FLAGS_TCP6_OFF0_MSK       (3<<1)
+               #define TX_BD_FLAGS_TCP6_OFF0_SHL       (1)
                #define TX_BD_FLAGS_TCP_UDP_CKSUM       (1<<1)
                #define TX_BD_FLAGS_IP_CKSUM            (1<<2)
                #define TX_BD_FLAGS_VLAN_TAG            (1<<3)
@@ -34,6 +37,7 @@ struct tx_bd {
                #define TX_BD_FLAGS_END                 (1<<6)
                #define TX_BD_FLAGS_START               (1<<7)
                #define TX_BD_FLAGS_SW_OPTION_WORD      (0x1f<<8)
+               #define TX_BD_FLAGS_TCP6_OFF4_SHL       (12)
                #define TX_BD_FLAGS_SW_FLAGS            (1<<13)
                #define TX_BD_FLAGS_SW_SNAP             (1<<14)
                #define TX_BD_FLAGS_SW_LSO              (1<<15)
@@ -6292,6 +6296,41 @@ struct l2_fhdr {
 #define MII_BNX2_DSP_ADDRESS                   0x17
 #define MII_BNX2_DSP_EXPAND_REG                         0x0f00
 
+#define MII_BNX2_BLK_ADDR                      0x1f
+#define MII_BNX2_BLK_ADDR_IEEE0                         0x0000
+#define MII_BNX2_BLK_ADDR_GP_STATUS             0x8120
+#define MII_BNX2_GP_TOP_AN_STATUS1               0x1b
+#define MII_BNX2_GP_TOP_AN_SPEED_MSK              0x3f00
+#define MII_BNX2_GP_TOP_AN_SPEED_10               0x0000
+#define MII_BNX2_GP_TOP_AN_SPEED_100              0x0100
+#define MII_BNX2_GP_TOP_AN_SPEED_1G               0x0200
+#define MII_BNX2_GP_TOP_AN_SPEED_2_5G             0x0300
+#define MII_BNX2_GP_TOP_AN_SPEED_1GKV             0x0d00
+#define MII_BNX2_GP_TOP_AN_FD                     0x8
+#define MII_BNX2_BLK_ADDR_SERDES_DIG            0x8300
+#define MII_BNX2_SERDES_DIG_1000XCTL1            0x10
+#define MII_BNX2_SD_1000XCTL1_FIBER               0x01
+#define MII_BNX2_SD_1000XCTL1_AUTODET             0x10
+#define MII_BNX2_SERDES_DIG_MISC1                0x18
+#define MII_BNX2_SD_MISC1_FORCE_MSK               0xf
+#define MII_BNX2_SD_MISC1_FORCE_2_5G              0x0
+#define MII_BNX2_SD_MISC1_FORCE                           0x10
+#define MII_BNX2_BLK_ADDR_OVER1G                0x8320
+#define MII_BNX2_OVER1G_UP1                      0x19
+#define MII_BNX2_BLK_ADDR_BAM_NXTPG             0x8350
+#define MII_BNX2_BAM_NXTPG_CTL                   0x10
+#define MII_BNX2_NXTPG_CTL_BAM                    0x1
+#define MII_BNX2_NXTPG_CTL_T2                     0x2
+#define MII_BNX2_BLK_ADDR_CL73_USERB0           0x8370
+#define MII_BNX2_CL73_BAM_CTL1                   0x12
+#define MII_BNX2_CL73_BAM_EN                      0x8000
+#define MII_BNX2_CL73_BAM_STA_MGR_EN              0x4000
+#define MII_BNX2_CL73_BAM_NP_AFT_BP_EN            0x2000
+#define MII_BNX2_BLK_ADDR_AER                   0xffd0
+#define MII_BNX2_AER_AER                         0x1e
+#define MII_BNX2_AER_AER_AN_MMD                           0x3800
+#define MII_BNX2_BLK_ADDR_COMBO_IEEEB0          0xffe0
+
 #define MIN_ETHERNET_PACKET_SIZE       60
 #define MAX_ETHERNET_PACKET_SIZE       1514
 #define MAX_ETHERNET_JUMBO_PACKET_SIZE 9014
@@ -6429,13 +6468,15 @@ struct bnx2 {
        u32                     last_status_idx;
 
        u32                     flags;
-#define PCIX_FLAG                      1
-#define PCI_32BIT_FLAG                 2
-#define ONE_TDMA_FLAG                  4       /* no longer used */
-#define NO_WOL_FLAG                    8
-#define USING_DAC_FLAG                 0x10
-#define USING_MSI_FLAG                 0x20
-#define ASF_ENABLE_FLAG                        0x40
+#define PCIX_FLAG                      0x00000001
+#define PCI_32BIT_FLAG                 0x00000002
+#define ONE_TDMA_FLAG                  0x00000004      /* no longer used */
+#define NO_WOL_FLAG                    0x00000008
+#define USING_MSI_FLAG                 0x00000020
+#define ASF_ENABLE_FLAG                        0x00000040
+#define MSI_CAP_FLAG                   0x00000080
+#define ONE_SHOT_MSI_FLAG              0x00000100
+#define PCIE_FLAG                      0x00000200
 
        /* Put tx producer and consumer fields in separate cache lines. */
 
@@ -6484,6 +6525,7 @@ struct bnx2 {
 
        /* Used to synchronize phy accesses. */
        spinlock_t              phy_lock;
+       spinlock_t              indirect_lock;
 
        u32                     phy_flags;
 #define PHY_SERDES_FLAG                        1
@@ -6495,6 +6537,13 @@ struct bnx2 {
 #define PHY_INT_MODE_LINK_READY_FLAG   0x200
 #define PHY_DIS_EARLY_DAC_FLAG         0x400
 
+       u32                     mii_bmcr;
+       u32                     mii_bmsr;
+       u32                     mii_bmsr1;
+       u32                     mii_adv;
+       u32                     mii_lpa;
+       u32                     mii_up1;
+
        u32                     chip_id;
        /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
 #define CHIP_NUM(bp)                   (((bp)->chip_id) & 0xffff0000)
index 21d368f..b49f439 100644 (file)
  */
 
 static u8 bnx2_COM_b06FwText[] = {
-       0x1f, 0x8b, 0x08, 0x08, 0x09, 0x83, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
-       0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xec, 0x5b, 0x7d, 0x6c,
-       0x5b, 0xd7, 0x75, 0x3f, 0xef, 0xf1, 0x51, 0x7a, 0x96, 0x68, 0xf9, 0x99,
-       0x7e, 0x96, 0x59, 0x4f, 0xb1, 0x49, 0xf1, 0xc9, 0xd2, 0x62, 0x2d, 0x63,
-       0x34, 0x35, 0xd1, 0x3a, 0x26, 0x66, 0x48, 0xda, 0x71, 0x36, 0x67, 0xa0,
-       0x1d, 0x05, 0x51, 0x51, 0xaf, 0xd0, 0x48, 0xd9, 0xcd, 0xb2, 0x0c, 0x73,
-       0x96, 0xb4, 0x70, 0xbc, 0xb4, 0xa1, 0x25, 0x79, 0xf5, 0x06, 0x45, 0xcf,
-       0xb3, 0x34, 0x39, 0xc0, 0x82, 0x41, 0x10, 0x9d, 0x3a, 0x7f, 0x30, 0xa5,
-       0xed, 0x7c, 0x19, 0xe8, 0x12, 0x29, 0xb2, 0x93, 0xb5, 0x43, 0xd0, 0xa6,
-       0x68, 0xff, 0xe8, 0x8a, 0x6e, 0x30, 0x52, 0x0c, 0xf3, 0x3a, 0xa0, 0x30,
-       0xfa, 0xc7, 0xe6, 0x2d, 0x1f, 0xdc, 0xef, 0xdc, 0x77, 0x1f, 0xf9, 0x48,
-       0x51, 0x96, 0x1c, 0x34, 0x5d, 0xb7, 0x99, 0x80, 0xf0, 0xde, 0xbd, 0xf7,
-       0xbc, 0x7b, 0xcf, 0x3d, 0xdf, 0xe7, 0xdc, 0xab, 0x5f, 0x53, 0xa9, 0x85,
-       0xe4, 0x6f, 0x2d, 0xfe, 0xc2, 0x7f, 0xf4, 0xc7, 0xb9, 0xdb, 0x3e, 0x7d,
-       0x5b, 0x1f, 0x5e, 0x07, 0x54, 0xdd, 0xaf, 0x72, 0xbf, 0x0f, 0x7f, 0x26,
-       0xfe, 0xfa, 0xe4, 0x7b, 0xa3, 0x9f, 0x81, 0xbf, 0x2b, 0x18, 0x1c, 0xfe,
-       0x09, 0x91, 0xb2, 0x0c, 0x8c, 0xf7, 0x57, 0x2e, 0x5f, 0x7f, 0x9c, 0x17,
-       0x0e, 0xaf, 0x62, 0x9e, 0x9b, 0xbf, 0x9b, 0xbf, 0x9b, 0xbf, 0x9b, 0xbf,
-       0x9b, 0xbf, 0x9b, 0xbf, 0x9b, 0xbf, 0xff, 0x3f, 0x3f, 0x9f, 0x13, 0x72,
-       0x88, 0x98, 0x85, 0xff, 0x48, 0x57, 0xe3, 0x89, 0xa1, 0xa4, 0x45, 0xba,
-       0x2f, 0x7e, 0x65, 0x28, 0x67, 0x11, 0x25, 0x8a, 0xdb, 0xc3, 0x29, 0xfa,
-       0xb0, 0x9c, 0x37, 0x35, 0xe2, 0xfe, 0x5b, 0xe2, 0x1f, 0x3c, 0xfd, 0xfa,
-       0x9d, 0x91, 0xab, 0xb3, 0x3e, 0xd2, 0x8d, 0xf8, 0xcb, 0xba, 0xb1, 0x8d,
-       0xf4, 0x0e, 0x7c, 0xf3, 0x5c, 0xf7, 0x7f, 0xa8, 0xd4, 0xe6, 0xce, 0x75,
-       0xa5, 0xfc, 0x7a, 0x37, 0xe5, 0x37, 0xc7, 0x75, 0x52, 0xe3, 0x5d, 0x3f,
-       0x48, 0xfa, 0x8c, 0x61, 0x5f, 0xdc, 0xa0, 0xf9, 0x12, 0x65, 0x0e, 0x4c,
-       0xf0, 0x1a, 0xb1, 0x75, 0xf7, 0x62, 0x2e, 0x2d, 0x3e, 0x3c, 0xf4, 0x67,
-       0xd6, 0xd3, 0x65, 0xd5, 0xb2, 0x7a, 0xe6, 0x28, 0x30, 0xf0, 0x7c, 0x3f,
-       0xc6, 0x8b, 0x91, 0x1e, 0xa2, 0x3b, 0x49, 0xb5, 0xf2, 0x01, 0x9f, 0xa5,
-       0x53, 0xb2, 0x64, 0x51, 0xaa, 0x44, 0xf4, 0x77, 0x45, 0x85, 0x9e, 0xb7,
-       0xda, 0x69, 0xae, 0xf7, 0x83, 0x72, 0x02, 0xb8, 0xbc, 0x6d, 0x0d, 0x0f,
-       0x8d, 0x5b, 0x3c, 0x57, 0x7c, 0x9d, 0x83, 0x6f, 0x6f, 0x5b, 0xce, 0xd2,
-       0x68, 0xb4, 0xc8, 0x7d, 0xbd, 0x2d, 0xdc, 0xe7, 0x8f, 0x3f, 0x1c, 0x7c,
-       0xde, 0x0a, 0xc8, 0xbe, 0x1f, 0xa5, 0x92, 0x98, 0x6f, 0xac, 0xc8, 0xb0,
-       0xcf, 0xde, 0x91, 0xb3, 0x4c, 0xd9, 0x6f, 0xc5, 0x93, 0x56, 0x08, 0xfd,
-       0x1d, 0x72, 0x2c, 0xbd, 0x2e, 0x67, 0x59, 0x72, 0xac, 0x88, 0x6f, 0x7a,
-       0x65, 0xff, 0x3b, 0xa9, 0x9c, 0x15, 0x93, 0xfd, 0x57, 0x93, 0x49, 0xab,
-       0x5f, 0xf6, 0x1f, 0xbe, 0x2b, 0x67, 0xc5, 0x65, 0xff, 0xf7, 0x81, 0x8b,
-       0x41, 0xc7, 0x8a, 0x61, 0xfc, 0x25, 0x30, 0xfe, 0x9a, 0x41, 0x6d, 0x19,
-       0x8c, 0x61, 0xef, 0xb6, 0x4e, 0x97, 0x7d, 0x21, 0x7a, 0xbd, 0xfb, 0x32,
-       0x68, 0x63, 0xd0, 0xd9, 0x12, 0x29, 0x99, 0xee, 0x10, 0x68, 0x62, 0xd2,
-       0xb9, 0x52, 0x2b, 0xf9, 0x4e, 0xfa, 0xb0, 0xe7, 0xcf, 0x51, 0xd6, 0xd4,
-       0x69, 0xfd, 0x8c, 0x42, 0x9d, 0x7d, 0x6b, 0x28, 0x61, 0xe4, 0x29, 0xd5,
-       0x8d, 0x28, 0x6e, 0xd2, 0x24, 0x6d, 0x66, 0x71, 0xbd, 0x8a, 0x1e, 0x95,
-       0x22, 0xa1, 0x2c, 0x28, 0x3c, 0x72, 0xfa, 0x5d, 0x8e, 0x39, 0xb1, 0x26,
-       0xff, 0x85, 0x29, 0x35, 0x71, 0x2b, 0x0d, 0x1b, 0x8c, 0x0f, 0x80, 0x05,
-       0x1f, 0x74, 0x25, 0x79, 0x2a, 0x44, 0xc7, 0xec, 0x80, 0x92, 0x3a, 0x75,
-       0x37, 0x25, 0x63, 0x64, 0xaa, 0xd4, 0x25, 0xbe, 0x2d, 0x14, 0x43, 0x34,
-       0x6e, 0x93, 0x92, 0xb4, 0x99, 0x5e, 0xed, 0x18, 0x6f, 0x13, 0xb0, 0xe8,
-       0xeb, 0xf0, 0x51, 0x97, 0x91, 0x22, 0x9d, 0x71, 0x46, 0x7f, 0x50, 0x49,
-       0x8b, 0x39, 0x44, 0x7f, 0x78, 0x8c, 0x02, 0x74, 0xba, 0x68, 0x4a, 0xd8,
-       0x72, 0x39, 0x19, 0x33, 0x00, 0x07, 0xda, 0xd9, 0x26, 0x0d, 0xe3, 0x39,
-       0x6a, 0xf3, 0xfa, 0x21, 0xc8, 0xcc, 0xb7, 0x87, 0xb2, 0xd3, 0x62, 0xbe,
-       0xb0, 0x2f, 0xce, 0xf3, 0x75, 0x00, 0xee, 0x1d, 0xe0, 0xa5, 0x90, 0x26,
-       0x78, 0x95, 0xa0, 0xec, 0x84, 0x02, 0x79, 0xc2, 0x53, 0xd0, 0x2d, 0x0d,
-       0xfc, 0x35, 0xb2, 0xfa, 0x14, 0xca, 0x59, 0x9b, 0x28, 0x6f, 0xa0, 0x5d,
-       0xbc, 0xa0, 0x26, 0xed, 0x66, 0x4a, 0x69, 0x61, 0xec, 0x5f, 0xc8, 0x0a,
-       0x8d, 0xe1, 0x1b, 0xd5, 0x62, 0x98, 0x9f, 0x61, 0xef, 0xc3, 0x82, 0xfe,
-       0x4d, 0xf1, 0xfd, 0x74, 0x69, 0x22, 0xaf, 0x26, 0x4b, 0xed, 0xe4, 0x9b,
-       0x89, 0x40, 0x9a, 0xc7, 0xd5, 0xd4, 0x19, 0x8d, 0xfc, 0x93, 0x0a, 0x41,
-       0x3e, 0x0c, 0x5f, 0xfc, 0xb8, 0xba, 0xb3, 0x74, 0x41, 0x4d, 0x95, 0xf8,
-       0x1b, 0xc0, 0x16, 0x55, 0xd0, 0x96, 0xdf, 0xb7, 0x83, 0x96, 0x34, 0xac,
-       0xc6, 0x75, 0x3d, 0x51, 0x64, 0x99, 0xe5, 0x6f, 0xc1, 0x0f, 0xec, 0xe5,
-       0x9c, 0x0d, 0xfe, 0x08, 0x7e, 0x85, 0xc1, 0xaf, 0x6f, 0x82, 0x5f, 0xfd,
-       0xe0, 0x53, 0x8c, 0xde, 0x28, 0xf5, 0xd2, 0x6b, 0xa5, 0x1e, 0x7a, 0x15,
-       0x32, 0xf9, 0x4a, 0x29, 0x4c, 0x2f, 0x97, 0x3a, 0xe8, 0xa5, 0x52, 0x88,
-       0xce, 0x0b, 0x1e, 0xa6, 0x21, 0xff, 0x82, 0xaf, 0xfa, 0x26, 0xf0, 0xa4,
-       0x1d, 0x3c, 0x59, 0x0f, 0x79, 0xd9, 0x08, 0xf9, 0x9b, 0xee, 0xd6, 0x69,
-       0xaa, 0x9b, 0x12, 0x41, 0xf4, 0x6f, 0x89, 0x6b, 0x82, 0x4e, 0x1a, 0xc6,
-       0xc7, 0x26, 0xfc, 0x94, 0x32, 0x4e, 0xd3, 0x7b, 0x93, 0x1a, 0x8d, 0x95,
-       0xa6, 0x36, 0x3a, 0x7c, 0xe3, 0xf6, 0x2c, 0x5d, 0x44, 0x5f, 0xca, 0x98,
-       0xa5, 0x4b, 0xdb, 0x54, 0x1a, 0x9d, 0xfe, 0x1b, 0x4a, 0x9e, 0x39, 0x4d,
-       0x3f, 0xfe, 0x3a, 0x51, 0x06, 0x34, 0x51, 0xfb, 0x7e, 0x5a, 0x4e, 0x18,
-       0xa0, 0x45, 0x5f, 0xaf, 0x90, 0x08, 0xb5, 0x8f, 0x79, 0x19, 0x86, 0xae,
-       0x68, 0x4a, 0xca, 0x7e, 0x01, 0xfa, 0xd2, 0xaa, 0x24, 0xa7, 0x88, 0x72,
-       0x53, 0x65, 0xca, 0xc5, 0xfc, 0xf4, 0x98, 0x51, 0xa6, 0x74, 0xac, 0x89,
-       0xbe, 0x68, 0xb4, 0xd3, 0x68, 0xef, 0x6f, 0xf8, 0xdc, 0x5c, 0x65, 0xba,
-       0xd4, 0x8f, 0x77, 0xee, 0x23, 0x9a, 0x12, 0xef, 0x4e, 0x7f, 0xbe, 0xe4,
-       0xa7, 0x84, 0x99, 0x0f, 0x69, 0xf4, 0x8e, 0xcf, 0xc1, 0x29, 0xe1, 0x8e,
-       0x81, 0x57, 0xc3, 0xb0, 0x0f, 0x8e, 0x0c, 0x66, 0x27, 0xd6, 0x5c, 0x4b,
-       0x88, 0x6e, 0xc0, 0x0b, 0xd9, 0xd3, 0x18, 0x8f, 0x61, 0x25, 0x6e, 0x52,
-       0xa7, 0xd0, 0x8d, 0x7e, 0xc0, 0x0c, 0x28, 0xfb, 0x4a, 0xcc, 0x6b, 0xbc,
-       0x17, 0x19, 0xd7, 0xcd, 0x80, 0xd5, 0xf0, 0x4c, 0x48, 0x9c, 0xbd, 0x78,
-       0xf2, 0x5c, 0x8c, 0x27, 0x3f, 0x7f, 0xcf, 0x83, 0xe7, 0xe7, 0x2b, 0xef,
-       0x53, 0x9e, 0xf7, 0x7c, 0xe9, 0x4f, 0x03, 0x0e, 0x7e, 0x4c, 0xcf, 0x01,
-       0x1a, 0x9d, 0x38, 0x2c, 0xd7, 0xc2, 0x7b, 0x91, 0xd7, 0x38, 0x0d, 0x3a,
-       0x09, 0xc8, 0x15, 0xd6, 0x3a, 0xec, 0x59, 0xeb, 0x49, 0xcf, 0x5a, 0x4f,
-       0x7a, 0xd6, 0xca, 0x83, 0xb6, 0xb4, 0x4e, 0xb5, 0xfc, 0xd0, 0x51, 0xee,
-       0x39, 0x8e, 0x39, 0x9f, 0x03, 0x5f, 0xbe, 0x0a, 0x98, 0x38, 0x2d, 0xda,
-       0xa0, 0xc7, 0x94, 0x46, 0x7b, 0x4d, 0x7e, 0x7f, 0xb1, 0xd5, 0xc1, 0x8b,
-       0xdf, 0x2f, 0x48, 0x9c, 0x5a, 0x1d, 0xb8, 0xd2, 0x15, 0xa1, 0xff, 0xf3,
-       0x25, 0xd6, 0x4f, 0x8a, 0xf9, 0x2c, 0x3a, 0x94, 0x8e, 0xb5, 0xd3, 0x98,
-       0xa1, 0xc4, 0x46, 0x7b, 0x9a, 0x99, 0x8e, 0x09, 0xd5, 0x6a, 0x85, 0x0e,
-       0x50, 0x58, 0x65, 0xdb, 0x25, 0xf0, 0x7b, 0x49, 0xe2, 0x61, 0x70, 0x3b,
-       0xa3, 0x5a, 0xc1, 0xba, 0x7e, 0x96, 0xdf, 0x57, 0xf0, 0xce, 0x32, 0x9c,
-       0xd4, 0x9c, 0xb5, 0x5f, 0x45, 0x9b, 0xed, 0xce, 0x66, 0xd9, 0x76, 0xc7,
-       0xff, 0xa0, 0xa9, 0xb6, 0xfd, 0x05, 0xb3, 0xb6, 0xed, 0xea, 0x82, 0xd7,
-       0x66, 0xf1, 0xde, 0xc2, 0xe4, 0xb3, 0x58, 0x8e, 0xfc, 0xc0, 0x35, 0x06,
-       0x3d, 0x6c, 0x96, 0x38, 0x7c, 0x4b, 0xe2, 0x00, 0x5c, 0x01, 0x37, 0x5a,
-       0xe2, 0x6f, 0x04, 0x4b, 0xea, 0xda, 0x4c, 0x43, 0xf7, 0x7d, 0xad, 0x18,
-       0xbf, 0xec, 0xe3, 0x75, 0xdc, 0x27, 0x29, 0x69, 0xe8, 0xc9, 0xd8, 0xb4,
-       0x46, 0xd9, 0xd8, 0x26, 0x21, 0xd7, 0xd9, 0x58, 0xd5, 0x06, 0x8c, 0x4e,
-       0xd4, 0xdb, 0x00, 0xfe, 0x8e, 0x6d, 0x80, 0xa3, 0xfb, 0x63, 0xd3, 0x6c,
-       0x0b, 0x1c, 0xdd, 0x3f, 0x36, 0xc1, 0x36, 0x41, 0xcc, 0x09, 0xfd, 0x67,
-       0x3b, 0xe0, 0xda, 0x00, 0xfe, 0x86, 0x6d, 0x80, 0x0f, 0xf2, 0xcd, 0xf3,
-       0xb9, 0x6b, 0x8f, 0xd7, 0xcd, 0x3b, 0xce, 0xb6, 0x45, 0xd9, 0xd9, 0xcd,
-       0x30, 0xc7, 0xb1, 0x76, 0x80, 0x0a, 0xd3, 0xcc, 0xc3, 0x48, 0xe8, 0x08,
-       0x1d, 0x17, 0x36, 0xef, 0xf4, 0x04, 0x25, 0x0e, 0x9e, 0x18, 0xa0, 0x34,
-       0x6c, 0xc0, 0xdc, 0xc4, 0xb5, 0x32, 0xf8, 0x78, 0x47, 0x13, 0x59, 0xb0,
-       0x75, 0xf0, 0x93, 0xfd, 0x7e, 0xf2, 0xc5, 0xe3, 0x90, 0xb7, 0x98, 0xf0,
-       0x5d, 0xd5, 0x9f, 0xa6, 0xed, 0xaa, 0x69, 0x37, 0xc1, 0x3f, 0x62, 0xde,
-       0xfe, 0x98, 0x90, 0x4d, 0xef, 0x2f, 0x09, 0x1b, 0x94, 0x8c, 0x7d, 0x08,
-       0xf9, 0x75, 0x69, 0xe4, 0xea, 0x1f, 0xdb, 0xfa, 0x2b, 0x1e, 0x1f, 0xb2,
-       0x05, 0x76, 0xdf, 0x84, 0x3c, 0xb9, 0x76, 0x9f, 0xed, 0x71, 0x88, 0x6d,
-       0x26, 0xf4, 0x8d, 0x6d, 0x70, 0x80, 0xd4, 0x19, 0x4d, 0xda, 0x69, 0x5d,
-       0xda, 0xe9, 0x00, 0x6c, 0x34, 0xb7, 0x0d, 0xd9, 0x36, 0x45, 0x1b, 0xf6,
-       0x1a, 0xf6, 0x70, 0x77, 0x3a, 0x35, 0xc1, 0xfe, 0x10, 0xbe, 0x7b, 0x86,
-       0x75, 0xf8, 0xdb, 0x43, 0x23, 0xd3, 0xc2, 0x07, 0xb0, 0xff, 0x80, 0x65,
-       0x66, 0x1b, 0xce, 0xb6, 0x1c, 0xfb, 0x2e, 0x62, 0xdd, 0x8a, 0xad, 0x64,
-       0x39, 0xf1, 0xe2, 0xc5, 0x38, 0xad, 0x21, 0xf5, 0xa4, 0x43, 0x6b, 0x35,
-       0xfe, 0xa8, 0x46, 0x2d, 0x4c, 0x63, 0xc6, 0x7f, 0x2b, 0x70, 0xe6, 0x7d,
-       0xfd, 0x4f, 0xe0, 0xcc, 0xeb, 0xd6, 0xe3, 0x4d, 0x7a, 0x6b, 0xfc, 0xac,
-       0xfe, 0xf0, 0x33, 0xa4, 0x37, 0xc7, 0xcf, 0xd2, 0xbf, 0x58, 0x74, 0x9f,
-       0x0e, 0x3f, 0xdb, 0xad, 0xc0, 0xcf, 0x16, 0xa1, 0xef, 0x53, 0x3a, 0x1d,
-       0x3c, 0x15, 0xc9, 0xfc, 0x2b, 0x45, 0x61, 0x3f, 0x76, 0xd0, 0xc8, 0x94,
-       0x42, 0x7a, 0x17, 0xb5, 0xc3, 0x7f, 0xf4, 0x37, 0x61, 0xfe, 0x5d, 0x44,
-       0x9b, 0x1d, 0xbf, 0xd9, 0x15, 0x1e, 0x05, 0xff, 0xd3, 0x2f, 0x7e, 0x05,
-       0xdf, 0x3c, 0x4d, 0x07, 0xa7, 0x0e, 0x2b, 0x39, 0xfb, 0x08, 0xe0, 0x97,
-       0x83, 0xd5, 0x01, 0x9b, 0x07, 0xec, 0x97, 0x31, 0xef, 0xd3, 0xa4, 0xdf,
-       0x1e, 0x19, 0x48, 0x28, 0xc0, 0xe3, 0x45, 0x01, 0x2f, 0x7d, 0x71, 0x97,
-       0xb1, 0x53, 0xf0, 0x3f, 0x40, 0xef, 0x15, 0x2f, 0x80, 0xbe, 0xbd, 0xf0,
-       0x39, 0x91, 0x67, 0x61, 0x93, 0xe1, 0x8f, 0x22, 0x57, 0x31, 0x2d, 0x7c,
-       0x11, 0x29, 0x0f, 0x76, 0xa7, 0x41, 0xef, 0x38, 0xfc, 0xd3, 0x00, 0xfc,
-       0x53, 0x0c, 0xbe, 0xa9, 0x07, 0x7e, 0xc9, 0x82, 0x5f, 0x0a, 0x83, 0x1f,
-       0x06, 0xcd, 0xc2, 0x47, 0xcd, 0x42, 0xfe, 0xe7, 0x66, 0x48, 0x19, 0x04,
-       0xad, 0xcf, 0xc1, 0x3f, 0x26, 0x63, 0x77, 0x42, 0xcf, 0x22, 0x17, 0x66,
-       0xd5, 0x41, 0xca, 0xc1, 0x9f, 0x77, 0x6e, 0x8b, 0x62, 0xbd, 0x26, 0x4a,
-       0x84, 0x5c, 0x1d, 0xe5, 0xdf, 0x7e, 0x85, 0xac, 0x7f, 0x06, 0xef, 0x22,
-       0x61, 0xa2, 0x3d, 0x94, 0xb5, 0xa3, 0x46, 0xa7, 0xda, 0x03, 0x18, 0x6e,
-       0x87, 0x95, 0x03, 0x53, 0x11, 0x05, 0xfb, 0x03, 0xcd, 0x27, 0x60, 0xeb,
-       0xcb, 0x34, 0x1e, 0x63, 0x3d, 0x29, 0xd3, 0xf3, 0xb1, 0xc8, 0x40, 0x9e,
-       0x5a, 0xe9, 0x98, 0x39, 0x21, 0x7c, 0xbc, 0x16, 0x3f, 0x21, 0x74, 0x2c,
-       0x67, 0xe1, 0x59, 0xec, 0x54, 0xb2, 0x53, 0xbc, 0x7e, 0x14, 0x5a, 0xee,
-       0xc7, 0x93, 0xe7, 0x07, 0xdd, 0xfa, 0x49, 0x39, 0xd8, 0x9d, 0x87, 0x77,
-       0x88, 0x18, 0x8b, 0x58, 0x39, 0x35, 0x11, 0x0d, 0x45, 0x55, 0x8d, 0x86,
-       0x35, 0x85, 0x46, 0x61, 0x6f, 0xd2, 0xb1, 0xff, 0x2c, 0x1f, 0x33, 0x79,
-       0xbc, 0x99, 0xbe, 0x2a, 0xfc, 0x0d, 0xd6, 0x2e, 0x4c, 0x63, 0x5d, 0x3f,
-       0xf8, 0xcb, 0xeb, 0xf2, 0x3c, 0x68, 0xc3, 0xf6, 0x6b, 0x56, 0xe4, 0xd9,
-       0x3c, 0xed, 0x00, 0x6d, 0xd9, 0x66, 0xc1, 0x3e, 0x0c, 0x60, 0xed, 0x5e,
-       0xd8, 0x4f, 0x3c, 0x93, 0xbd, 0x1c, 0x07, 0x05, 0x68, 0xd8, 0x64, 0x79,
-       0xd4, 0xe5, 0x98, 0xe9, 0x19, 0xf3, 0xcb, 0xb1, 0x20, 0xfe, 0xe0, 0x7f,
-       0x4d, 0x96, 0x19, 0x6e, 0x73, 0x4c, 0xc6, 0x34, 0x09, 0xd3, 0xdc, 0x64,
-       0x02, 0x34, 0x8b, 0x9c, 0x4d, 0x10, 0xd3, 0x0c, 0x46, 0x7b, 0x7f, 0x82,
-       0xbe, 0x64, 0xaf, 0xf7, 0x3b, 0xb6, 0xb0, 0x55, 0x49, 0xc1, 0x17, 0xa8,
-       0x56, 0x0b, 0x7c, 0x45, 0x98, 0x5e, 0x15, 0xb0, 0x64, 0xa8, 0xf1, 0x68,
-       0xe8, 0x4b, 0x74, 0xab, 0xb0, 0x11, 0x09, 0xc3, 0x4b, 0xe3, 0xff, 0x52,
-       0xc9, 0x72, 0xbf, 0x69, 0xa5, 0xec, 0x20, 0xf3, 0x89, 0xd7, 0x33, 0x68,
-       0xae, 0xe4, 0xbc, 0xfb, 0x10, 0xa3, 0x16, 0x60, 0x6b, 0xce, 0x4f, 0xaa,
-       0xf4, 0xf8, 0x1d, 0xf0, 0x65, 0xb1, 0x6d, 0x58, 0xcb, 0xc4, 0x78, 0x1e,
-       0x6d, 0x15, 0x6d, 0xe8, 0x99, 0x11, 0x02, 0x8f, 0xb9, 0x9f, 0xe1, 0x4c,
-       0xfc, 0xbd, 0xcf, 0xb1, 0x75, 0x3e, 0xab, 0xde, 0x4a, 0x14, 0x64, 0x7a,
-       0xc5, 0x40, 0x2b, 0xcb, 0x50, 0xd5, 0x6d, 0xc2, 0x5f, 0x3b, 0xb6, 0xc4,
-       0x82, 0x2e, 0xc2, 0xe6, 0xf6, 0x79, 0x75, 0x91, 0xe3, 0x09, 0x57, 0x17,
-       0x23, 0xa1, 0x84, 0x0a, 0x5b, 0xdc, 0xa7, 0xd1, 0x09, 0xd1, 0x56, 0x28,
-       0x31, 0x18, 0x09, 0x2d, 0xa8, 0x1c, 0x4b, 0x33, 0x6c, 0x18, 0xf1, 0x4a,
-       0x40, 0xc2, 0x22, 0x9e, 0xb3, 0xdd, 0x98, 0x30, 0x84, 0x7e, 0x53, 0xf4,
-       0x1f, 0xab, 0xe8, 0xa8, 0x13, 0xff, 0xa9, 0x88, 0x11, 0x0b, 0x88, 0x11,
-       0x53, 0x42, 0x47, 0x8d, 0x04, 0x72, 0x04, 0xd0, 0xdc, 0xd1, 0xcf, 0x42,
-       0x91, 0x71, 0xc9, 0xb1, 0x5c, 0x0e, 0x00, 0x99, 0x13, 0x8e, 0x7d, 0xa4,
-       0x3c, 0xc7, 0x91, 0xa3, 0xea, 0x53, 0x34, 0x5c, 0x60, 0x3f, 0x8e, 0x3f,
-       0x9b, 0x6d, 0x2d, 0xec, 0xa3, 0xf0, 0xc5, 0x51, 0xf0, 0x39, 0x0f, 0x1a,
-       0xac, 0x97, 0x74, 0xdd, 0x4f, 0x07, 0xec, 0x3d, 0xa0, 0x79, 0x9c, 0x46,
-       0x4e, 0x8d, 0xb0, 0xcc, 0xf6, 0x14, 0x28, 0xd2, 0x73, 0x8c, 0xb6, 0x1b,
-       0x73, 0x2c, 0xdf, 0x83, 0xe5, 0x1d, 0xe0, 0x85, 0xd0, 0x51, 0xc8, 0x20,
-       0x65, 0x0b, 0x23, 0xf4, 0x58, 0x89, 0xfb, 0xf2, 0xa0, 0x1d, 0xe2, 0xda,
-       0xfe, 0xfd, 0x52, 0xce, 0x31, 0x9f, 0xe6, 0xce, 0x37, 0x22, 0xe7, 0x63,
-       0x38, 0x86, 0xe1, 0x6f, 0xaa, 0xf3, 0xee, 0x14, 0x3c, 0x8d, 0x18, 0x5d,
-       0x6a, 0x79, 0x87, 0x1f, 0xe3, 0xcf, 0xf7, 0xf3, 0x3b, 0xe6, 0x81, 0xef,
-       0x6f, 0xb6, 0xf6, 0x00, 0x76, 0x10, 0x73, 0xfa, 0xa9, 0xb3, 0xdd, 0xc5,
-       0x37, 0x81, 0xb5, 0xd9, 0xcf, 0x31, 0x9f, 0x1f, 0xa1, 0xec, 0xa9, 0x7c,
-       0x8f, 0x0a, 0x19, 0x9b, 0xcd, 0x28, 0xe4, 0xb7, 0x1e, 0xa6, 0xdc, 0xa9,
-       0xa3, 0x6c, 0x37, 0x40, 0xab, 0x3d, 0xb4, 0x6b, 0x22, 0xd2, 0x73, 0x80,
-       0x34, 0xb1, 0xce, 0x5b, 0x24, 0xe8, 0x1f, 0x9b, 0x15, 0xbe, 0x20, 0x43,
-       0xe9, 0x89, 0xed, 0xa1, 0x4b, 0xe8, 0x1b, 0x1e, 0x8c, 0x84, 0x17, 0xe8,
-       0x09, 0xd0, 0xe5, 0x23, 0xf8, 0x22, 0xab, 0x67, 0x0c, 0x3a, 0x84, 0x9c,
-       0x0a, 0xeb, 0x8f, 0x4a, 0xda, 0xe0, 0xbb, 0xcc, 0x51, 0xd0, 0x8f, 0xf2,
-       0x0e, 0x4d, 0x99, 0x9e, 0x4c, 0xcb, 0xaf, 0xc0, 0xf6, 0x1c, 0x11, 0xb1,
-       0x4b, 0x56, 0xd0, 0xee, 0xd2, 0x06, 0x47, 0x0e, 0x60, 0x8b, 0x30, 0xef,
-       0xe5, 0x41, 0x85, 0xb6, 0x20, 0x4e, 0x3f, 0x24, 0x78, 0xeb, 0xa3, 0x7d,
-       0x66, 0xd4, 0xd8, 0x47, 0xf3, 0x7e, 0x27, 0x56, 0xc0, 0x3c, 0x3d, 0xf7,
-       0x60, 0x0f, 0x90, 0x53, 0xfb, 0xeb, 0xeb, 0xa8, 0x2d, 0x12, 0x4e, 0xa8,
-       0x09, 0xfa, 0x93, 0xd2, 0xdd, 0xe4, 0xe8, 0x77, 0x2b, 0xdb, 0x7e, 0xf0,
-       0xb0, 0xd3, 0x69, 0x5b, 0x78, 0x16, 0x3a, 0xb1, 0x1e, 0xe3, 0xfe, 0xac,
-       0xc0, 0x7d, 0x84, 0xba, 0xa1, 0x6b, 0x22, 0x8f, 0x39, 0x51, 0x8b, 0x17,
-       0xf3, 0xbc, 0x9e, 0xcf, 0x5f, 0xc6, 0x3c, 0xdc, 0xcf, 0x70, 0x78, 0x2f,
-       0x3c, 0x41, 0x23, 0x90, 0xc7, 0x5c, 0x7f, 0x57, 0x68, 0x0c, 0xdf, 0xa4,
-       0x4a, 0x4d, 0x74, 0x54, 0xe3, 0xf1, 0x48, 0x38, 0xaf, 0x1e, 0x42, 0xdc,
-       0xf3, 0xb8, 0xea, 0xb7, 0x7e, 0xe6, 0x67, 0xbf, 0xe3, 0xb7, 0xae, 0x29,
-       0xd5, 0xb9, 0x10, 0x87, 0x8a, 0xdc, 0x60, 0x41, 0x19, 0x2c, 0x5d, 0x52,
-       0x92, 0x85, 0x6b, 0x4a, 0xaa, 0xc4, 0x30, 0x8e, 0xce, 0x67, 0xcf, 0x74,
-       0x82, 0x4e, 0x1f, 0x89, 0xef, 0xe6, 0x7a, 0x8f, 0x50, 0xea, 0xd4, 0xad,
-       0x94, 0x9e, 0xe6, 0xbc, 0x34, 0x02, 0x7c, 0x3f, 0x2a, 0xe7, 0x62, 0x41,
-       0xca, 0x9d, 0xe1, 0x31, 0xb6, 0x5f, 0xd6, 0xd5, 0x45, 0x1f, 0xef, 0x9f,
-       0xf9, 0x6f, 0x52, 0xc1, 0x7e, 0x53, 0xd2, 0x8f, 0xdf, 0x7d, 0x9c, 0x93,
-       0xe1, 0xf7, 0x6f, 0x86, 0xd3, 0xb7, 0x95, 0x16, 0x36, 0xdc, 0xc8, 0x3e,
-       0x57, 0xb3, 0xc7, 0x47, 0x7d, 0x7e, 0x6b, 0x7b, 0x13, 0xb5, 0x84, 0x80,
-       0xc3, 0x4a, 0x7b, 0x64, 0x98, 0x5f, 0x87, 0x1c, 0xb0, 0x4d, 0xd9, 0x0d,
-       0x7e, 0x5a, 0x6c, 0xc3, 0x60, 0x93, 0x76, 0x53, 0xae, 0xc4, 0xb2, 0x1d,
-       0x35, 0x32, 0x90, 0xb1, 0x34, 0x75, 0xb1, 0x1e, 0xb9, 0xba, 0x07, 0xdb,
-       0x9d, 0x87, 0xed, 0x46, 0x3c, 0x64, 0x53, 0xbe, 0x29, 0xce, 0x36, 0xbc,
-       0x0b, 0xb2, 0x85, 0xbe, 0x62, 0x55, 0x17, 0x77, 0x2d, 0xc1, 0x5d, 0x5b,
-       0xc2, 0xa3, 0x02, 0xd5, 0xe2, 0x3f, 0x4b, 0x8c, 0xff, 0x5f, 0x00, 0xff,
-       0xcf, 0x01, 0x7f, 0xc6, 0xa9, 0x31, 0xfe, 0x3b, 0x2b, 0xf8, 0x33, 0x0c,
-       0xfc, 0x1c, 0x64, 0xf1, 0x0d, 0xe8, 0xe2, 0x6b, 0x36, 0x7c, 0x9d, 0x0d,
-       0xff, 0x67, 0xc3, 0xdf, 0xd9, 0xf0, 0x8b, 0x36, 0x7c, 0x1e, 0xf6, 0x74,
-       0x0e, 0x36, 0xe9, 0xac, 0x9d, 0x34, 0x58, 0x9f, 0x92, 0x31, 0xf6, 0x9d,
-       0xbb, 0x65, 0xde, 0x1d, 0x92, 0x71, 0xf7, 0xa7, 0x64, 0x2c, 0x7b, 0x00,
-       0xb1, 0xec, 0x66, 0x1a, 0xed, 0xe1, 0x9c, 0xa4, 0x05, 0xcf, 0x75, 0x78,
-       0x22, 0x6e, 0xed, 0x49, 0x48, 0xbd, 0xfc, 0x0c, 0x62, 0x5c, 0xd8, 0xff,
-       0x1e, 0xe4, 0x37, 0x19, 0xc4, 0x6a, 0x56, 0x1f, 0xc7, 0xe5, 0xb0, 0x65,
-       0xef, 0x37, 0x39, 0x76, 0xfe, 0x2e, 0x19, 0x03, 0xbb, 0xed, 0x56, 0xc0,
-       0xa4, 0xd1, 0xd7, 0x8a, 0x6f, 0x7e, 0x07, 0xb2, 0xdf, 0x86, 0xf6, 0xce,
-       0x3a, 0x18, 0xe4, 0xb3, 0x56, 0x16, 0x7d, 0x11, 0xc0, 0xb4, 0x61, 0x9d,
-       0x0e, 0xb4, 0xf7, 0xa0, 0x7d, 0x8b, 0xb3, 0x8e, 0xf1, 0x2b, 0x68, 0xa7,
-       0xea, 0xbe, 0xd9, 0x8a, 0xbe, 0x4c, 0x5d, 0xdf, 0x9b, 0xe8, 0x4b, 0xa2,
-       0x6f, 0x51, 0x7e, 0x97, 0x47, 0x3b, 0x52, 0x07, 0xb3, 0x88, 0x3e, 0xc6,
-       0xf1, 0x5b, 0x78, 0xde, 0x47, 0xa3, 0x19, 0x8e, 0x03, 0xdc, 0xb1, 0xdc,
-       0x7a, 0x6a, 0xe3, 0xdc, 0xf7, 0x43, 0x21, 0x3b, 0xf3, 0xd2, 0x46, 0xa7,
-       0x27, 0xd8, 0x4f, 0x8c, 0x20, 0xee, 0xe1, 0x71, 0xe1, 0x9c, 0x3c, 0xfd,
-       0x1f, 0x00, 0xf6, 0x61, 0x8c, 0x21, 0x56, 0xb7, 0xcb, 0x4d, 0x8d, 0xc7,
-       0x1f, 0xc5, 0xf8, 0x5f, 0xca, 0x6f, 0x2b, 0x73, 0x03, 0xfe, 0x1b, 0x75,
-       0x7d, 0x6a, 0xb0, 0xb6, 0xbd, 0xd6, 0xf3, 0xbe, 0x4d, 0x5f, 0xfa, 0xfd,
-       0x48, 0x1d, 0xfc, 0xef, 0x6e, 0xa8, 0x6d, 0x3f, 0xc5, 0xdf, 0x20, 0x87,
-       0x70, 0xdb, 0x09, 0xc8, 0x1d, 0xdb, 0xa4, 0xfa, 0x79, 0x3e, 0x6b, 0xd4,
-       0xf6, 0x6d, 0x32, 0x6b, 0xdb, 0x1c, 0x27, 0x31, 0x5c, 0x08, 0xf2, 0xde,
-       0xa1, 0xec, 0xb2, 0x7f, 0x13, 0xe3, 0x61, 0xe5, 0x5e, 0xdb, 0x8b, 0x67,
-       0x48, 0xe6, 0x46, 0xe1, 0x4a, 0xcc, 0x3b, 0x5f, 0x0a, 0x40, 0xae, 0x3e,
-       0x0f, 0x9e, 0x73, 0xdc, 0x53, 0xd5, 0xf1, 0xf7, 0x68, 0x39, 0x1d, 0x67,
-       0x1f, 0xc0, 0x31, 0xfe, 0x36, 0x11, 0x1f, 0xfb, 0xe2, 0x4f, 0x70, 0x0c,
-       0xf6, 0xb4, 0xe3, 0x5b, 0x2c, 0xf8, 0x43, 0xb4, 0x4b, 0x7e, 0xc7, 0x6e,
-       0x22, 0x9f, 0xc8, 0x16, 0xd8, 0x9f, 0xb1, 0x0f, 0x89, 0xc0, 0x4e, 0xb3,
-       0x1f, 0xfd, 0x24, 0x7d, 0xc6, 0x5d, 0xcd, 0x6c, 0xfb, 0x34, 0xeb, 0x05,
-       0xc4, 0x0b, 0x1c, 0xe7, 0xb1, 0xed, 0xc6, 0x7b, 0xd1, 0x8d, 0x57, 0xee,
-       0xd7, 0xc8, 0xaa, 0xfa, 0x11, 0x67, 0x8f, 0x5b, 0x59, 0x37, 0x56, 0xb1,
-       0xef, 0xc6, 0xb6, 0xed, 0xc7, 0x75, 0xb6, 0xe1, 0xb2, 0xb0, 0x0d, 0x0f,
-       0x6a, 0x7e, 0xeb, 0xf7, 0x9b, 0x1d, 0x79, 0x6d, 0x6c, 0x1b, 0xee, 0xad,
-       0xd8, 0x06, 0x57, 0x5e, 0xbd, 0x79, 0xeb, 0x0f, 0xc0, 0x1b, 0x0b, 0xbc,
-       0xa9, 0xaf, 0xd5, 0x70, 0x8e, 0xe2, 0x87, 0x1f, 0xe2, 0x18, 0x91, 0x73,
-       0xd9, 0x18, 0xe5, 0x62, 0x45, 0xc4, 0x6a, 0x91, 0xd9, 0xd9, 0x4a, 0x8e,
-       0xf5, 0x35, 0x69, 0xbb, 0x6b, 0xe2, 0x22, 0x7a, 0xbc, 0x78, 0x09, 0xf8,
-       0x73, 0xbc, 0xa5, 0x49, 0x1b, 0xc1, 0xfd, 0xe3, 0x12, 0x47, 0x7e, 0xe7,
-       0x3a, 0x1e, 0x7c, 0x69, 0xf1, 0x47, 0xe0, 0x15, 0xc7, 0x7d, 0x51, 0x27,
-       0xde, 0xab, 0x89, 0xa9, 0xd7, 0xf8, 0xc9, 0xe2, 0x78, 0x89, 0x61, 0x74,
-       0x19, 0x2f, 0x05, 0x64, 0x5e, 0x63, 0xc8, 0x3c, 0x87, 0x63, 0x6d, 0xae,
-       0xb1, 0xd6, 0xc7, 0x50, 0x0b, 0x43, 0xc1, 0x6d, 0xcc, 0x13, 0x8e, 0xa1,
-       0xda, 0x28, 0x39, 0xe3, 0xc4, 0x50, 0x4e, 0x9d, 0xcd, 0xcd, 0x71, 0x5c,
-       0x5c, 0xd9, 0x0f, 0xef, 0xc0, 0x3e, 0x45, 0x9e, 0x14, 0x74, 0xea, 0x7f,
-       0x1a, 0xec, 0xf6, 0x51, 0xf4, 0x8f, 0xba, 0xfd, 0x9e, 0x5c, 0xc3, 0xc5,
-       0x85, 0x7d, 0xbd, 0x1b, 0xd3, 0xed, 0x96, 0x31, 0x1d, 0x62, 0x18, 0xdb,
-       0xc9, 0xbb, 0xf6, 0x16, 0x33, 0xe8, 0xe3, 0x75, 0x11, 0x1b, 0x12, 0xc7,
-       0x49, 0x90, 0xaf, 0xfd, 0x91, 0x50, 0x58, 0xad, 0xc7, 0xab, 0x75, 0xa1,
-       0x16, 0xaf, 0x41, 0xf1, 0xdd, 0xf8, 0x92, 0xef, 0x48, 0xc4, 0x92, 0xe3,
-       0xf6, 0x10, 0xe8, 0xc5, 0xf8, 0xb9, 0xba, 0xe1, 0xc6, 0xc9, 0x8c, 0xd3,
-       0x3f, 0x82, 0xc6, 0xbb, 0x15, 0xfe, 0x7e, 0xcc, 0xde, 0x2f, 0xe8, 0x96,
-       0x15, 0xb8, 0x0e, 0x7b, 0x70, 0x1d, 0x91, 0xb8, 0xb2, 0x2e, 0xb0, 0x7e,
-       0x78, 0x6b, 0x9a, 0xa6, 0xd8, 0x1b, 0x70, 0x0e, 0xf3, 0xb9, 0xb9, 0x6a,
-       0x2d, 0x0c, 0xf9, 0xb6, 0xc1, 0x1f, 0x02, 0xd7, 0xac, 0x88, 0x43, 0x03,
-       0x0b, 0xf5, 0x34, 0x1c, 0xc7, 0x5a, 0x88, 0xdb, 0x81, 0x8f, 0xcb, 0xf3,
-       0x26, 0x89, 0xcf, 0x37, 0xc5, 0xdc, 0x63, 0xa2, 0x06, 0xea, 0xd3, 0x39,
-       0x77, 0xc9, 0x0a, 0xde, 0x69, 0x92, 0x77, 0x8f, 0x56, 0xf0, 0x73, 0x78,
-       0x1c, 0x90, 0x74, 0xe5, 0xdc, 0x95, 0x75, 0x5a, 0xf0, 0xa7, 0x9d, 0x73,
-       0xd3, 0x41, 0x6a, 0x14, 0x23, 0x2f, 0x0c, 0xa9, 0xdb, 0x1c, 0x3a, 0x3a,
-       0x31, 0xf2, 0xda, 0xba, 0x18, 0xf9, 0xb6, 0x20, 0xc7, 0x5a, 0xc3, 0x50,
-       0x82, 0x79, 0xf8, 0xba, 0x97, 0x6d, 0xc8, 0x36, 0x70, 0x3d, 0x5f, 0x53,
-       0xbb, 0xec, 0x59, 0xa6, 0xd6, 0x1c, 0x20, 0xdf, 0x0c, 0xfb, 0x0e, 0x0b,
-       0x79, 0x06, 0x91, 0x36, 0xc9, 0x3a, 0xcb, 0xbe, 0xbd, 0x1a, 0x67, 0xcf,
-       0x51, 0xa3, 0x18, 0xfb, 0x46, 0xfd, 0xfa, 0x79, 0xbf, 0xdf, 0x3a, 0xac,
-       0x3b, 0x36, 0x73, 0x25, 0xbf, 0xee, 0xc2, 0xed, 0x41, 0x9c, 0xad, 0x50,
-       0x93, 0x55, 0xc0, 0xfe, 0xde, 0xf0, 0x37, 0x5b, 0xae, 0x2e, 0x06, 0x68,
-       0xfd, 0xcc, 0x2d, 0x42, 0x1f, 0x8d, 0xc9, 0xaa, 0x3e, 0x8e, 0x82, 0x37,
-       0x19, 0xa7, 0x06, 0x60, 0xae, 0xa7, 0xeb, 0xd7, 0x0b, 0xc6, 0xed, 0x37,
-       0xfd, 0xaa, 0xe5, 0xca, 0xc0, 0xf5, 0xf2, 0x91, 0x4f, 0xd5, 0xd1, 0xba,
-       0x51, 0x4d, 0xf8, 0x2c, 0xe8, 0x1a, 0x47, 0xde, 0x1d, 0x79, 0x81, 0x10,
-       0x3b, 0x39, 0x79, 0x78, 0x1a, 0xb9, 0x77, 0xe4, 0x02, 0xe7, 0xe3, 0x6e,
-       0x7e, 0xfe, 0x6a, 0x29, 0x72, 0x36, 0x8f, 0x9c, 0x79, 0x1e, 0x39, 0xf9,
-       0xcb, 0xc8, 0xc9, 0xcf, 0x97, 0x7a, 0x41, 0xff, 0x1e, 0x99, 0x8f, 0xb3,
-       0x8e, 0x99, 0x74, 0x11, 0xb9, 0xd3, 0x77, 0x67, 0xd8, 0x46, 0x74, 0xd1,
-       0x3d, 0xc8, 0x35, 0xbe, 0x3f, 0xa9, 0x68, 0x9d, 0x7d, 0x01, 0x5f, 0xc2,
-       0xb8, 0x91, 0x38, 0x71, 0x29, 0x4f, 0x1a, 0xc7, 0x8a, 0x23, 0x4d, 0x7e,
-       0x6b, 0xae, 0x95, 0x5a, 0xf6, 0x2c, 0xcb, 0x93, 0x6a, 0xac, 0xe8, 0xc2,
-       0x19, 0xd4, 0xd9, 0xf7, 0x87, 0x9c, 0xdb, 0xc4, 0x48, 0xe4, 0xd3, 0xeb,
-       0xe8, 0xed, 0x93, 0x65, 0xda, 0x19, 0xbb, 0x56, 0xbe, 0x68, 0xad, 0xa3,
-       0x6c, 0xef, 0x43, 0x32, 0x97, 0x5c, 0x78, 0x28, 0x69, 0xe5, 0x43, 0x3e,
-       0xf7, 0x7c, 0x62, 0x42, 0x47, 0x84, 0xc8, 0xbf, 0x20, 0xcd, 0x0d, 0x20,
-       0x71, 0x6e, 0xd9, 0xfe, 0x02, 0x1f, 0x10, 0xb1, 0x6d, 0x9c, 0x33, 0x03,
-       0xa2, 0xd6, 0xb6, 0xd1, 0xe2, 0x7e, 0x03, 0xfc, 0xbe, 0x8f, 0xe6, 0x90,
-       0x43, 0x14, 0x44, 0x1e, 0xde, 0x0e, 0x78, 0x37, 0x0f, 0xbf, 0x1f, 0xb9,
-       0x01, 0xd3, 0xd8, 0x04, 0xfc, 0x6f, 0x03, 0xc6, 0x6b, 0x43, 0x9f, 0x6b,
-       0x22, 0xf1, 0x3d, 0x8f, 0xb7, 0x13, 0xd7, 0x65, 0xab, 0xf3, 0xf2, 0x9c,
-       0x3c, 0xf6, 0x61, 0xf9, 0xf6, 0xbe, 0x3e, 0xcf, 0xdc, 0x6d, 0x9e, 0xb9,
-       0xef, 0xf0, 0xcc, 0xed, 0xc3, 0xb7, 0x2e, 0x3e, 0x41, 0x7c, 0xeb, 0xae,
-       0xf1, 0xb7, 0x9e, 0x35, 0x5c, 0xdc, 0xdb, 0x3d, 0xb8, 0xbf, 0x8f, 0xf9,
-       0xb9, 0xcf, 0xf4, 0xf4, 0xf1, 0x9a, 0x1b, 0x68, 0x6e, 0xb0, 0x8d, 0x16,
-       0x4f, 0x72, 0x5f, 0xd0, 0x83, 0x0b, 0xe3, 0x17, 0x90, 0x63, 0x6d, 0x74,
-       0xf1, 0x64, 0x8b, 0xc0, 0x9b, 0xfd, 0xf9, 0xc6, 0xca, 0x9a, 0x57, 0xb0,
-       0xa6, 0x3b, 0x97, 0x89, 0x6f, 0x19, 0x96, 0xf1, 0xe3, 0x31, 0xee, 0xe3,
-       0xb1, 0x37, 0xcb, 0x5f, 0x33, 0x82, 0xce, 0x9e, 0x0d, 0xc6, 0xcd, 0xfd,
-       0x56, 0x6b, 0x26, 0x8b, 0xdb, 0x9d, 0x34, 0x1b, 0xd4, 0xc0, 0x37, 0x55,
-       0xfa, 0x28, 0xae, 0x23, 0xa8, 0x4a, 0xb4, 0x8f, 0xf9, 0xbc, 0x4e, 0xd6,
-       0xaf, 0x5b, 0x30, 0x6f, 0xd8, 0xcd, 0xd1, 0x88, 0xe5, 0x38, 0x27, 0xec,
-       0xbe, 0x26, 0xc7, 0xd9, 0xee, 0xb3, 0xdf, 0xc7, 0x53, 0xc8, 0xaa, 0x3c,
-       0xaf, 0x29, 0xed, 0xa0, 0x83, 0x50, 0xcf, 0x8b, 0xb2, 0x9e, 0xb2, 0xe8,
-       0xad, 0x99, 0x18, 0x4e, 0x1c, 0xe3, 0x9c, 0xed, 0xac, 0x85, 0xfe, 0xe0,
-       0xbd, 0x98, 0x00, 0x1e, 0x61, 0x8a, 0xe2, 0xaf, 0x50, 0xca, 0xe3, 0x69,
-       0xe1, 0xa9, 0xe0, 0xc9, 0xf5, 0x0c, 0x1d, 0x4f, 0xe8, 0x18, 0xec, 0x53,
-       0xb4, 0xef, 0x92, 0x93, 0x3f, 0x41, 0x37, 0xde, 0x9e, 0x74, 0xea, 0x51,
-       0x8b, 0xd6, 0x72, 0xf5, 0xa8, 0x3f, 0x67, 0x9e, 0x9c, 0x70, 0xeb, 0x51,
-       0x8b, 0x24, 0xea, 0x51, 0x27, 0x56, 0xa8, 0x47, 0x25, 0x56, 0x5f, 0x8f,
-       0xe2, 0xf9, 0x35, 0xda, 0xd7, 0x4f, 0xca, 0x17, 0x64, 0x3d, 0xea, 0x3d,
-       0x72, 0xea, 0x51, 0x17, 0xa9, 0x71, 0x3d, 0xea, 0x78, 0x5d, 0x3d, 0x2a,
-       0x28, 0xea, 0x51, 0x3c, 0x8f, 0x53, 0x8f, 0x12, 0xed, 0xbe, 0x88, 0xa7,
-       0xee, 0x42, 0xf4, 0xee, 0x64, 0x07, 0x68, 0x66, 0xd0, 0xf7, 0x1a, 0xda,
-       0x34, 0x45, 0xc8, 0xdb, 0x4a, 0x35, 0xd0, 0x07, 0x6e, 0xb8, 0xbe, 0xa2,
-       0xd0, 0x06, 0xcc, 0x9b, 0xec, 0x7b, 0xd8, 0x53, 0x63, 0x61, 0x9a, 0xff,
-       0x62, 0xea, 0x2c, 0x07, 0x45, 0x9d, 0xe5, 0x87, 0x6b, 0xbc, 0x75, 0x96,
-       0x45, 0xba, 0x7e, 0x9d, 0xe5, 0x60, 0x83, 0x3a, 0xcb, 0x5b, 0x54, 0xad,
-       0xb3, 0xbc, 0x45, 0xd5, 0x3a, 0xcb, 0xc1, 0x12, 0xe7, 0xe2, 0x3e, 0x89,
-       0x5f, 0x06, 0xed, 0x41, 0xf1, 0xc7, 0xb5, 0x97, 0xc5, 0xca, 0x1e, 0x7e,
-       0xd9, 0x6a, 0x2f, 0x6c, 0x03, 0x22, 0x17, 0x2e, 0xd7, 0xd4, 0x5e, 0xb8,
-       0x0d, 0x9d, 0xb1, 0xd7, 0x08, 0x19, 0x99, 0x83, 0x7f, 0x5f, 0x9c, 0x0c,
-       0x61, 0xce, 0x0e, 0xf8, 0x8c, 0x0e, 0xe4, 0x06, 0x61, 0xb4, 0x15, 0xda,
-       0x64, 0x0d, 0xa1, 0x8f, 0xc7, 0xd9, 0x0e, 0x43, 0xb7, 0x6c, 0x77, 0x7f,
-       0x0f, 0x48, 0x1a, 0x44, 0x68, 0xb8, 0x9d, 0xf4, 0x20, 0xfb, 0x8e, 0xc9,
-       0x3d, 0x74, 0xc8, 0xde, 0x22, 0xf6, 0xbd, 0xc1, 0xaa, 0x95, 0xb9, 0xc1,
-       0x1b, 0x90, 0xb9, 0xcc, 0xaa, 0x65, 0x8e, 0xe5, 0xcd, 0x39, 0xf7, 0xdd,
-       0x60, 0xf1, 0xfa, 0x1d, 0x02, 0xa7, 0x77, 0x1b, 0xc8, 0xfb, 0x18, 0xec,
-       0x8e, 0x33, 0xbf, 0x2e, 0xd7, 0xab, 0x8f, 0x87, 0x9f, 0x6d, 0x66, 0xff,
-       0xbd, 0x72, 0x3d, 0xb1, 0xde, 0x7f, 0xaf, 0xe4, 0x47, 0x15, 0x61, 0x93,
-       0xb3, 0x25, 0xae, 0xed, 0x7b, 0xf9, 0x33, 0x8f, 0x9c, 0x00, 0x7d, 0x42,
-       0x0f, 0x98, 0xae, 0x41, 0xf0, 0x01, 0xeb, 0xd8, 0x4f, 0xc9, 0x5a, 0x16,
-       0x9e, 0x05, 0x97, 0x7f, 0xad, 0xb0, 0x99, 0xee, 0x18, 0xdb, 0x01, 0x0b,
-       0xfe, 0x8f, 0xeb, 0x28, 0x7c, 0x8e, 0xca, 0xfd, 0x2e, 0x5f, 0xbb, 0x2e,
-       0xbc, 0xa7, 0x72, 0xbb, 0x5c, 0xce, 0x8a, 0x7a, 0x2d, 0xa9, 0x9d, 0x7d,
-       0xd3, 0x2d, 0x6c, 0x6b, 0xb6, 0x58, 0xae, 0xcc, 0x26, 0xf0, 0xce, 0x7c,
-       0x7d, 0x17, 0x36, 0x9c, 0xcf, 0xaa, 0xbf, 0x23, 0x6a, 0x04, 0x73, 0x36,
-       0xdb, 0x6b, 0x8e, 0x41, 0x7f, 0x0b, 0xb2, 0xc4, 0xef, 0x51, 0x71, 0x2e,
-       0x21, 0x6a, 0xf8, 0x83, 0xdc, 0x76, 0xed, 0x4a, 0x94, 0xed, 0x30, 0xf6,
-       0x5c, 0xa5, 0x31, 0xe2, 0x23, 0xc8, 0x0c, 0xc7, 0xb1, 0x0c, 0xe7, 0xc6,
-       0x9e, 0x9a, 0xa7, 0x66, 0xab, 0xcb, 0xb8, 0x88, 0x75, 0x39, 0x00, 0x9a,
-       0xed, 0x10, 0x31, 0xea, 0xb8, 0x5d, 0xa6, 0xea, 0x19, 0x3f, 0xd3, 0xdc,
-       0x39, 0xe7, 0x3f, 0x66, 0x2f, 0x47, 0xfb, 0xcd, 0x37, 0x48, 0x7b, 0x47,
-       0x1f, 0x6b, 0xe9, 0xae, 0x23, 0x7e, 0x71, 0xe9, 0xee, 0xfa, 0xa8, 0x49,
-       0x49, 0x83, 0xa8, 0xac, 0x2b, 0x7e, 0x5a, 0x9e, 0x29, 0xfd, 0x5f, 0xd8,
-       0xaf, 0xe2, 0xd9, 0xaf, 0xab, 0xbb, 0xfb, 0xe4, 0x7e, 0xc3, 0x75, 0xba,
-       0x1b, 0x97, 0x75, 0xb9, 0x5f, 0x84, 0xee, 0xba, 0x7b, 0xe2, 0xb5, 0xb7,
-       0x5c, 0x67, 0xdd, 0x67, 0x48, 0x8d, 0xaf, 0x14, 0x7b, 0xff, 0xb4, 0xf9,
-       0xe3, 0xc5, 0xde, 0x1f, 0x87, 0x9e, 0x5e, 0xbd, 0x65, 0x1a, 0xb6, 0x89,
-       0xb8, 0xc2, 0xd1, 0x1f, 0xd8, 0xe3, 0x82, 0x9f, 0x16, 0x1e, 0xd2, 0xe9,
-       0x9f, 0xee, 0xe4, 0xfa, 0xac, 0x26, 0x73, 0x7c, 0x6e, 0x7f, 0xb1, 0x95,
-       0x63, 0xab, 0x4d, 0xd6, 0x77, 0x44, 0x6e, 0x95, 0x57, 0x4d, 0x8f, 0x1f,
-       0x31, 0x30, 0xce, 0x63, 0x61, 0xba, 0x1c, 0xbc, 0x91, 0xb8, 0xbc, 0xcb,
-       0x58, 0xf4, 0xad, 0x26, 0x2e, 0xbf, 0x55, 0xf7, 0x5b, 0x7f, 0xdd, 0x7a,
-       0xbd, 0x3a, 0x47, 0x35, 0x2e, 0xe7, 0x7c, 0x3e, 0xe8, 0xd4, 0x18, 0x4c,
-       0x8e, 0xcf, 0xd7, 0x4a, 0x9e, 0xf0, 0x3b, 0x72, 0x11, 0x1b, 0x79, 0x08,
-       0x64, 0xfc, 0x55, 0xc8, 0xca, 0x2b, 0x36, 0xf2, 0x0e, 0x1b, 0xf9, 0x88,
-       0x8d, 0xdc, 0xc3, 0x46, 0xee, 0x61, 0xf7, 0xc8, 0x1c, 0x26, 0x23, 0xeb,
-       0x56, 0x7c, 0x46, 0xcb, 0xf9, 0x61, 0x5e, 0xc9, 0xd8, 0xe3, 0x7c, 0x1f,
-       0x41, 0x4d, 0xc6, 0x36, 0xca, 0x78, 0xf0, 0x38, 0xdf, 0x77, 0x28, 0xab,
-       0x71, 0xae, 0x45, 0x91, 0xaa, 0xc6, 0x6f, 0x87, 0x8f, 0xda, 0x0e, 0xbc,
-       0x9a, 0x79, 0xdc, 0xa7, 0xc6, 0x5b, 0x99, 0x76, 0x8a, 0x1a, 0x5f, 0x2b,
-       0xcf, 0x0d, 0x7a, 0x03, 0x0e, 0xfe, 0xdd, 0xdc, 0xd6, 0xd4, 0xf8, 0xdd,
-       0xec, 0xd3, 0xc2, 0xa4, 0xba, 0xfd, 0xb7, 0x07, 0x98, 0xae, 0xa4, 0xde,
-       0x16, 0xe0, 0xb8, 0x76, 0xde, 0xf6, 0x8b, 0x3b, 0x05, 0xc9, 0x18, 0xd7,
-       0xcc, 0xb8, 0x5d, 0xa5, 0xab, 0xba, 0x2c, 0x5d, 0xfd, 0x95, 0xfa, 0x3f,
-       0xd3, 0xd2, 0xc7, 0x70, 0xa2, 0x36, 0xc6, 0x34, 0x75, 0xe7, 0xe3, 0xf3,
-       0x66, 0x5e, 0x47, 0xdc, 0x63, 0xc0, 0xf3, 0x60, 0x33, 0xb5, 0x0d, 0x0e,
-       0xf9, 0x2d, 0xef, 0xba, 0x6c, 0x43, 0x76, 0x90, 0x37, 0xc7, 0x5a, 0x7e,
-       0xcd, 0xa8, 0x38, 0x1b, 0x49, 0xf6, 0x47, 0x85, 0xec, 0xb0, 0xac, 0x69,
-       0xe2, 0xce, 0xd5, 0x47, 0xe2, 0x1e, 0x09, 0xcb, 0x19, 0xcb, 0xf2, 0x78,
-       0x7f, 0x57, 0x58, 0x53, 0x5b, 0xb0, 0x46, 0x98, 0xd2, 0x25, 0x71, 0x56,
-       0x80, 0x7c, 0xe9, 0xdc, 0x3a, 0x6a, 0xfb, 0x07, 0xbd, 0x9a, 0xc7, 0x46,
-       0x9d, 0xb3, 0x7a, 0xbb, 0xde, 0xff, 0x8d, 0x8a, 0x73, 0x65, 0xc7, 0x06,
-       0xb9, 0xe7, 0xc3, 0xab, 0x3b, 0xff, 0xbe, 0xbe, 0x3e, 0xb5, 0xd4, 0xd7,
-       0x0d, 0x24, 0x0d, 0x98, 0x36, 0x8d, 0xcf, 0xee, 0xe7, 0x4b, 0x7c, 0xaf,
-       0x25, 0x12, 0xe3, 0xdc, 0x6d, 0x44, 0xdc, 0xf9, 0x50, 0x21, 0x85, 0x3a,
-       0x8d, 0x19, 0x9c, 0xf3, 0x85, 0x86, 0x7d, 0x71, 0xca, 0x64, 0x27, 0x48,
-       0x43, 0xac, 0x98, 0xa9, 0xd6, 0x03, 0x1f, 0x5c, 0x43, 0x96, 0x2b, 0x97,
-       0x51, 0xce, 0x1f, 0x6a, 0xce, 0xed, 0x16, 0xe9, 0xb0, 0x72, 0xa0, 0x74,
-       0x84, 0x0e, 0x34, 0x8c, 0x29, 0x1b, 0xd7, 0x03, 0x2f, 0xd6, 0xd5, 0x14,
-       0x16, 0x44, 0x4d, 0x21, 0xb7, 0xc6, 0x6f, 0x3d, 0x19, 0x70, 0xee, 0xb5,
-       0x34, 0xd6, 0x93, 0x5d, 0x15, 0x3d, 0x71, 0xe1, 0xf8, 0x2c, 0xbe, 0x8d,
-       0x76, 0x8a, 0xb5, 0x0e, 0x2b, 0x59, 0xbb, 0x95, 0x76, 0x1a, 0x0e, 0xd6,
-       0xa3, 0x36, 0xe3, 0x75, 0x58, 0x39, 0x68, 0xe7, 0x95, 0xb4, 0xa8, 0x3d,
-       0x70, 0x8c, 0xbf, 0xe6, 0xda, 0x30, 0x95, 0xe9, 0xed, 0x98, 0xfb, 0x3d,
-       0xc3, 0x78, 0x6b, 0x8a, 0x2e, 0x9d, 0xf8, 0x2e, 0x51, 0x58, 0xe6, 0x6f,
-       0xce, 0x7c, 0xb9, 0x29, 0xae, 0x25, 0xde, 0x8f, 0xfd, 0x33, 0xfc, 0x6e,
-       0x25, 0x39, 0x55, 0x2e, 0xa7, 0x31, 0x3e, 0xd6, 0x7b, 0xaf, 0xc8, 0x8d,
-       0xd4, 0x38, 0x0d, 0x71, 0x8e, 0xac, 0x2d, 0xc9, 0x91, 0xd3, 0xd0, 0x35,
-       0xc4, 0x20, 0x76, 0x13, 0xbe, 0x75, 0xe3, 0x91, 0xcf, 0xae, 0x75, 0x64,
-       0xe4, 0xbb, 0x12, 0x0f, 0x1e, 0xff, 0xfb, 0x80, 0x7b, 0x0f, 0x28, 0x77,
-       0x2a, 0x8d, 0xfd, 0x37, 0x51, 0xca, 0x74, 0xf2, 0xbb, 0xec, 0x99, 0x23,
-       0x1b, 0x6a, 0xe1, 0xd1, 0x77, 0xca, 0x85, 0x0f, 0xd6, 0xc1, 0xf3, 0x19,
-       0xd7, 0x5f, 0xd5, 0xc1, 0x07, 0x3d, 0xf0, 0x66, 0x1d, 0x3c, 0xe2, 0xae,
-       0x33, 0xdf, 0xa8, 0x83, 0x37, 0x3d, 0xf0, 0xed, 0x75, 0xf0, 0xed, 0x80,
-       0x7f, 0xa3, 0x0e, 0x1e, 0x7d, 0xa7, 0x90, 0x13, 0x08, 0xda, 0x70, 0x8c,
-       0x74, 0x48, 0xe6, 0x89, 0x78, 0x2e, 0xb9, 0x1f, 0xc9, 0xf2, 0xd3, 0x01,
-       0x1a, 0x7b, 0xeb, 0xb5, 0x09, 0xd8, 0xa8, 0xaa, 0x4c, 0x39, 0xfa, 0xea,
-       0x95, 0x25, 0x96, 0xbd, 0x3c, 0xe4, 0x15, 0x7a, 0x54, 0x80, 0x3e, 0x15,
-       0x5c, 0x5f, 0xca, 0x77, 0xaa, 0x22, 0xc7, 0x1d, 0x3d, 0x56, 0x68, 0xbd,
-       0x35, 0x2f, 0x73, 0x91, 0xab, 0x8c, 0x3b, 0xfc, 0x86, 0xeb, 0x3b, 0xe8,
-       0x84, 0x63, 0x57, 0x58, 0xbf, 0x79, 0x7e, 0x69, 0x5f, 0x4a, 0x2c, 0x87,
-       0xce, 0x3a, 0xe9, 0x25, 0x32, 0x1b, 0x5e, 0x52, 0x77, 0xf1, 0xd5, 0xd9,
-       0x77, 0x12, 0xf6, 0x3d, 0xd7, 0xe2, 0xb7, 0x36, 0xac, 0xbd, 0x9e, 0x7d,
-       0xcf, 0x78, 0xec, 0x7b, 0x38, 0x58, 0xf5, 0xf9, 0x8f, 0x09, 0x9f, 0xdf,
-       0xd1, 0xc0, 0x66, 0xac, 0xde, 0xe7, 0xef, 0xfd, 0xd8, 0x3e, 0x7f, 0xb9,
-       0x75, 0x57, 0xe3, 0xf3, 0x1f, 0x69, 0xf9, 0x78, 0x3e, 0x9f, 0xd7, 0xac,
-       0xaf, 0x65, 0x7a, 0xcf, 0x59, 0x8e, 0xca, 0x18, 0x7b, 0xb7, 0x27, 0xc6,
-       0x66, 0xfc, 0xbe, 0x27, 0xef, 0x02, 0x9e, 0x5e, 0xeb, 0xc8, 0xdb, 0x51,
-       0x19, 0xa7, 0x73, 0xec, 0x8d, 0xf7, 0xc2, 0x23, 0x90, 0xd1, 0x7c, 0x8f,
-       0x8f, 0x54, 0x9a, 0x35, 0x9d, 0xb3, 0xed, 0x9f, 0x6f, 0xae, 0x17, 0xa1,
-       0xcb, 0xc2, 0x9f, 0x24, 0x3e, 0x81, 0x5a, 0xea, 0x49, 0xc8, 0x8f, 0xbb,
-       0xaf, 0x95, 0x6a, 0xa9, 0xf5, 0xe7, 0x1f, 0x7c, 0xee, 0x41, 0xca, 0x03,
-       0x95, 0x73, 0x10, 0xaf, 0x4e, 0xe9, 0x94, 0x9d, 0x21, 0xdd, 0x8c, 0x93,
-       0xb2, 0x8f, 0x71, 0x8e, 0xfd, 0xb0, 0x52, 0x6f, 0x3f, 0x24, 0x6b, 0x30,
-       0xea, 0xb2, 0x77, 0x82, 0x7e, 0x02, 0x7c, 0x58, 0xaf, 0x9c, 0x1a, 0x8c,
-       0xea, 0xdc, 0x09, 0x3a, 0xfe, 0xf3, 0xbb, 0x13, 0xc4, 0xf3, 0x6b, 0xb4,
-       0xb7, 0xc1, 0x9d, 0x20, 0xdf, 0x2a, 0xef, 0x04, 0xad, 0x17, 0x35, 0x18,
-       0x9e, 0xc7, 0xa9, 0xc1, 0x70, 0xbb, 0xb3, 0x8f, 0xe5, 0x3a, 0x4c, 0xa3,
-       0x93, 0xb7, 0x88, 0x7b, 0xa8, 0x9d, 0x7d, 0xb5, 0xf2, 0xbd, 0xef, 0x13,
-       0x8d, 0xa5, 0x79, 0xbd, 0xa3, 0x0d, 0xef, 0xb6, 0x24, 0x3f, 0xc1, 0x9a,
-       0xcb, 0x21, 0x51, 0x73, 0xb9, 0xb3, 0xcd, 0x5b, 0x73, 0x51, 0x57, 0xb8,
-       0xdb, 0x72, 0xa8, 0x41, 0xcd, 0xc5, 0xef, 0xb9, 0xdb, 0xe2, 0xf7, 0xdc,
-       0x6d, 0x39, 0x24, 0xeb, 0x2b, 0xea, 0x2f, 0xd1, 0xdd, 0x96, 0xe4, 0x8a,
-       0x77, 0x5b, 0xb6, 0x4a, 0x7d, 0xf5, 0xc2, 0xaf, 0xfe, 0xbc, 0x32, 0x55,
-       0x67, 0xe7, 0x13, 0xc2, 0xce, 0xdf, 0xd5, 0xea, 0xb7, 0x9e, 0x69, 0xbb,
-       0x9e, 0x9d, 0xdf, 0x57, 0xd1, 0x53, 0xbe, 0xa3, 0xcd, 0x77, 0xbe, 0x58,
-       0x16, 0xf9, 0x7c, 0xa6, 0x89, 0x72, 0x03, 0xbf, 0x2a, 0x68, 0xf6, 0x58,
-       0x6f, 0xed, 0x99, 0x63, 0xf5, 0x5e, 0xa4, 0xee, 0xb9, 0x17, 0x69, 0xa2,
-       0x5f, 0xaf, 0xab, 0x87, 0x04, 0xe4, 0xdd, 0x7e, 0xf8, 0xc2, 0x19, 0x43,
-       0xda, 0x5e, 0xc4, 0x70, 0x98, 0xae, 0x50, 0xe4, 0x3b, 0x95, 0x6d, 0xe4,
-       0x9b, 0x71, 0xce, 0x4b, 0x54, 0x11, 0x63, 0x42, 0x8e, 0x8b, 0x7e, 0xe1,
-       0x6f, 0xd4, 0xb8, 0x23, 0xb3, 0xe3, 0xf6, 0x05, 0xe0, 0xbf, 0x21, 0x51,
-       0x6d, 0x9b, 0x95, 0x5a, 0xce, 0x58, 0xe5, 0x0e, 0xbf, 0x09, 0xfb, 0xe0,
-       0xdc, 0x07, 0xca, 0x98, 0x7c, 0x67, 0xe4, 0x62, 0x5b, 0xf5, 0x3e, 0xd0,
-       0x67, 0xa4, 0x9c, 0x3a, 0xf7, 0x81, 0x48, 0x4d, 0x40, 0x3e, 0x6e, 0xe4,
-       0x3e, 0x50, 0xd7, 0x92, 0xfb, 0x40, 0x2b, 0xf3, 0x66, 0xe9, 0x7d, 0xa0,
-       0xc6, 0xfc, 0xe1, 0xfb, 0x40, 0xff, 0xde, 0xe6, 0xdc, 0x43, 0x5d, 0x89,
-       0x3f, 0x6e, 0x9c, 0xf4, 0x11, 0xe0, 0xf9, 0x3e, 0x50, 0xe5, 0x1e, 0x90,
-       0xe7, 0x0e, 0x10, 0xdf, 0x25, 0x59, 0xee, 0x0c, 0xce, 0x7b, 0xff, 0xa4,
-       0xa7, 0x72, 0xff, 0xe4, 0x7c, 0xc9, 0xf5, 0xed, 0xee, 0xb9, 0x1c, 0xc7,
-       0x39, 0xbb, 0x44, 0x8e, 0x7a, 0xae, 0x54, 0x5b, 0xc3, 0x60, 0xbe, 0x8f,
-       0x16, 0xcf, 0x81, 0x3e, 0x6f, 0x89, 0xdc, 0x00, 0x7c, 0xde, 0xe2, 0x23,
-       0xe6, 0x1d, 0x29, 0xa0, 0x8b, 0x38, 0xcb, 0x75, 0xf8, 0xdd, 0x21, 0x64,
-       0xc1, 0x91, 0x8b, 0xdd, 0x9e, 0xf3, 0xd0, 0xaa, 0x1c, 0x38, 0x67, 0xba,
-       0x0e, 0xef, 0x6a, 0x65, 0x46, 0x9c, 0xdd, 0x0c, 0xed, 0xb5, 0x9c, 0xf3,
-       0xc6, 0xa8, 0x38, 0xb7, 0x6d, 0xaf, 0xb3, 0x5b, 0x3a, 0xe4, 0x06, 0x31,
-       0x67, 0x8c, 0xeb, 0xd5, 0x8c, 0xfb, 0x66, 0xc1, 0xe3, 0x46, 0x67, 0x71,
-       0x2b, 0xd7, 0xf1, 0xdc, 0x9a, 0x0a, 0x21, 0x97, 0xd8, 0x9d, 0xce, 0x09,
-       0xbb, 0xe9, 0xac, 0xdd, 0x29, 0xd6, 0xde, 0x58, 0x77, 0x96, 0xcd, 0x72,
-       0xb5, 0x5c, 0x4c, 0x70, 0x3d, 0x9a, 0xde, 0xb3, 0x84, 0xa6, 0xb5, 0xba,
-       0x84, 0xdc, 0xb5, 0x62, 0xe3, 0x3b, 0x2a, 0xba, 0x34, 0x2e, 0xee, 0x21,
-       0xbb, 0xe7, 0xb5, 0x0e, 0xfd, 0xaa, 0xba, 0xb7, 0x5c, 0x3c, 0x53, 0x4f,
-       0xbf, 0x4d, 0xff, 0x4b, 0xe8, 0x77, 0x15, 0xf4, 0xe3, 0x77, 0x03, 0xef,
-       0xef, 0x8a, 0x7a, 0xc0, 0xb9, 0x52, 0xe4, 0x78, 0x9e, 0x38, 0x4e, 0x88,
-       0xcc, 0x2e, 0x50, 0x0f, 0xe8, 0xc8, 0xff, 0xeb, 0xe2, 0xde, 0x9d, 0x60,
-       0xfa, 0xb2, 0x7d, 0x8f, 0xbc, 0x70, 0x99, 0xd8, 0xc6, 0xdf, 0x8d, 0x7d,
-       0x94, 0xcb, 0x2f, 0xc5, 0x5c, 0xfa, 0xb3, 0xee, 0x73, 0x9d, 0xaa, 0x76,
-       0x5f, 0x7b, 0x57, 0xed, 0x53, 0x1d, 0xf9, 0xcc, 0x34, 0x90, 0xcf, 0x8c,
-       0xdc, 0xa3, 0x6f, 0xa6, 0x71, 0xbc, 0x9a, 0x9a, 0xfc, 0xef, 0x5e, 0xae,
-       0x26, 0xb6, 0x8d, 0x22, 0x0a, 0xbf, 0xac, 0xd7, 0x4e, 0xe3, 0xa4, 0x61,
-       0x93, 0x3a, 0xad, 0x69, 0xd2, 0x60, 0xc7, 0x4b, 0x12, 0x29, 0xa5, 0xa4,
-       0x52, 0x55, 0x45, 0x60, 0xa9, 0x21, 0x4e, 0xda, 0x0a, 0x71, 0x70, 0x0b,
-       0x48, 0x51, 0xc5, 0x21, 0x4d, 0xd3, 0x7b, 0x85, 0x84, 0x54, 0xa1, 0x8a,
-       0x46, 0x4e, 0x02, 0x15, 0x4a, 0xe5, 0x0a, 0x96, 0x72, 0x41, 0xa2, 0xd8,
-       0x8e, 0x02, 0x52, 0x2a, 0xf7, 0xca, 0x85, 0xba, 0xbf, 0x08, 0x89, 0x03,
-       0x70, 0x06, 0x29, 0x2a, 0x3f, 0xe2, 0xc0, 0x8d, 0x1b, 0x54, 0x5d, 0xde,
-       0x37, 0xb3, 0x63, 0xaf, 0x77, 0xd7, 0x8e, 0x03, 0x11, 0x07, 0x27, 0xbb,
-       0xf6, 0xcc, 0xce, 0xec, 0xcc, 0x37, 0x6f, 0xbe, 0xf7, 0x37, 0xfd, 0xbe,
-       0x78, 0x8d, 0x5a, 0xdb, 0x5b, 0xf3, 0x55, 0xec, 0xe7, 0xaf, 0x37, 0x18,
-       0x57, 0xed, 0xba, 0xe4, 0xa9, 0xf5, 0xe3, 0x9a, 0x72, 0xd9, 0x1b, 0xf0,
-       0xfe, 0xc7, 0x68, 0x51, 0xd8, 0x86, 0x94, 0xad, 0xee, 0xc5, 0x40, 0x9b,
-       0xd9, 0xff, 0x33, 0x16, 0x03, 0x3e, 0x9b, 0x68, 0xad, 0x6d, 0x8a, 0xed,
-       0x71, 0xd9, 0x16, 0xde, 0xda, 0xc2, 0xb6, 0x10, 0x3c, 0x16, 0xfd, 0x9e,
-       0xb1, 0xa8, 0xc9, 0xea, 0xa1, 0x16, 0xed, 0x74, 0x88, 0x21, 0xbf, 0x9d,
-       0x67, 0x6c, 0x05, 0xca, 0xce, 0x4f, 0x5d, 0x36, 0x3c, 0xe0, 0x73, 0xdc,
-       0x59, 0xeb, 0xc0, 0x27, 0xb5, 0x9d, 0x1a, 0x51, 0xed, 0x01, 0x8f, 0xc9,
-       0xc5, 0x45, 0x82, 0xbe, 0x86, 0x36, 0xe3, 0x82, 0xe3, 0xfa, 0x39, 0x14,
-       0x8f, 0xf1, 0xfa, 0x1b, 0x88, 0xe5, 0x70, 0xda, 0x3f, 0xd9, 0x76, 0xae,
-       0x9c, 0xe5, 0xbd, 0x42, 0xd4, 0x63, 0xbd, 0xef, 0x52, 0xdb, 0x82, 0xa8,
-       0x27, 0xe3, 0x20, 0x1c, 0x1d, 0xd0, 0xe1, 0xe2, 0x8d, 0x74, 0x3f, 0xff,
-       0x9e, 0x13, 0xcc, 0xdd, 0x7f, 0xdd, 0x1d, 0x36, 0x3f, 0x34, 0x64, 0xae,
-       0xde, 0x56, 0xdc, 0x5d, 0xd9, 0x89, 0x06, 0x85, 0xaf, 0xc1, 0xad, 0x7b,
-       0x41, 0x76, 0x5d, 0xe0, 0x3d, 0x7c, 0xa8, 0xba, 0x7f, 0xef, 0x84, 0x7d,
-       0xe8, 0x99, 0x16, 0x62, 0x1d, 0x44, 0x8e, 0xe5, 0x2b, 0x53, 0xc8, 0x45,
-       0xaa, 0xe6, 0xef, 0x78, 0xf3, 0x3c, 0x20, 0x3f, 0x55, 0x9e, 0x87, 0xca,
-       0x23, 0xc5, 0x7b, 0x24, 0x02, 0xf2, 0x3c, 0xdc, 0x32, 0x18, 0xf5, 0xea,
-       0xdf, 0xc3, 0x2d, 0x7f, 0x57, 0x1c, 0xf9, 0x5b, 0xf0, 0xd8, 0xe3, 0x97,
-       0xf3, 0x6a, 0x2d, 0x20, 0xe7, 0x43, 0xf1, 0x94, 0xde, 0x00, 0x9e, 0x12,
-       0x9c, 0xeb, 0xa1, 0xa5, 0x2f, 0xf2, 0x5e, 0x7e, 0x08, 0x7b, 0xb9, 0x51,
-       0x8b, 0xe9, 0x95, 0x72, 0xf0, 0xdc, 0x3a, 0x64, 0xa2, 0xca, 0xb9, 0x81,
-       0x5c, 0x44, 0x2c, 0x3c, 0xe6, 0xba, 0xe4, 0x60, 0x11, 0xbf, 0xa9, 0x58,
-       0x52, 0xa5, 0x47, 0xbd, 0x23, 0xf2, 0x0c, 0xbe, 0x1b, 0x3f, 0xcc, 0x1c,
-       0x18, 0xf2, 0x13, 0x76, 0xa6, 0x43, 0x0e, 0x1f, 0xbe, 0xcc, 0xbf, 0x8d,
-       0x39, 0xd7, 0x92, 0x8b, 0xca, 0x6b, 0xa5, 0x4b, 0xfd, 0xd0, 0x41, 0xe6,
-       0x6f, 0x0e, 0x2f, 0xad, 0xb3, 0x41, 0xc4, 0x53, 0xda, 0xdb, 0x74, 0xa1,
-       0xd8, 0x0c, 0x83, 0xf5, 0xf8, 0x4b, 0x79, 0x38, 0x4f, 0x42, 0x70, 0x9e,
-       0x9f, 0x3a, 0xc2, 0xe6, 0x44, 0x4f, 0xb3, 0x38, 0x9c, 0x53, 0x55, 0xfc,
-       0xa9, 0x72, 0xaa, 0x6f, 0x8f, 0x3a, 0x10, 0xa7, 0xe6, 0xc7, 0x04, 0xe6,
-       0x1f, 0xfa, 0x9c, 0x5a, 0x87, 0xd0, 0xeb, 0x10, 0xf3, 0x87, 0x76, 0x8d,
-       0x06, 0x6b, 0xb0, 0x66, 0x13, 0x2f, 0x50, 0x2b, 0xb1, 0x7f, 0xc9, 0xd1,
-       0x0a, 0x9d, 0xed, 0x69, 0xa6, 0xf3, 0x9e, 0x08, 0xd4, 0x79, 0x83, 0x72,
-       0xa4, 0xcc, 0x80, 0x1c, 0x29, 0x37, 0x0e, 0x75, 0x17, 0x0e, 0xe3, 0x2e,
-       0x2e, 0x30, 0xc0, 0xdc, 0xb9, 0x8b, 0xf1, 0x04, 0xee, 0x1c, 0xa5, 0xd0,
-       0x07, 0x6e, 0xee, 0xec, 0xf7, 0x13, 0x49, 0x5c, 0xfe, 0xdb, 0xdc, 0xa9,
-       0xa0, 0x7e, 0x27, 0x7c, 0xfd, 0x86, 0x1c, 0x9f, 0x6c, 0xc8, 0x13, 0x82,
-       0x38, 0xfe, 0x4e, 0xf7, 0xd3, 0xbb, 0xf6, 0xd1, 0xa6, 0x09, 0xfd, 0x70,
-       0x74, 0xb1, 0xba, 0xee, 0x5f, 0xf0, 0xd9, 0xb9, 0xc1, 0x67, 0x43, 0xc2,
-       0x27, 0xd7, 0x25, 0xf6, 0x90, 0x9d, 0x93, 0x61, 0x9d, 0x1e, 0x19, 0x66,
-       0xf7, 0xd4, 0xec, 0xfc, 0x88, 0x21, 0xec, 0x73, 0x74, 0x0e, 0xb9, 0xef,
-       0x14, 0x1a, 0xc6, 0xa5, 0xe2, 0x3b, 0xe9, 0x1b, 0x38, 0x77, 0x04, 0xb2,
-       0x1b, 0xf2, 0xfc, 0xf4, 0x6c, 0xd8, 0x34, 0x1c, 0x1f, 0x03, 0xfc, 0x08,
-       0xc0, 0xa9, 0x7a, 0x7e, 0x90, 0x0d, 0x3d, 0x68, 0x0e, 0x87, 0x7c, 0x73,
-       0x28, 0xf1, 0x06, 0x6e, 0x8f, 0x58, 0xbc, 0x83, 0x9e, 0x38, 0xc5, 0x9d,
-       0x18, 0x93, 0xee, 0x80, 0x78, 0x41, 0xc4, 0xfa, 0xf9, 0xfa, 0xcb, 0xef,
-       0x7c, 0x51, 0xf3, 0xaf, 0xad, 0x49, 0x6d, 0xba, 0x3c, 0xad, 0x4d, 0x15,
-       0x51, 0xee, 0xa2, 0x56, 0xdb, 0x97, 0x36, 0x5d, 0x1c, 0x11, 0x7c, 0x30,
-       0x79, 0xad, 0x42, 0x78, 0x4f, 0xdb, 0xbe, 0x25, 0xb8, 0xed, 0x80, 0x0f,
-       0xab, 0x8a, 0x73, 0x18, 0x2d, 0xbc, 0x97, 0xb4, 0xbd, 0xb8, 0xb9, 0x8e,
-       0x5b, 0xbe, 0x3f, 0x1d, 0x20, 0xdf, 0x9b, 0xd9, 0x0a, 0x91, 0xbf, 0x29,
-       0xe2, 0xb2, 0xa9, 0x68, 0x21, 0xde, 0xf1, 0x30, 0xe2, 0x7b, 0xe1, 0xd7,
-       0xa8, 0x62, 0xe1, 0x6e, 0x30, 0x16, 0xaa, 0xf6, 0x60, 0x1d, 0xb9, 0xa3,
-       0x2c, 0x8b, 0xc3, 0xe9, 0x5e, 0x0a, 0x99, 0x28, 0xff, 0x6c, 0xe2, 0x3e,
-       0x1d, 0x73, 0x78, 0x09, 0xfc, 0x3c, 0xb2, 0xde, 0x4c, 0x0b, 0x76, 0xe1,
-       0x60, 0x7f, 0x46, 0x84, 0x65, 0xf3, 0x67, 0xbd, 0xad, 0xf9, 0x33, 0x54,
-       0x39, 0xd4, 0xed, 0xa2, 0x35, 0x0b, 0x71, 0x92, 0xf0, 0x2f, 0x75, 0x77,
-       0xb4, 0x9b, 0x41, 0xf2, 0x4f, 0xc5, 0x7e, 0x82, 0x1f, 0xc9, 0xb9, 0xba,
-       0x41, 0x98, 0x3b, 0x9b, 0xbe, 0x6f, 0x30, 0x57, 0xdb, 0xb1, 0x29, 0x37,
-       0x9f, 0x2b, 0xc3, 0x33, 0x57, 0xd8, 0x8b, 0x9a, 0xcd, 0x95, 0xf2, 0x43,
-       0x2a, 0xdf, 0xdc, 0x51, 0xc8, 0x93, 0x45, 0xf7, 0x5c, 0xed, 0x8c, 0x7f,
-       0x4e, 0xce, 0xd9, 0x4e, 0xfb, 0xe0, 0x1a, 0x8f, 0x43, 0x34, 0xd0, 0x76,
-       0x12, 0x2c, 0x33, 0xfc, 0x6b, 0xeb, 0x86, 0x5c, 0x5b, 0xcc, 0x2b, 0x9e,
-       0x6f, 0xb8, 0xb6, 0xb0, 0x0f, 0x5c, 0x70, 0xf6, 0x81, 0xd3, 0x3e, 0x7d,
-       0x51, 0xd9, 0xbc, 0xff, 0xab, 0xed, 0x0d, 0xcf, 0x7d, 0x22, 0xce, 0xe9,
-       0xc8, 0x91, 0xdc, 0x47, 0xce, 0x37, 0xe4, 0x61, 0x3d, 0xdb, 0x5c, 0xa7,
-       0x6a, 0xee, 0x91, 0x73, 0x01, 0x79, 0x99, 0xa5, 0xf3, 0xf9, 0xc7, 0x06,
-       0x75, 0xf7, 0x53, 0xa4, 0x1a, 0xd3, 0x72, 0x40, 0xf0, 0x61, 0xb7, 0xbe,
-       0xbc, 0xec, 0xe4, 0x28, 0xe6, 0x5c, 0x63, 0xb0, 0x9c, 0xcf, 0x36, 0x89,
-       0xa7, 0x6f, 0x25, 0x9e, 0x63, 0xc0, 0x23, 0x37, 0xbd, 0x73, 0x35, 0xa1,
-       0x65, 0xf2, 0xa8, 0xb3, 0x87, 0xce, 0xea, 0x9f, 0xf0, 0x18, 0x3d, 0xb1,
-       0x23, 0xe2, 0x9c, 0x11, 0xe0, 0xd2, 0xb6, 0x97, 0xcd, 0x0e, 0x5a, 0x94,
-       0x7e, 0x46, 0x9a, 0xfa, 0xf8, 0x12, 0x15, 0x85, 0x7f, 0x0b, 0xb9, 0x51,
-       0xb0, 0x71, 0xc3, 0x47, 0x87, 0xe7, 0xf0, 0xf7, 0x1b, 0x13, 0x8e, 0xcc,
-       0xfd, 0x93, 0x31, 0x8c, 0x7a, 0x38, 0x0b, 0x01, 0xeb, 0x9d, 0x34, 0xc9,
-       0x31, 0xb9, 0x1d, 0x71, 0x4e, 0x80, 0x8c, 0xcd, 0xbb, 0x5d, 0xde, 0x8e,
-       0x4f, 0xa1, 0x55, 0xbd, 0xe4, 0xeb, 0x68, 0xd8, 0xfc, 0x72, 0xcf, 0xf6,
-       0x7d, 0x0a, 0x2a, 0x77, 0x5f, 0x71, 0x58, 0x75, 0x2d, 0x73, 0x69, 0xc1,
-       0x99, 0xe7, 0xd7, 0x55, 0xde, 0x6d, 0x77, 0x40, 0xde, 0x6d, 0x88, 0xe6,
-       0x84, 0xaf, 0x2e, 0x44, 0x39, 0x47, 0x37, 0x93, 0x9c, 0x5a, 0xd9, 0x6a,
-       0x23, 0x4e, 0xfc, 0x29, 0xee, 0xdd, 0x39, 0xf9, 0x7c, 0x5f, 0x04, 0xcf,
-       0x46, 0x4e, 0xb5, 0x2d, 0x62, 0xf1, 0x33, 0xa2, 0x5c, 0xa7, 0xa7, 0x1c,
-       0xdf, 0x17, 0xd5, 0x33, 0x3b, 0xb9, 0x7c, 0x8a, 0x64, 0x0e, 0x7d, 0x27,
-       0xcd, 0x15, 0x9b, 0xf5, 0x6b, 0x1f, 0xe2, 0x81, 0xe3, 0xf0, 0x95, 0x0a,
-       0xbf, 0x95, 0xa1, 0xfa, 0x80, 0x3e, 0xb5, 0x57, 0xfb, 0x04, 0xf9, 0x14,
-       0x12, 0x7e, 0x05, 0xbe, 0x76, 0xda, 0x99, 0x23, 0x77, 0xbf, 0xc2, 0xdc,
-       0x2f, 0x3c, 0xa7, 0xd3, 0x55, 0xb6, 0xd3, 0x55, 0xb6, 0x36, 0x5e, 0x3a,
-       0xeb, 0x54, 0x0b, 0xe5, 0x1f, 0x59, 0x2f, 0xfd, 0x56, 0xd8, 0xe6, 0xe6,
-       0xb3, 0x06, 0x2d, 0xac, 0xf7, 0xf2, 0x27, 0xc6, 0x1f, 0x94, 0xdb, 0xcb,
-       0xff, 0xdd, 0x9c, 0xa2, 0x5f, 0xc4, 0x02, 0xb6, 0xce, 0x07, 0x83, 0xf1,
-       0x1f, 0xbc, 0x6e, 0x13, 0x01, 0xeb, 0xb6, 0xf9, 0xbe, 0x22, 0xf7, 0x93,
-       0xe4, 0x95, 0x8a, 0x23, 0xaf, 0x36, 0x69, 0xd0, 0x27, 0xa7, 0x82, 0xd6,
-       0x29, 0xfa, 0x78, 0xca, 0xe9, 0xe3, 0x9b, 0xa2, 0x3f, 0xe3, 0x54, 0xa8,
-       0xe6, 0x0d, 0x1f, 0xe1, 0xeb, 0x98, 0xb2, 0xd1, 0x35, 0x90, 0xab, 0xdf,
-       0x6c, 0x43, 0xc6, 0x04, 0x71, 0xb2, 0x03, 0x01, 0xfa, 0x80, 0xee, 0xd2,
-       0x07, 0xe2, 0x55, 0x7d, 0x60, 0x45, 0xe8, 0x09, 0xbb, 0x1c, 0x1d, 0x34,
-       0xd8, 0x16, 0x97, 0xcb, 0xe3, 0xcc, 0x1b, 0xd8, 0xf8, 0xa4, 0x1d, 0x7d,
-       0xda, 0xaa, 0x9e, 0x99, 0xc3, 0xba, 0x65, 0x8d, 0x4b, 0xfb, 0xe5, 0x09,
-       0xce, 0xac, 0xa8, 0xcc, 0x3e, 0x30, 0xa3, 0xa4, 0xa5, 0x93, 0xf1, 0xa9,
-       0x50, 0x84, 0x16, 0xac, 0x28, 0x15, 0xac, 0x14, 0x73, 0x70, 0xf0, 0xe3,
-       0xd0, 0x80, 0x46, 0x11, 0x96, 0x35, 0x11, 0x2a, 0x95, 0x94, 0x4e, 0x76,
-       0x86, 0xc8, 0x2c, 0xc6, 0xa4, 0x0d, 0x9b, 0x71, 0x9a, 0x1f, 0x33, 0xe6,
-       0x49, 0x43, 0xcc, 0x8b, 0x93, 0xa3, 0x0e, 0x0c, 0x8a, 0x38, 0x4b, 0xfd,
-       0xe5, 0x91, 0x28, 0xb5, 0xa7, 0xa5, 0xcd, 0x68, 0x86, 0xdb, 0xf8, 0xc2,
-       0x8a, 0xd1, 0x95, 0x7c, 0xd2, 0x38, 0xc1, 0xed, 0x64, 0xac, 0x64, 0x62,
-       0x92, 0x9f, 0x5d, 0x2c, 0x45, 0x28, 0x67, 0x45, 0xa8, 0x50, 0x4a, 0x19,
-       0x43, 0x6d, 0xa2, 0xcd, 0x18, 0xda, 0x7c, 0x49, 0x1f, 0x33, 0x4e, 0x92,
-       0xbb, 0xcd, 0xaf, 0x9c, 0x36, 0xbd, 0x6d, 0xfd, 0x61, 0xe3, 0xfe, 0x44,
-       0xa8, 0x32, 0x7b, 0x9f, 0xf1, 0x92, 0x5b, 0x9d, 0x60, 0xd9, 0x14, 0x13,
-       0x67, 0xdb, 0x68, 0xe9, 0x34, 0xcb, 0x1d, 0x9c, 0x6d, 0x61, 0xd0, 0x62,
-       0x39, 0x4e, 0xef, 0x57, 0xed, 0x07, 0x12, 0x43, 0x39, 0x91, 0x43, 0x84,
-       0x33, 0x17, 0x2a, 0xb3, 0xbf, 0x9b, 0x5e, 0x7f, 0x3f, 0xeb, 0x5b, 0x1f,
-       0xc5, 0x28, 0x72, 0x15, 0x71, 0xdd, 0x36, 0x5d, 0x1b, 0x4f, 0x5e, 0xd9,
-       0x14, 0x79, 0x68, 0x09, 0x5a, 0x33, 0xa5, 0x3c, 0xcd, 0x71, 0xf9, 0x15,
-       0x94, 0x5b, 0x4b, 0xd0, 0x3d, 0x91, 0x8f, 0xd6, 0x4e, 0x77, 0xf4, 0x18,
-       0x85, 0x6e, 0x9a, 0xc6, 0xbc, 0xf0, 0x0b, 0x57, 0x66, 0x87, 0x86, 0x0d,
-       0xd2, 0xae, 0xa2, 0x1e, 0xff, 0xbf, 0x89, 0xfb, 0x28, 0x61, 0x7e, 0x66,
-       0xac, 0x31, 0x5e, 0x49, 0xc3, 0xf1, 0x12, 0x64, 0xf3, 0x41, 0x89, 0xa5,
-       0x39, 0x23, 0x42, 0xd0, 0x5f, 0x61, 0x7b, 0xeb, 0x35, 0x27, 0x7b, 0xa4,
-       0xfe, 0xe4, 0x3b, 0x9b, 0x43, 0x9f, 0x19, 0x71, 0x9f, 0xcf, 0x51, 0x7b,
-       0x66, 0xc6, 0x92, 0xef, 0xb9, 0x52, 0xee, 0xa5, 0x25, 0x6e, 0x7b, 0x64,
-       0xf8, 0x8c, 0x73, 0xa6, 0x0f, 0xff, 0xd9, 0x8b, 0x7b, 0x85, 0xb7, 0x7d,
-       0x7d, 0x14, 0xc5, 0x3d, 0x0d, 0xe8, 0x3c, 0xc7, 0xb0, 0xe9, 0x87, 0xc5,
-       0xb8, 0xa7, 0xe2, 0x98, 0xcb, 0xb9, 0xb8, 0x3a, 0x97, 0x08, 0x65, 0xba,
-       0xe9, 0x91, 0xd5, 0x45, 0x3f, 0x8b, 0xf3, 0x47, 0xf8, 0xba, 0x84, 0x9c,
-       0xa3, 0x36, 0xca, 0x64, 0xbb, 0x69, 0xb3, 0x14, 0x66, 0x71, 0x05, 0xec,
-       0x44, 0xb9, 0x4c, 0x81, 0xa6, 0xd6, 0x5f, 0xeb, 0x83, 0x1f, 0x66, 0x52,
-       0xab, 0x61, 0xe9, 0x51, 0x00, 0x96, 0x7e, 0xa9, 0xc3, 0xd2, 0xd1, 0xbe,
-       0xe6, 0x58, 0xea, 0x77, 0x62, 0xd6, 0xa3, 0x14, 0x71, 0x70, 0xf4, 0x39,
-       0xe3, 0xe8, 0x3d, 0xc6, 0xd1, 0xf1, 0x06, 0x38, 0xd2, 0x3c, 0x38, 0x3a,
-       0x51, 0x87, 0xa3, 0x6c, 0x5f, 0x33, 0x1c, 0x1d, 0x0f, 0xa1, 0xff, 0xcd,
-       0xd6, 0x32, 0xfa, 0xb0, 0x9f, 0x39, 0xbd, 0x49, 0xa5, 0xd5, 0xe4, 0xf8,
-       0x24, 0x55, 0x90, 0x73, 0x92, 0x58, 0xa2, 0xb4, 0xe0, 0x76, 0x05, 0x81,
-       0xbf, 0x2c, 0x8f, 0xc9, 0xae, 0x06, 0xe7, 0xaa, 0x24, 0x9c, 0x79, 0x93,
-       0x73, 0x99, 0xc9, 0x57, 0x66, 0x1f, 0x32, 0x36, 0xee, 0x6d, 0xe8, 0x3a,
-       0x7e, 0x0b, 0xb1, 0x8c, 0xbc, 0xbb, 0x81, 0x73, 0x5b, 0xe2, 0x74, 0xdf,
-       0x1a, 0xa0, 0x7b, 0xd6, 0x7e, 0xba, 0x6b, 0x0d, 0xd2, 0x03, 0x0b, 0x6d,
-       0x60, 0x0e, 0xf8, 0x5e, 0xcc, 0x81, 0x46, 0x33, 0x31, 0x2e, 0x53, 0xda,
-       0x4f, 0x95, 0x92, 0xc2, 0x35, 0xb0, 0x03, 0x0c, 0x35, 0xc6, 0x4e, 0xa6,
-       0x0e, 0x3b, 0xb2, 0x0e, 0x30, 0xb3, 0xe4, 0xb7, 0xad, 0xed, 0x32, 0xf8,
-       0x5d, 0x0d, 0xc6, 0x56, 0x58, 0xc4, 0x91, 0x24, 0x47, 0x67, 0x42, 0x90,
-       0x59, 0xb7, 0x18, 0x53, 0x3c, 0x17, 0x3c, 0x7e, 0xda, 0xf5, 0x41, 0x96,
-       0x39, 0x4f, 0x09, 0x1b, 0xf4, 0x94, 0xa9, 0xc7, 0x33, 0x64, 0x5f, 0xd6,
-       0xcc, 0x31, 0x91, 0xeb, 0xb6, 0x54, 0xf6, 0x9e, 0x31, 0x91, 0xe1, 0xb1,
-       0x57, 0x78, 0xf4, 0xca, 0xa1, 0x76, 0xaa, 0x38, 0x31, 0x4c, 0x85, 0x55,
-       0xdb, 0x7e, 0xc8, 0xfc, 0x7f, 0xcd, 0x84, 0xcc, 0xfe, 0xdb, 0xae, 0xc4,
-       0x74, 0x5a, 0x36, 0x55, 0xdf, 0xee, 0x08, 0x7c, 0x31, 0x47, 0xa4, 0x77,
-       0x37, 0xaa, 0xaf, 0xc4, 0xbf, 0xe3, 0xbb, 0xbf, 0x04, 0x97, 0x59, 0xab,
-       0x96, 0x85, 0xed, 0xf8, 0xd2, 0xd8, 0xc2, 0x2a, 0xce, 0x7e, 0x7b, 0xfc,
-       0xea, 0xf9, 0xd5, 0x5c, 0x1f, 0x4b, 0xd8, 0x94, 0x4e, 0x76, 0x68, 0x79,
-       0x3c, 0xf7, 0x5c, 0x98, 0x86, 0x19, 0x97, 0x38, 0x83, 0x6b, 0x6c, 0x34,
-       0x2c, 0xce, 0x38, 0xd9, 0xcd, 0x78, 0xc8, 0x0a, 0x3b, 0xfd, 0xd4, 0x91,
-       0x09, 0x9a, 0x2c, 0xa7, 0xf9, 0x53, 0x3f, 0x7e, 0xb5, 0xb9, 0xe3, 0xe1,
-       0x48, 0xe3, 0x37, 0x37, 0xff, 0xa8, 0xd5, 0x9d, 0xe6, 0xba, 0x33, 0x5b,
-       0xd6, 0x55, 0xe7, 0x12, 0xfd, 0x03, 0x69, 0xae, 0x1b, 0xa3, 0xbc, 0x57,
-       0x00, 0x00, 0x00 };
+       0x1f, 0x8b, 0x08, 0x00, 0x45, 0x30, 0xe7, 0x45, 0x00, 0x03, 0xdc, 0x5a,
+       0x6b, 0x6c, 0x1c, 0xd7, 0x75, 0x3e, 0x33, 0x3b, 0x4b, 0xae, 0xc8, 0x15,
+       0x35, 0xa2, 0xc6, 0xf4, 0x5a, 0xa2, 0xed, 0x5d, 0x72, 0x28, 0x12, 0x96,
+       0xec, 0x6e, 0x68, 0xda, 0x62, 0x8c, 0x8d, 0xb4, 0xd9, 0xa5, 0x0c, 0xa1,
+       0x65, 0x6b, 0x4a, 0xa2, 0x6d, 0x05, 0x11, 0x02, 0x62, 0x49, 0xa9, 0x46,
+       0x50, 0xb7, 0x92, 0xab, 0xb6, 0x81, 0x6b, 0x4b, 0x6b, 0x92, 0x6a, 0x09,
+       0x84, 0xe6, 0x08, 0x11, 0x43, 0x19, 0xa9, 0x11, 0x10, 0xa4, 0x1c, 0xbb,
+       0xc0, 0xb6, 0x2b, 0xbf, 0x05, 0x34, 0x2e, 0x15, 0x4a, 0x6e, 0xd4, 0x34,
+       0x30, 0xfc, 0xa7, 0xa8, 0x51, 0x38, 0xad, 0xe1, 0x04, 0xa8, 0x9b, 0x16,
+       0x45, 0xd0, 0xfc, 0x88, 0x0a, 0xdb, 0xd9, 0x7e, 0xdf, 0x9d, 0x3b, 0xcb,
+       0xe1, 0x92, 0xd4, 0xc3, 0x8f, 0xfe, 0x28, 0x81, 0xe5, 0xcc, 0xbd, 0x73,
+       0xe7, 0xde, 0x73, 0xcf, 0xe3, 0x3b, 0x8f, 0xb9, 0x77, 0x8a, 0x34, 0x88,
+       0xfe, 0x5b, 0x8f, 0x5f, 0xf2, 0xd1, 0x3f, 0x18, 0xbe, 0xab, 0xe7, 0xae,
+       0xbb, 0x71, 0x7b, 0xb7, 0x19, 0xb1, 0x22, 0xec, 0xe7, 0x3f, 0x07, 0xbf,
+       0x6e, 0x7d, 0xbf, 0xda, 0x9f, 0x8d, 0xdf, 0x65, 0xfc, 0x86, 0x7e, 0x2e,
+       0x62, 0xac, 0x31, 0x26, 0xfc, 0x57, 0xa9, 0x5c, 0xfd, 0xb9, 0x49, 0x5a,
+       0xae, 0xf2, 0x3c, 0xe2, 0x2f, 0xa9, 0x68, 0xe6, 0x4f, 0x62, 0x66, 0x46,
+       0x8e, 0xe7, 0x5c, 0x89, 0x45, 0x32, 0x1f, 0x1c, 0x1f, 0x76, 0x45, 0xb2,
+       0xa5, 0x6d, 0xc9, 0xbc, 0x7c, 0x5c, 0x29, 0x3a, 0x96, 0xb0, 0xff, 0xd6,
+       0xcc, 0x47, 0x27, 0xde, 0xd8, 0x91, 0xfa, 0xc5, 0x6c, 0x44, 0x62, 0x76,
+       0xe6, 0x15, 0xb1, 0xb7, 0x4a, 0xac, 0x15, 0xef, 0x3c, 0xdb, 0x99, 0x33,
+       0xa4, 0x29, 0x98, 0xeb, 0x83, 0xca, 0x1b, 0x9d, 0x52, 0xdc, 0x9c, 0x89,
+       0x89, 0x99, 0xe9, 0x78, 0x27, 0x17, 0xb1, 0x87, 0x22, 0x19, 0x5b, 0x16,
+       0xca, 0x32, 0x30, 0x32, 0x29, 0xb1, 0x58, 0x66, 0x22, 0x56, 0xdf, 0x21,
+       0xb1, 0x68, 0x66, 0xe8, 0xf8, 0xf7, 0xdc, 0x13, 0x15, 0xd3, 0x75, 0x93,
+       0xa3, 0x12, 0xef, 0x1d, 0xef, 0xc1, 0xf3, 0x52, 0x0a, 0x04, 0xef, 0x10,
+       0xd3, 0x2d, 0xc6, 0x23, 0x6e, 0x4c, 0x72, 0x65, 0x57, 0xf2, 0x65, 0x91,
+       0x1f, 0x96, 0x0c, 0x19, 0x77, 0x5b, 0x64, 0x74, 0xfb, 0x47, 0x95, 0x2c,
+       0x68, 0xf9, 0x3b, 0x77, 0xe8, 0xf8, 0x73, 0x2e, 0xe9, 0x9d, 0x8e, 0xf9,
+       0xf4, 0x8e, 0xd7, 0x0f, 0xbb, 0x96, 0xcc, 0x95, 0xd8, 0x77, 0xd0, 0x64,
+       0x9f, 0x95, 0xf9, 0x7e, 0xc3, 0xb8, 0x1b, 0xd7, 0x7d, 0x13, 0xd9, 0x1c,
+       0xe6, 0x9b, 0x2f, 0x71, 0xec, 0xbb, 0x5f, 0x18, 0x76, 0x1d, 0xdd, 0x9f,
+       0xdd, 0x91, 0x73, 0x13, 0xe8, 0x6f, 0xd5, 0xcf, 0x9e, 0x79, 0x74, 0xd8,
+       0x75, 0xf5, 0x33, 0xcb, 0xca, 0xb9, 0x5d, 0xba, 0xbf, 0xb4, 0x6b, 0xd8,
+       0xdd, 0xae, 0xfb, 0x7f, 0xbc, 0x2b, 0xe7, 0xa6, 0x75, 0x7f, 0xef, 0x57,
+       0x86, 0xdd, 0x1e, 0xdd, 0xff, 0xf6, 0xce, 0x9c, 0xdb, 0xab, 0xfb, 0x4f,
+       0xf5, 0x0e, 0xbb, 0xb6, 0x9c, 0x2d, 0x25, 0xf1, 0x9b, 0x88, 0x59, 0x1d,
+       0x19, 0x3d, 0xe6, 0x59, 0xd0, 0x9b, 0xc5, 0x98, 0x3e, 0xf4, 0xef, 0xc1,
+       0xaf, 0x1f, 0xbf, 0xf2, 0x06, 0x69, 0x1a, 0xc0, 0xf3, 0x0f, 0xb7, 0xf8,
+       0x3c, 0x04, 0xaf, 0xbc, 0x98, 0xbc, 0x17, 0x49, 0xc8, 0x1b, 0x9d, 0xef,
+       0x81, 0x97, 0xb6, 0x9c, 0x2b, 0x8b, 0x31, 0xd0, 0x99, 0x00, 0x0f, 0x1d,
+       0x79, 0xb1, 0xdc, 0x28, 0x91, 0x6f, 0x45, 0xc0, 0xa3, 0xaf, 0x4a, 0xc1,
+       0x89, 0xc9, 0xc6, 0x19, 0x43, 0xda, 0xba, 0xd7, 0x49, 0xd6, 0x2e, 0x4a,
+       0xbe, 0x13, 0x52, 0x9f, 0x72, 0xc4, 0x9a, 0x59, 0xdc, 0x68, 0xa2, 0xc7,
+       0x94, 0x54, 0xa2, 0x80, 0x19, 0x47, 0xce, 0xbe, 0x4b, 0x1d, 0xa5, 0x7c,
+       0xf1, 0x4b, 0x4a, 0x7e, 0xf2, 0x0e, 0x19, 0xb2, 0x49, 0xe7, 0x9f, 0xdd,
+       0xea, 0xaf, 0x19, 0x33, 0x72, 0x67, 0x06, 0xe5, 0xa4, 0x17, 0x37, 0xf2,
+       0x67, 0x76, 0x4a, 0x2e, 0x2d, 0x8e, 0x29, 0x1d, 0xea, 0xdd, 0xf9, 0xd2,
+       0xa0, 0x8c, 0x7b, 0x62, 0xe4, 0x3c, 0x4b, 0x46, 0x4b, 0x2d, 0x78, 0xde,
+       0xa4, 0xc6, 0xa2, 0xaf, 0x35, 0x22, 0x1d, 0x76, 0x5e, 0x62, 0xe8, 0xb7,
+       0xd1, 0xdf, 0x6c, 0xf4, 0xa9, 0x39, 0x54, 0x7f, 0x72, 0x4c, 0xe2, 0xd8,
+       0x9b, 0xa3, 0xc7, 0x56, 0x2a, 0xb9, 0xb4, 0x8d, 0x71, 0x83, 0x32, 0xe6,
+       0x39, 0x32, 0x84, 0xeb, 0xa8, 0xc7, 0xf5, 0x13, 0xd0, 0xb1, 0xb7, 0x8e,
+       0x17, 0xa6, 0xd5, 0x7c, 0xc9, 0x48, 0x86, 0xf3, 0xb5, 0x62, 0xdc, 0x05,
+       0xd0, 0x65, 0x88, 0xa5, 0x64, 0x9b, 0x95, 0xc2, 0xa4, 0x21, 0xe4, 0x5b,
+       0x41, 0xf1, 0xb0, 0x0f, 0xf4, 0x5b, 0xe2, 0x76, 0x1b, 0x32, 0xec, 0xde,
+       0x2c, 0x45, 0x1b, 0xed, 0xd2, 0x79, 0x33, 0xe7, 0xd5, 0x4b, 0xde, 0x4a,
+       0x62, 0xff, 0x94, 0xfd, 0x90, 0x8c, 0xe1, 0x1d, 0xd3, 0xe5, 0x98, 0x8f,
+       0xb0, 0x77, 0xb4, 0xf1, 0x6e, 0x5d, 0xe6, 0xa0, 0x5c, 0x9a, 0x2c, 0x9a,
+       0xb9, 0x72, 0x8b, 0x44, 0x66, 0x52, 0xd0, 0xfe, 0x71, 0x33, 0xff, 0xbc,
+       0x25, 0xd1, 0x29, 0xea, 0x97, 0xd8, 0x91, 0xcc, 0x84, 0xb9, 0xbb, 0x7c,
+       0xde, 0xcc, 0x97, 0xf9, 0x0e, 0xc6, 0x96, 0x4c, 0xf0, 0x96, 0xf7, 0xdb,
+       0xc0, 0x4b, 0xea, 0x36, 0xdf, 0x81, 0x1c, 0xb0, 0x87, 0x17, 0x3d, 0xc8,
+       0x45, 0xc9, 0x29, 0x09, 0x39, 0x89, 0xd1, 0xd7, 0x19, 0x93, 0xb1, 0x69,
+       0x4b, 0x0a, 0xe9, 0x9b, 0x15, 0xe7, 0x0b, 0xe9, 0x25, 0x9a, 0x46, 0x27,
+       0x6b, 0x69, 0xe2, 0x7b, 0xa4, 0xc9, 0xa7, 0x65, 0x6c, 0x9a, 0xb4, 0xf9,
+       0xb4, 0x9c, 0x9c, 0x24, 0x8d, 0x5c, 0x87, 0xf4, 0x90, 0xae, 0x80, 0x26,
+       0xbe, 0x43, 0x9a, 0x36, 0x61, 0x7e, 0x65, 0xc0, 0x46, 0x1f, 0x68, 0x18,
+       0xf3, 0x2c, 0xc8, 0x26, 0x2e, 0x05, 0xbb, 0x68, 0x8c, 0xf5, 0x6e, 0x4b,
+       0xc0, 0xaa, 0x8d, 0xd1, 0x5e, 0xd2, 0xeb, 0x42, 0x7e, 0x75, 0x4a, 0xce,
+       0x66, 0x66, 0x9c, 0x3c, 0xc3, 0x78, 0xae, 0x8d, 0xfb, 0x92, 0x2d, 0xe3,
+       0x6a, 0x3e, 0xd2, 0xf3, 0x59, 0xcc, 0x43, 0x7a, 0x2f, 0x43, 0x57, 0x7b,
+       0xa0, 0xa3, 0x69, 0xf9, 0xdb, 0xf2, 0x76, 0x79, 0xbd, 0xdc, 0x25, 0xaf,
+       0xc1, 0x7e, 0x5f, 0x2d, 0x27, 0xe5, 0x95, 0x72, 0xab, 0xbc, 0x5c, 0x4e,
+       0xc8, 0x4b, 0x4a, 0x7f, 0xfb, 0x44, 0x9a, 0x94, 0x4e, 0xc7, 0x6e, 0x86,
+       0x3e, 0xb6, 0x40, 0x1f, 0x9b, 0x61, 0x4f, 0x1b, 0x61, 0xab, 0xdf, 0x06,
+       0x0f, 0xa7, 0x3b, 0x25, 0xbb, 0x09, 0xfd, 0xb7, 0x65, 0x2c, 0xa5, 0x23,
+       0x16, 0x9e, 0x8f, 0x4d, 0x46, 0x25, 0x6f, 0x9f, 0x95, 0xf7, 0xa7, 0x2c,
+       0x19, 0x2b, 0x3f, 0x79, 0x9b, 0xaf, 0xb3, 0x6c, 0xcf, 0xca, 0x45, 0xf4,
+       0xe5, 0xed, 0x59, 0xb9, 0xb4, 0xd5, 0x94, 0xd1, 0xe9, 0xef, 0x4a, 0xee,
+       0xf9, 0xb3, 0xf2, 0xd3, 0xbf, 0x16, 0x19, 0x00, 0xef, 0xcd, 0xee, 0xff,
+       0xaa, 0x64, 0x6d, 0xec, 0xb1, 0x7b, 0xbb, 0x92, 0x89, 0xd9, 0x4d, 0x3d,
+       0x4e, 0x02, 0x57, 0x2c, 0x23, 0xef, 0xbd, 0x00, 0x6c, 0x69, 0x34, 0x72,
+       0xa7, 0x45, 0x86, 0x4f, 0x57, 0x64, 0x38, 0x1d, 0x95, 0xc7, 0xec, 0x8a,
+       0xf4, 0xa5, 0xeb, 0xe4, 0xa8, 0x4d, 0xac, 0x39, 0x6e, 0x04, 0xb8, 0xfe,
+       0xed, 0xf2, 0x09, 0xdc, 0xb3, 0x4f, 0x64, 0x5a, 0xdd, 0xfb, 0xfd, 0xc5,
+       0x72, 0x54, 0xb2, 0x4e, 0x31, 0x61, 0x49, 0x9b, 0xe9, 0xd3, 0xf4, 0xcd,
+       0xe0, 0x19, 0x78, 0x35, 0x04, 0x2c, 0xf5, 0xed, 0xaf, 0x30, 0xb9, 0xee,
+       0x4a, 0x56, 0x75, 0x47, 0x29, 0x3b, 0xe8, 0x34, 0x79, 0x9d, 0x1c, 0x32,
+       0x32, 0x8e, 0xb4, 0x29, 0xbc, 0xe8, 0xc1, 0x98, 0x5e, 0x63, 0x7f, 0x99,
+       0x7a, 0x8e, 0xfb, 0x12, 0x69, 0xdd, 0x8c, 0xb1, 0x16, 0xae, 0x59, 0x4d,
+       0x73, 0x98, 0x4e, 0xce, 0x45, 0x3a, 0x79, 0x7d, 0x21, 0x44, 0xe7, 0x5f,
+       0x56, 0xef, 0xa7, 0x43, 0xf7, 0xc5, 0xf2, 0x0f, 0x1a, 0x7c, 0xfa, 0xc8,
+       0xcf, 0x5e, 0xe8, 0xe3, 0x37, 0xf4, 0x5a, 0xb8, 0x2f, 0x71, 0x8d, 0xb3,
+       0x15, 0x5f, 0xa7, 0x8a, 0xd7, 0x58, 0xeb, 0x62, 0x68, 0xad, 0x4b, 0xa1,
+       0xb5, 0x2e, 0x85, 0xd6, 0x2a, 0x82, 0xb7, 0xb2, 0xc1, 0x74, 0xa3, 0xc0,
+       0x27, 0xf6, 0x4c, 0x60, 0xce, 0x67, 0x21, 0x97, 0x9f, 0x60, 0x4c, 0x46,
+       0x16, 0x3d, 0xf0, 0xe3, 0x74, 0x54, 0xf6, 0xa9, 0x67, 0xbd, 0x9a, 0xae,
+       0xf0, 0xb3, 0x98, 0xec, 0x75, 0x78, 0x1f, 0x3c, 0xb3, 0xc0, 0x63, 0xb6,
+       0xff, 0xe1, 0x16, 0xbf, 0xcd, 0xfb, 0xf3, 0x9a, 0xfe, 0x87, 0xfc, 0xf7,
+       0xca, 0x1f, 0x28, 0x9c, 0x5c, 0x28, 0x13, 0xc7, 0x24, 0x1d, 0x71, 0xe5,
+       0x48, 0x5f, 0x1a, 0x76, 0x65, 0x1b, 0xe9, 0xd1, 0xae, 0x7a, 0xf2, 0x3c,
+       0x6b, 0xba, 0x8d, 0xc0, 0x0a, 0x49, 0x9a, 0xd0, 0xb3, 0x51, 0xb5, 0x97,
+       0x75, 0xa6, 0x4f, 0xb3, 0xcd, 0xf6, 0x80, 0xe9, 0x36, 0xd7, 0xf4, 0xd3,
+       0xde, 0x1b, 0x71, 0x4f, 0xdd, 0x7e, 0x4c, 0xcb, 0x37, 0x8e, 0x36, 0xf1,
+       0xb9, 0x5f, 0xb7, 0x83, 0xe7, 0x39, 0x6b, 0x79, 0xfb, 0xed, 0x2d, 0xcb,
+       0xdb, 0x01, 0x76, 0x84, 0xb1, 0x9d, 0x7b, 0x4d, 0x4a, 0xc4, 0xa5, 0xce,
+       0x45, 0x41, 0x6b, 0x1a, 0xb6, 0x58, 0xaf, 0x69, 0xb8, 0x5d, 0xd3, 0x00,
+       0x5a, 0x31, 0x6e, 0x54, 0xd9, 0x98, 0x12, 0x5f, 0x4d, 0x9b, 0xfc, 0x0e,
+       0xee, 0xd7, 0xab, 0xe7, 0xbe, 0x2d, 0x06, 0x57, 0x31, 0x76, 0x77, 0x52,
+       0xe6, 0x13, 0x90, 0x79, 0x5c, 0xe6, 0xa7, 0xc9, 0xb3, 0x54, 0xe2, 0x71,
+       0x41, 0xbb, 0x94, 0x90, 0xb3, 0x93, 0x92, 0x3d, 0x7c, 0xaa, 0x57, 0xfa,
+       0x60, 0x9f, 0x73, 0x93, 0x57, 0x2a, 0xe0, 0xdb, 0xbd, 0x75, 0xe2, 0x02,
+       0x83, 0xe1, 0xef, 0x7b, 0xa2, 0x12, 0xc9, 0x64, 0xa0, 0x0b, 0x69, 0xe5,
+       0x83, 0x97, 0xfe, 0x2c, 0xeb, 0xfe, 0x65, 0xed, 0x3a, 0xf8, 0x79, 0xcc,
+       0xdb, 0x93, 0x56, 0x7a, 0x13, 0xfe, 0xcb, 0x01, 0x57, 0x72, 0xe9, 0x8f,
+       0xa1, 0x5b, 0x01, 0x4d, 0x81, 0x6d, 0xd0, 0x07, 0x7d, 0x10, 0xf2, 0x6d,
+       0xad, 0xc0, 0x17, 0x07, 0xf2, 0x0b, 0xfc, 0x11, 0xfd, 0x44, 0x82, 0x58,
+       0x0e, 0x5b, 0xa0, 0x6f, 0x88, 0x8b, 0x39, 0x63, 0x69, 0xff, 0x11, 0xd3,
+       0xfe, 0x23, 0x0e, 0xdf, 0xc1, 0xb6, 0xad, 0xdb, 0x8e, 0x6e, 0x27, 0xd0,
+       0x46, 0xec, 0x31, 0x43, 0xbb, 0x7a, 0xeb, 0xf8, 0xc8, 0xb4, 0xf2, 0x49,
+       0xf4, 0x67, 0xf0, 0x14, 0xf4, 0x29, 0xf4, 0x2d, 0xd8, 0x6f, 0x09, 0xeb,
+       0x55, 0x31, 0x9c, 0xf2, 0x08, 0xd3, 0x43, 0x5a, 0xd6, 0x89, 0x09, 0x3f,
+       0x9b, 0x75, 0x48, 0xef, 0x77, 0x20, 0x0f, 0x62, 0x25, 0xe9, 0xbe, 0x15,
+       0xb4, 0x72, 0x3f, 0xff, 0x97, 0xb4, 0x72, 0xbd, 0x5a, 0x7a, 0x3f, 0x2d,
+       0x66, 0x2b, 0xec, 0xc0, 0x9e, 0x33, 0xc0, 0x66, 0x31, 0xf6, 0x77, 0x0e,
+       0x62, 0xcf, 0x03, 0xc0, 0xee, 0x7e, 0x60, 0xf7, 0x1e, 0x60, 0x77, 0x1f,
+       0xb0, 0x3b, 0x0b, 0xec, 0xee, 0x05, 0x6e, 0xf7, 0x00, 0xb7, 0xd3, 0xe0,
+       0x8d, 0x23, 0xb3, 0xc0, 0xf1, 0x59, 0xe8, 0xcb, 0x2c, 0xe6, 0x28, 0xcc,
+       0x88, 0xf1, 0x35, 0xec, 0xe1, 0xe8, 0x54, 0x6a, 0x16, 0xfa, 0x9d, 0x18,
+       0x32, 0xa1, 0x07, 0xe9, 0xbb, 0x61, 0x6f, 0x88, 0x9b, 0xca, 0x83, 0x32,
+       0x0c, 0xbf, 0xdf, 0xb6, 0xb5, 0x1d, 0xfa, 0x84, 0x68, 0x24, 0x11, 0xe8,
+       0x68, 0xbf, 0x14, 0xbc, 0x76, 0xbb, 0xcd, 0xec, 0x42, 0x5f, 0x2a, 0x89,
+       0x18, 0xd5, 0x38, 0x74, 0x3a, 0x65, 0x8c, 0x9c, 0x26, 0x0f, 0x26, 0x81,
+       0x83, 0x15, 0x19, 0x4f, 0x53, 0x4f, 0x2b, 0xf2, 0x5c, 0x3a, 0xd5, 0x5b,
+       0x94, 0x46, 0x39, 0xe9, 0x4c, 0x2a, 0xdf, 0x6f, 0x65, 0x4e, 0x29, 0x1f,
+       0x3a, 0xec, 0xe2, 0x5a, 0x6a, 0x33, 0x0a, 0xa7, 0xb9, 0xd7, 0x76, 0xfc,
+       0xa2, 0x58, 0xf7, 0x57, 0x90, 0x91, 0x25, 0x7d, 0x3d, 0x62, 0x1c, 0xee,
+       0x2c, 0x02, 0x39, 0x53, 0xf6, 0x22, 0x56, 0xcb, 0x4f, 0xb6, 0x27, 0xda,
+       0x4d, 0x4b, 0x86, 0x2c, 0x43, 0x46, 0x61, 0x5f, 0x7d, 0xe9, 0xff, 0xa9,
+       0x9c, 0x74, 0xf8, 0xbc, 0x5e, 0xfe, 0x5c, 0x61, 0x31, 0xd6, 0x9e, 0x9f,
+       0xc6, 0xba, 0x51, 0xf0, 0x9b, 0xeb, 0x72, 0x1e, 0xb4, 0x81, 0x8b, 0x96,
+       0x9b, 0x9a, 0x2d, 0xca, 0x2e, 0xd8, 0xe9, 0x06, 0xc9, 0x6d, 0xaf, 0x93,
+       0xec, 0x40, 0x52, 0x0a, 0x53, 0xbb, 0x80, 0x8d, 0x31, 0x65, 0xab, 0x85,
+       0xc1, 0xa4, 0x3c, 0x36, 0xc5, 0xbe, 0x2c, 0xf6, 0x9a, 0x3a, 0x95, 0x15,
+       0xee, 0xd5, 0x90, 0xec, 0xc1, 0xac, 0x3c, 0xe6, 0x65, 0x65, 0x04, 0xf2,
+       0x3a, 0x0b, 0x5e, 0x1e, 0xf2, 0x5c, 0x79, 0x0e, 0xbe, 0x26, 0x7f, 0x1a,
+       0x58, 0xeb, 0xae, 0x07, 0x2e, 0xa6, 0xce, 0x31, 0xc6, 0x37, 0x19, 0x87,
+       0x82, 0x97, 0x7f, 0x34, 0x45, 0x5e, 0x9a, 0x32, 0x7d, 0xaf, 0x01, 0x3c,
+       0x48, 0x82, 0x77, 0xae, 0xfc, 0xb1, 0x97, 0x3a, 0x9f, 0x35, 0x81, 0xc5,
+       0xe9, 0xde, 0x88, 0x34, 0x24, 0x30, 0xce, 0x1f, 0x93, 0x4f, 0x47, 0x20,
+       0xd7, 0x22, 0xc6, 0xa6, 0xd0, 0xcf, 0x77, 0x1d, 0xfc, 0xb2, 0x18, 0x07,
+       0x5d, 0xb5, 0x53, 0xe7, 0x67, 0x4d, 0x8e, 0x4f, 0x42, 0x3e, 0x36, 0xc6,
+       0x03, 0xf8, 0x6c, 0xde, 0xa7, 0x8d, 0x02, 0x69, 0xf0, 0xa8, 0x53, 0x88,
+       0x49, 0xcb, 0xc4, 0xd4, 0xf6, 0x73, 0xaf, 0x0b, 0xd7, 0xf9, 0x22, 0xc6,
+       0x7f, 0x88, 0x38, 0xdc, 0x96, 0x79, 0xc8, 0xe5, 0xa7, 0xe0, 0x55, 0x36,
+       0xe1, 0xb7, 0x0b, 0x33, 0xa9, 0x73, 0x8b, 0x26, 0xef, 0xdd, 0xe2, 0xa8,
+       0xd9, 0x23, 0xd2, 0x4c, 0x7e, 0xa5, 0xc1, 0x2b, 0xd7, 0x36, 0xcd, 0xb4,
+       0xf2, 0x65, 0xbe, 0x2d, 0xdf, 0x05, 0x9a, 0xa0, 0xf3, 0xdd, 0x61, 0x9b,
+       0xa0, 0xaf, 0x0d, 0x6c, 0x22, 0x95, 0x98, 0x35, 0xe1, 0x9f, 0xbb, 0x2d,
+       0x39, 0xa5, 0xda, 0xe0, 0xd1, 0x60, 0x2a, 0x91, 0x35, 0x11, 0x33, 0x95,
+       0xba, 0xe4, 0xac, 0xc7, 0xf1, 0x49, 0x85, 0x51, 0xfe, 0x78, 0xc4, 0x7a,
+       0x1e, 0xe3, 0xc5, 0x2e, 0xd0, 0xec, 0xdb, 0xc9, 0xdc, 0xa4, 0xa3, 0x9e,
+       0x9d, 0xf4, 0xfc, 0xb8, 0xd0, 0x44, 0xec, 0x38, 0x8b, 0xd8, 0x31, 0xaf,
+       0x6c, 0xc6, 0xce, 0x22, 0xd7, 0x80, 0xce, 0xfb, 0xf6, 0x32, 0x5f, 0xba,
+       0x4f, 0x86, 0xcf, 0x7c, 0x3f, 0x6e, 0x22, 0xce, 0x2a, 0x38, 0xa4, 0x8b,
+       0xe3, 0xcf, 0x81, 0x4e, 0xf2, 0x4e, 0x86, 0x18, 0x57, 0x21, 0x16, 0x7e,
+       0x84, 0x32, 0x1e, 0xed, 0x7e, 0x88, 0x7c, 0x2b, 0x82, 0xe8, 0x53, 0x3e,
+       0x8e, 0x49, 0x91, 0x71, 0xe8, 0x62, 0xe4, 0x09, 0x19, 0x9a, 0xa7, 0x2f,
+       0xc4, 0xcf, 0x23, 0x26, 0x02, 0xc7, 0x94, 0xcf, 0x6a, 0x87, 0x3e, 0x14,
+       0xc1, 0xef, 0x8d, 0x3a, 0x0e, 0x3b, 0x08, 0xf9, 0xf6, 0x43, 0xfe, 0x19,
+       0x19, 0x39, 0x33, 0x42, 0xdd, 0xee, 0x9a, 0x97, 0x54, 0xd7, 0x49, 0xd9,
+       0x66, 0xcf, 0xc1, 0x06, 0xb3, 0x83, 0x95, 0x5d, 0x66, 0x86, 0xef, 0x9c,
+       0xc0, 0x3b, 0xb8, 0xce, 0x8f, 0xc8, 0xd1, 0x32, 0xfb, 0x9e, 0x05, 0xdf,
+       0x11, 0x17, 0xf7, 0x1c, 0xd4, 0xf6, 0x80, 0xf9, 0xac, 0x60, 0xbe, 0x11,
+       0x3d, 0x1f, 0xc7, 0x71, 0x0c, 0xdf, 0x59, 0x9a, 0x77, 0x37, 0x7d, 0x22,
+       0x30, 0xa8, 0xc3, 0xac, 0xec, 0x8a, 0xe2, 0xf9, 0x73, 0x3d, 0xbc, 0xc7,
+       0x3c, 0xf0, 0x89, 0xb6, 0xdb, 0x8f, 0xb1, 0x83, 0x98, 0x73, 0x9d, 0xb4,
+       0xb5, 0x04, 0xf4, 0x52, 0x3f, 0x18, 0xab, 0xb0, 0x3d, 0xb2, 0xc9, 0x97,
+       0xd1, 0xab, 0x11, 0xdf, 0xc7, 0xcc, 0xa2, 0x4d, 0x3b, 0x3c, 0x26, 0x79,
+       0x2f, 0x85, 0x7d, 0x42, 0x06, 0xe5, 0x51, 0xbd, 0x47, 0xc8, 0x69, 0xe0,
+       0x29, 0xf0, 0x41, 0x8a, 0x3e, 0x6f, 0xc8, 0x17, 0xf2, 0xe4, 0x38, 0x6c,
+       0xe0, 0x71, 0x8c, 0x41, 0xbc, 0xab, 0x78, 0x60, 0x6f, 0xf2, 0xe3, 0xf5,
+       0x54, 0x31, 0xcb, 0xbc, 0xb3, 0x99, 0xba, 0x0d, 0xdc, 0x2a, 0x0f, 0xd8,
+       0x9c, 0x7b, 0xd6, 0x64, 0x7e, 0x92, 0x4a, 0x5e, 0x88, 0xec, 0x67, 0xbb,
+       0x6b, 0xd6, 0x84, 0x8c, 0x20, 0xc7, 0xdc, 0xf6, 0x76, 0x8d, 0x55, 0xef,
+       0x28, 0x5d, 0xa6, 0xde, 0x17, 0xbc, 0x6d, 0xf6, 0x43, 0x42, 0x5d, 0x76,
+       0xa0, 0x17, 0xc4, 0x0b, 0x5e, 0x2d, 0xf8, 0xee, 0x04, 0x74, 0x61, 0xbd,
+       0xa6, 0x9d, 0xf7, 0x96, 0xcc, 0xda, 0x58, 0xc3, 0xfb, 0x8f, 0x0d, 0x7e,
+       0x1f, 0xef, 0x19, 0x33, 0x05, 0x72, 0x0c, 0x68, 0xa5, 0x3c, 0x6b, 0x65,
+       0xf8, 0x24, 0x68, 0x67, 0x3f, 0xae, 0xf3, 0xc7, 0x60, 0xa7, 0xc0, 0x94,
+       0x9e, 0x8e, 0xc4, 0x45, 0x8c, 0xcf, 0x03, 0xf7, 0x8b, 0x16, 0x9f, 0x5d,
+       0x31, 0x96, 0xde, 0x31, 0x19, 0x27, 0x23, 0x1e, 0xbf, 0x60, 0x7c, 0x0d,
+       0xb1, 0x4e, 0x6e, 0xfe, 0x8a, 0x91, 0x87, 0x5e, 0xcc, 0x7b, 0x77, 0x43,
+       0x9f, 0x68, 0x57, 0x36, 0xd6, 0x4e, 0x25, 0xfe, 0xc9, 0x6c, 0x4f, 0xce,
+       0x01, 0x03, 0x0e, 0x81, 0xb1, 0xbe, 0x2c, 0x5d, 0x25, 0xdb, 0x45, 0x33,
+       0xaa, 0xf1, 0x8f, 0xed, 0x94, 0xfd, 0xb0, 0xc0, 0x58, 0x1a, 0xf6, 0x80,
+       0xcf, 0x7b, 0x64, 0xb8, 0x9c, 0x91, 0xc2, 0x99, 0x6d, 0xf6, 0x28, 0x72,
+       0xf5, 0x25, 0xda, 0x89, 0x75, 0x45, 0x60, 0x1d, 0xfc, 0xb7, 0x27, 0xc5,
+       0xba, 0x0c, 0x31, 0xaf, 0x03, 0xfa, 0x84, 0xbe, 0xd2, 0x92, 0x4e, 0xde,
+       0xbf, 0x62, 0x3f, 0xf4, 0xdb, 0xcb, 0xf7, 0x34, 0x2f, 0xd7, 0xde, 0xd3,
+       0xee, 0xea, 0x9e, 0x88, 0x31, 0xf0, 0x03, 0x1e, 0xfc, 0x00, 0x74, 0xfa,
+       0x75, 0x0f, 0x7e, 0xc0, 0x83, 0x1f, 0x80, 0x3d, 0xbe, 0x02, 0x7d, 0x7c,
+       0xd9, 0x83, 0x2f, 0xf0, 0xe0, 0x0b, 0x3c, 0xf8, 0x02, 0x2f, 0x07, 0xd9,
+       0x11, 0xef, 0xe9, 0x4b, 0x0e, 0x54, 0xfd, 0xa7, 0x1f, 0x83, 0xdd, 0xa2,
+       0xe3, 0x1a, 0xd8, 0xae, 0xbd, 0x59, 0x46, 0xbb, 0x98, 0x13, 0x35, 0xe0,
+       0xda, 0x88, 0x2b, 0x62, 0x98, 0xae, 0x2f, 0x69, 0xdb, 0x79, 0x1c, 0x74,
+       0x01, 0x17, 0xba, 0xbe, 0x08, 0xdd, 0x44, 0x1c, 0xe1, 0xfe, 0x86, 0x8e,
+       0x7f, 0x7e, 0x64, 0xf9, 0xba, 0xd9, 0x88, 0xbe, 0xfb, 0xd0, 0xd7, 0x88,
+       0x31, 0x47, 0x31, 0x86, 0xf1, 0x53, 0x93, 0xee, 0x0b, 0x8f, 0x63, 0x1c,
+       0xf5, 0x00, 0xd6, 0x4a, 0x61, 0x5c, 0x13, 0xe6, 0x6e, 0xc5, 0x98, 0x9d,
+       0x18, 0x73, 0x2b, 0xda, 0x8c, 0xb9, 0xb7, 0xa0, 0x7d, 0x4f, 0xcd, 0x3b,
+       0xb7, 0xa3, 0xef, 0x4b, 0x35, 0x7d, 0x8b, 0xe8, 0xeb, 0x41, 0xdf, 0x45,
+       0xfd, 0x5e, 0x11, 0xed, 0x96, 0x9a, 0x31, 0x97, 0xd1, 0x87, 0xb8, 0xd9,
+       0xfe, 0x7b, 0x5c, 0xfb, 0x71, 0x25, 0x4d, 0xc1, 0x33, 0xc6, 0xcd, 0xc8,
+       0x41, 0xab, 0xb1, 0xef, 0x5b, 0x8c, 0x0b, 0xe1, 0x7b, 0x7f, 0x6c, 0xf9,
+       0x71, 0xe3, 0x77, 0x6d, 0x5f, 0x57, 0x83, 0xf6, 0x8f, 0x6a, 0xda, 0x1c,
+       0xfb, 0xdf, 0x35, 0x7d, 0x3b, 0x36, 0x2e, 0x6f, 0xdf, 0x59, 0xb7, 0xf2,
+       0x9d, 0x89, 0x9a, 0x31, 0x2f, 0x37, 0x2f, 0x6f, 0xff, 0xe9, 0x2a, 0xef,
+       0xec, 0xd9, 0xb0, 0xbc, 0xef, 0xd1, 0x4d, 0x35, 0x63, 0xa0, 0x53, 0x0e,
+       0x72, 0xab, 0x60, 0xfc, 0x03, 0x37, 0xf9, 0xcf, 0xc9, 0xdf, 0x5a, 0x5d,
+       0x52, 0x5b, 0x47, 0xdb, 0x84, 0x1c, 0x2e, 0x18, 0xb0, 0x39, 0xdb, 0xcc,
+       0x5c, 0x32, 0xf2, 0xd0, 0xa9, 0x5c, 0x39, 0x98, 0x8f, 0xb6, 0x5c, 0x5b,
+       0xdb, 0x08, 0x6a, 0x1a, 0x8c, 0xbb, 0xe2, 0xd0, 0x9b, 0xfd, 0x90, 0x71,
+       0x6a, 0xa2, 0x28, 0x4b, 0x36, 0xdc, 0x66, 0xae, 0x65, 0xc3, 0x4f, 0x6b,
+       0xdc, 0x7a, 0x0a, 0x74, 0x56, 0x64, 0x20, 0x5d, 0x4f, 0xff, 0xa4, 0xf1,
+       0x8c, 0x58, 0x54, 0xa9, 0x44, 0xb6, 0x56, 0xe4, 0x48, 0xfa, 0xc3, 0x8a,
+       0x28, 0x1c, 0x9c, 0x50, 0x58, 0x94, 0x34, 0xdb, 0x21, 0x23, 0x1b, 0xb9,
+       0x8d, 0x23, 0x43, 0x0e, 0xfd, 0xd9, 0x31, 0xc6, 0x29, 0x27, 0x7c, 0x9c,
+       0x25, 0x16, 0xa1, 0x8d, 0xbc, 0xae, 0x70, 0xda, 0x50, 0x31, 0x70, 0x61,
+       0x9e, 0xd8, 0x4e, 0x3c, 0x85, 0xdf, 0xb6, 0x39, 0xef, 0x6a, 0x78, 0x19,
+       0x8b, 0x32, 0x3e, 0xb4, 0xdc, 0x17, 0xe0, 0x1b, 0xf9, 0x8c, 0x71, 0x04,
+       0xee, 0x4b, 0xaa, 0xae, 0x56, 0x5c, 0xbe, 0x97, 0xcd, 0xcc, 0x43, 0xae,
+       0x63, 0x7f, 0xab, 0x63, 0x54, 0xbb, 0x79, 0x6d, 0x7b, 0xde, 0x5b, 0xb5,
+       0xe7, 0x40, 0xdf, 0x56, 0xab, 0x59, 0xbc, 0xa3, 0xf8, 0xff, 0x52, 0x39,
+       0x75, 0xaa, 0x08, 0xfb, 0x59, 0x50, 0x39, 0x7a, 0x20, 0x0b, 0xc6, 0x3c,
+       0xa9, 0x67, 0x66, 0xe9, 0x2d, 0x54, 0x8e, 0xc2, 0xfc, 0xa4, 0x22, 0xbb,
+       0xd3, 0xff, 0xa6, 0xf6, 0x9e, 0x35, 0x3b, 0xeb, 0x18, 0x63, 0x2c, 0x78,
+       0xe4, 0x53, 0x1a, 0xcf, 0x11, 0xfb, 0xa7, 0x7f, 0x26, 0x79, 0x87, 0x7d,
+       0xbf, 0xac, 0xcc, 0x21, 0x36, 0x52, 0xf1, 0x92, 0x8a, 0x0f, 0x18, 0xef,
+       0x1d, 0x01, 0x8f, 0xc8, 0xc7, 0x01, 0xf0, 0x36, 0x88, 0x19, 0xfe, 0x91,
+       0xbe, 0x58, 0x96, 0xc7, 0xd1, 0xc8, 0xb4, 0x4a, 0x97, 0x30, 0xa7, 0x89,
+       0xf9, 0xe8, 0xe3, 0xe8, 0x47, 0xd8, 0x5f, 0x88, 0x32, 0xb6, 0xf3, 0x63,
+       0x83, 0x08, 0xd6, 0xb3, 0x80, 0x83, 0xef, 0x0a, 0x63, 0x9a, 0x61, 0x25,
+       0x03, 0x62, 0x29, 0x9f, 0xb1, 0x2f, 0xa6, 0x63, 0xef, 0xb8, 0x8e, 0xb5,
+       0x6d, 0x1d, 0x6b, 0x93, 0x0e, 0xd6, 0x2d, 0x83, 0x38, 0x82, 0x72, 0xba,
+       0x70, 0xdc, 0xdc, 0xca, 0x38, 0xa2, 0x49, 0x56, 0x8f, 0x23, 0x02, 0x9a,
+       0x76, 0x82, 0x26, 0xc6, 0x7d, 0xaa, 0x4e, 0xd5, 0xec, 0xd7, 0xc6, 0x48,
+       0x43, 0xe0, 0x27, 0x95, 0x3f, 0x9e, 0x80, 0xeb, 0xc3, 0xde, 0x10, 0x48,
+       0x02, 0xdb, 0x73, 0x93, 0x3b, 0xb5, 0xdf, 0x65, 0x0e, 0xc1, 0xf8, 0xdd,
+       0xd7, 0xd3, 0x5c, 0x7a, 0x34, 0x98, 0xa7, 0x05, 0x9e, 0x32, 0x54, 0x43,
+       0xe3, 0x5a, 0x8c, 0x7b, 0x82, 0x18, 0x68, 0x8f, 0x8e, 0x81, 0xfa, 0xe5,
+       0x88, 0xe7, 0xe7, 0x0c, 0x03, 0xa5, 0x01, 0xf4, 0x29, 0xda, 0x13, 0x8c,
+       0x35, 0x4d, 0x93, 0xb1, 0x66, 0x0a, 0xc9, 0x87, 0xbf, 0x97, 0xb6, 0xad,
+       0xac, 0x65, 0x06, 0x7b, 0x69, 0xbc, 0xb0, 0x7c, 0x2f, 0xbb, 0x94, 0xde,
+       0x9b, 0xe0, 0x9d, 0x8f, 0x4d, 0x9c, 0xf3, 0x7c, 0x94, 0xb8, 0x35, 0x50,
+       0x1a, 0x54, 0xf3, 0x8e, 0xaf, 0x98, 0x57, 0xb0, 0xc7, 0x03, 0x6b, 0x3c,
+       0xe3, 0xfe, 0x19, 0x5b, 0xd8, 0x7a, 0xff, 0x81, 0x0c, 0x2f, 0x63, 0xce,
+       0x2e, 0xa3, 0xa0, 0xe2, 0xb6, 0x83, 0x4a, 0x1e, 0x85, 0xd2, 0x10, 0xae,
+       0xb4, 0x17, 0x35, 0x8f, 0xb2, 0x99, 0x51, 0x25, 0x83, 0x11, 0xb5, 0xc7,
+       0xb9, 0xd2, 0x23, 0x88, 0xd7, 0xbe, 0x0e, 0x3f, 0x18, 0xae, 0x2b, 0x3a,
+       0x18, 0x43, 0x5e, 0x15, 0x43, 0x78, 0x4a, 0x9a, 0x59, 0x33, 0xbc, 0x82,
+       0x35, 0xb8, 0xe7, 0x38, 0xe4, 0x6f, 0xf8, 0xcf, 0xd5, 0xfa, 0x01, 0xcf,
+       0xeb, 0x42, 0xf4, 0x54, 0x10, 0xbf, 0x26, 0x40, 0x43, 0xf8, 0x9d, 0x63,
+       0xd2, 0xe7, 0x51, 0x56, 0xed, 0x89, 0x11, 0xe4, 0xbb, 0x05, 0x09, 0x62,
+       0x11, 0xae, 0x4f, 0x0c, 0xc8, 0x23, 0x97, 0x4a, 0x60, 0x7f, 0x01, 0x5f,
+       0x03, 0x9e, 0xc6, 0x2f, 0xd4, 0xea, 0xc7, 0x38, 0xe8, 0x19, 0xf6, 0xc8,
+       0xa7, 0x40, 0x6f, 0x83, 0xb5, 0x2f, 0xab, 0xfd, 0x8c, 0xa9, 0xda, 0xe7,
+       0xfa, 0xba, 0x40, 0x7f, 0x47, 0x11, 0xb7, 0xf8, 0xfa, 0xf8, 0x7b, 0x9a,
+       0x37, 0x81, 0xde, 0xc6, 0xb5, 0x0e, 0x30, 0x47, 0xa4, 0x5d, 0x05, 0x3a,
+       0xd2, 0x61, 0xef, 0x57, 0xbc, 0xe0, 0x33, 0x95, 0x13, 0x2a, 0x39, 0x0f,
+       0x55, 0xe5, 0xbc, 0xbe, 0x46, 0x67, 0x3b, 0x6d, 0xdf, 0x46, 0x69, 0x8b,
+       0xb0, 0x69, 0xd0, 0xf7, 0xd2, 0x32, 0xdb, 0xef, 0x5a, 0xa3, 0xae, 0x1c,
+       0x97, 0xc8, 0xcc, 0x0f, 0xc0, 0xcb, 0xdb, 0x91, 0xd7, 0x20, 0xcb, 0x9f,
+       0x22, 0x46, 0x31, 0xfe, 0x58, 0x8a, 0x89, 0xe7, 0x64, 0xb5, 0x78, 0xf8,
+       0x5a, 0xb1, 0xc7, 0x9d, 0xd7, 0x19, 0x7b, 0xfc, 0x49, 0x1d, 0xf3, 0x9c,
+       0x05, 0xd8, 0xe9, 0x21, 0xbc, 0x5f, 0xe7, 0xfe, 0x10, 0x3e, 0xed, 0xaf,
+       0xac, 0x7a, 0x37, 0xc0, 0x8b, 0xb8, 0x6c, 0x9c, 0xd9, 0xac, 0x30, 0xc3,
+       0x9e, 0x5a, 0xc2, 0x8c, 0x51, 0xcf, 0xd7, 0x5f, 0xf0, 0xca, 0xd9, 0x28,
+       0xd7, 0x9b, 0x77, 0x2f, 0xe5, 0x10, 0x43, 0xd5, 0x1c, 0xe2, 0x96, 0x1a,
+       0x3e, 0xae, 0x86, 0x99, 0xe7, 0x54, 0xbe, 0xfc, 0x6a, 0x39, 0xf5, 0x82,
+       0x48, 0x1f, 0xf2, 0xe4, 0xd4, 0x79, 0x91, 0x2c, 0x72, 0x65, 0xe6, 0x73,
+       0x7b, 0x90, 0x3b, 0xa7, 0x7e, 0x21, 0xd2, 0x8b, 0x9c, 0x99, 0xf9, 0x70,
+       0x3f, 0xf8, 0xda, 0x03, 0x4c, 0x4d, 0x03, 0x63, 0xb7, 0x83, 0xbf, 0x5d,
+       0x0a, 0x57, 0x0f, 0x9d, 0x46, 0xae, 0xad, 0xea, 0xec, 0xb4, 0x75, 0x07,
+       0x7e, 0xb5, 0x52, 0x79, 0x2c, 0xdd, 0x8e, 0x7c, 0x3f, 0x29, 0x5f, 0xb6,
+       0x98, 0xf3, 0x1a, 0x56, 0xae, 0x7b, 0x26, 0x12, 0x8e, 0x63, 0x0b, 0xd7,
+       0xf4, 0x11, 0x2b, 0x79, 0x3f, 0xac, 0xfc, 0xc4, 0x78, 0xe4, 0x6a, 0xbc,
+       0xdf, 0x5f, 0xe5, 0xfd, 0x9d, 0x0d, 0xd2, 0xd0, 0xaf, 0xea, 0x0b, 0xb9,
+       0xee, 0xaf, 0x13, 0xcb, 0xd2, 0xf0, 0xf3, 0xf0, 0xc7, 0x15, 0xb9, 0x3f,
+       0x7d, 0xa5, 0x72, 0xd1, 0xdd, 0x20, 0x85, 0xed, 0x07, 0x34, 0x9e, 0x1f,
+       0x78, 0x32, 0xe7, 0x16, 0x61, 0x1f, 0xfa, 0xdb, 0xc2, 0x64, 0x0c, 0x51,
+       0x29, 0xff, 0x9a, 0x65, 0xae, 0xf7, 0xf6, 0x7a, 0x69, 0xd8, 0xf6, 0x02,
+       0x8b, 0x63, 0xc4, 0x99, 0x39, 0x27, 0xae, 0xea, 0xdd, 0x37, 0xb9, 0xec,
+       0xb7, 0x21, 0xd3, 0xdf, 0x92, 0x39, 0xc4, 0x13, 0xf3, 0xbd, 0xa0, 0x71,
+       0x7b, 0x0b, 0xc6, 0xd3, 0xee, 0xc8, 0xf3, 0xdf, 0x96, 0xa1, 0x41, 0xf2,
+       0xd4, 0xc1, 0xf8, 0xfb, 0x31, 0xa6, 0x19, 0xd7, 0x07, 0x23, 0x73, 0x76,
+       0xcc, 0x6f, 0x0f, 0x70, 0x0e, 0xfa, 0x52, 0xce, 0xc3, 0xb5, 0x5a, 0x94,
+       0xcd, 0x2f, 0xcd, 0xcf, 0xb9, 0xf9, 0xec, 0xe3, 0xca, 0xbe, 0xee, 0xee,
+       0xd0, 0x1a, 0x4d, 0xa1, 0x35, 0x7a, 0x42, 0x6b, 0x90, 0xb6, 0xe6, 0x10,
+       0x6d, 0xcd, 0x78, 0xff, 0x3e, 0xac, 0xd7, 0xaf, 0xe3, 0x94, 0x60, 0x9d,
+       0x60, 0x1f, 0x2d, 0xa1, 0xb1, 0x1f, 0x62, 0x0d, 0xf6, 0x39, 0xa1, 0x3e,
+       0xae, 0x0b, 0x1c, 0x73, 0xd8, 0x6e, 0x0e, 0xd1, 0x42, 0xfa, 0x1a, 0xd0,
+       0xaf, 0xe6, 0x02, 0x3f, 0x1b, 0xe0, 0xbb, 0x4c, 0xf8, 0x8f, 0x08, 0xe2,
+       0xaa, 0x60, 0x4f, 0xc1, 0x1c, 0x0e, 0xde, 0xe3, 0x18, 0xff, 0xb9, 0xff,
+       0x0e, 0xfb, 0xf9, 0x3c, 0x22, 0xdf, 0x53, 0xf4, 0xb2, 0xcd, 0x3d, 0x34,
+       0x81, 0x56, 0x5e, 0x53, 0x32, 0xdb, 0x0c, 0xd9, 0x77, 0x33, 0x9f, 0x36,
+       0xe4, 0x36, 0xd7, 0x34, 0xf2, 0xdd, 0x94, 0xef, 0x06, 0x8d, 0x97, 0x0d,
+       0x46, 0xee, 0x34, 0x6b, 0x08, 0x8d, 0x3a, 0xf7, 0x43, 0xbe, 0xa1, 0x7c,
+       0x4c, 0xe0, 0x03, 0xe8, 0x63, 0x18, 0xab, 0xd0, 0x7f, 0x66, 0xf5, 0x3d,
+       0xae, 0xd0, 0xd3, 0xc3, 0xf3, 0xcd, 0x72, 0x51, 0xf1, 0xd0, 0x96, 0xc5,
+       0x2a, 0x0f, 0xa3, 0xfa, 0xbb, 0xd1, 0x31, 0xfd, 0x4d, 0x66, 0x3f, 0xe2,
+       0x01, 0xdc, 0x97, 0x80, 0xb9, 0xdd, 0xd0, 0xb7, 0x6e, 0xe6, 0x70, 0x45,
+       0x5c, 0x59, 0xc3, 0x30, 0x70, 0x75, 0x70, 0x8d, 0xe1, 0x0a, 0xbf, 0x04,
+       0xac, 0xc9, 0x77, 0xbf, 0x0d, 0x1d, 0x82, 0x6c, 0xca, 0xb6, 0x71, 0xbf,
+       0xe7, 0xd7, 0x87, 0x16, 0xdd, 0xd5, 0xeb, 0x43, 0x8b, 0xa2, 0xea, 0x43,
+       0x13, 0xd7, 0xa8, 0x0f, 0x65, 0xaf, 0xbf, 0x3e, 0x74, 0xa2, 0x9e, 0x18,
+       0xbc, 0xb7, 0x47, 0x8c, 0xdf, 0xd5, 0xf5, 0xa1, 0xf7, 0xc5, 0xaf, 0x0f,
+       0x5d, 0x94, 0xd5, 0xeb, 0x43, 0x13, 0x35, 0xf5, 0xa1, 0x8d, 0xaa, 0x3e,
+       0xc4, 0x79, 0xfc, 0xfa, 0x10, 0xdb, 0x6d, 0xdd, 0xbd, 0xa1, 0x3a, 0x08,
+       0xf0, 0x54, 0xe5, 0x84, 0xb6, 0x31, 0xe8, 0x05, 0x18, 0x45, 0x2c, 0xbf,
+       0xb9, 0xea, 0x8f, 0x96, 0xf0, 0xca, 0x50, 0xba, 0x75, 0x2d, 0xbc, 0x1a,
+       0xf4, 0x63, 0x90, 0x65, 0x58, 0x35, 0x5e, 0x8d, 0x53, 0x5e, 0xab, 0x67,
+       0xde, 0x3c, 0x56, 0x5a, 0x9a, 0x77, 0x0c, 0xb2, 0x1d, 0xaa, 0xd6, 0x50,
+       0xd6, 0x8a, 0x85, 0x1c, 0x39, 0xb6, 0xea, 0x37, 0xb8, 0x44, 0x76, 0xe5,
+       0x37, 0x38, 0x43, 0x1c, 0xd0, 0xd9, 0xd6, 0x5d, 0x50, 0x79, 0xd5, 0x9c,
+       0xf7, 0x55, 0xb9, 0xf0, 0xb0, 0x0d, 0x3c, 0x09, 0x6a, 0x26, 0x94, 0xe5,
+       0x92, 0x8f, 0x28, 0x98, 0x9f, 0x5f, 0xdd, 0xe4, 0xb0, 0xaa, 0x9b, 0xfc,
+       0xbc, 0x3e, 0x5c, 0x37, 0x59, 0x94, 0xab, 0xd7, 0x4d, 0x0e, 0xaf, 0x52,
+       0x37, 0x79, 0x53, 0x96, 0xea, 0x26, 0x6f, 0x4a, 0x50, 0x37, 0x89, 0xc8,
+       0x85, 0x4d, 0x9c, 0xe7, 0x08, 0xde, 0x19, 0xc0, 0xaf, 0x1f, 0x3f, 0xbf,
+       0x8e, 0xb2, 0x58, 0xa5, 0x7f, 0xb5, 0x3a, 0x4a, 0x7d, 0xec, 0x93, 0xd4,
+       0x51, 0x7c, 0x4c, 0x0f, 0xea, 0x28, 0x0d, 0x88, 0x5f, 0xe0, 0x43, 0xcc,
+       0x70, 0x1d, 0xa5, 0x15, 0xf3, 0xb2, 0x8f, 0x6d, 0xf6, 0xc3, 0x2e, 0xe0,
+       0x67, 0xb2, 0xaa, 0xce, 0xf1, 0x9b, 0x9a, 0x87, 0x07, 0xb0, 0xe7, 0x24,
+       0x64, 0x41, 0x3e, 0xb6, 0xab, 0x38, 0x32, 0x6b, 0x25, 0x8c, 0x5c, 0x27,
+       0xbc, 0xd3, 0x24, 0xbf, 0xd9, 0x27, 0x64, 0xa4, 0x4c, 0x1d, 0x6f, 0x45,
+       0xdc, 0x6d, 0xa1, 0xef, 0x00, 0xda, 0x41, 0x8c, 0xd4, 0x5d, 0x9d, 0x83,
+       0x76, 0x38, 0xc7, 0x7a, 0x9f, 0x73, 0x3d, 0x3e, 0x67, 0x27, 0x68, 0x0e,
+       0xef, 0xa3, 0x08, 0x7f, 0x83, 0x3e, 0x25, 0x73, 0xc6, 0x8a, 0x01, 0x2d,
+       0x49, 0xda, 0xf4, 0x75, 0xcc, 0xc7, 0xbe, 0x9d, 0x2a, 0xdf, 0x1a, 0xee,
+       0xe1, 0x5e, 0xe9, 0xbb, 0x16, 0x40, 0x1f, 0xfa, 0xe6, 0x99, 0xe3, 0xd1,
+       0x8f, 0x05, 0x39, 0x58, 0x5c, 0xe5, 0x60, 0x2d, 0x8a, 0x1f, 0xe4, 0xf5,
+       0x23, 0x31, 0xe2, 0x63, 0x8b, 0xcb, 0x3d, 0xf4, 0x6b, 0x5c, 0x63, 0xdb,
+       0xcf, 0xf5, 0x58, 0x8f, 0x6e, 0x71, 0x9f, 0x80, 0x5c, 0x59, 0xab, 0x09,
+       0xe4, 0xf7, 0x0d, 0xbd, 0xef, 0x5e, 0x29, 0xb6, 0x48, 0x6c, 0x23, 0xe8,
+       0x69, 0x9b, 0x62, 0x8c, 0x7d, 0x8f, 0xca, 0x37, 0x1c, 0x77, 0x6d, 0xbb,
+       0xdd, 0x7f, 0x03, 0x76, 0x3b, 0x70, 0x55, 0xbb, 0x3d, 0x1b, 0x0b, 0xdb,
+       0xed, 0xfe, 0x1b, 0xb0, 0xdb, 0x23, 0x37, 0x64, 0xb7, 0xdc, 0x1b, 0x31,
+       0x29, 0xa8, 0x8b, 0xad, 0x8c, 0x9b, 0x82, 0x75, 0x47, 0xb1, 0x66, 0x76,
+       0x8d, 0x35, 0x87, 0xd6, 0xac, 0xbb, 0xd6, 0xc6, 0x4c, 0xd7, 0x23, 0x6f,
+       0xe6, 0x21, 0xf4, 0xab, 0x71, 0xed, 0x83, 0x9e, 0xd6, 0x3a, 0x1f, 0xe4,
+       0xed, 0x61, 0xfb, 0xa1, 0x5e, 0x50, 0x17, 0x7e, 0x02, 0x7e, 0x51, 0x1f,
+       0x02, 0x9b, 0x6b, 0xaf, 0xd1, 0xc1, 0x05, 0xe4, 0xf3, 0xed, 0x5a, 0x07,
+       0x29, 0xeb, 0x4e, 0xf5, 0x3d, 0x69, 0xde, 0x7b, 0xc2, 0xcf, 0xe3, 0xa1,
+       0x03, 0x85, 0xf9, 0xc0, 0xd6, 0x92, 0x58, 0x37, 0x78, 0x46, 0x3e, 0xba,
+       0x88, 0x61, 0xb6, 0x21, 0xfe, 0x02, 0x8f, 0x54, 0xff, 0xf2, 0x3a, 0xf0,
+       0xd5, 0xf1, 0x4c, 0x8a, 0x51, 0x8c, 0x7d, 0xae, 0x07, 0x36, 0xde, 0x43,
+       0x8c, 0xca, 0x20, 0x8f, 0xa1, 0x1e, 0x52, 0x37, 0x3b, 0xba, 0x0e, 0x99,
+       0x8c, 0x91, 0x0e, 0xc2, 0xf6, 0x6c, 0xa5, 0xc7, 0xbb, 0xcb, 0x1d, 0xe7,
+       0x16, 0x4d, 0xae, 0x51, 0xa9, 0x14, 0x54, 0xbd, 0x5e, 0xcc, 0x5c, 0xf7,
+       0x4d, 0xeb, 0xe8, 0x97, 0x6e, 0x76, 0x23, 0x5a, 0xd7, 0xb2, 0xb8, 0xa7,
+       0xde, 0xfe, 0x2b, 0x7c, 0x3b, 0xf2, 0x89, 0xee, 0x7f, 0x41, 0x7f, 0x02,
+       0x36, 0x4f, 0x5f, 0xce, 0xfc, 0x62, 0x87, 0x1e, 0xd7, 0xae, 0xbe, 0x95,
+       0xaa, 0xef, 0x2d, 0x4e, 0xe0, 0x7f, 0x52, 0xf4, 0xcf, 0xcb, 0xe4, 0xcc,
+       0xb3, 0x1b, 0x79, 0x95, 0x9f, 0xf0, 0x7d, 0xa5, 0x93, 0xc8, 0x29, 0xac,
+       0x50, 0x9d, 0x3d, 0xa6, 0x73, 0x31, 0xda, 0x58, 0x5c, 0xe5, 0x89, 0x7e,
+       0xee, 0xc1, 0x5c, 0x75, 0xf9, 0x99, 0x8d, 0xd5, 0x75, 0x60, 0xf3, 0x27,
+       0xd0, 0x81, 0x5a, 0xf9, 0xc5, 0x60, 0xfb, 0x81, 0xfc, 0x82, 0x98, 0x65,
+       0x56, 0xef, 0xbb, 0xdd, 0x97, 0xe1, 0xff, 0x8b, 0x7d, 0x1a, 0xa1, 0x7d,
+       0x06, 0x78, 0x74, 0x58, 0xef, 0x73, 0x47, 0x0d, 0x1e, 0x0d, 0xd4, 0xd8,
+       0xec, 0xe7, 0x89, 0x47, 0x97, 0xd7, 0x7d, 0xfe, 0x78, 0xc4, 0x7d, 0x6d,
+       0x59, 0x15, 0x87, 0xfc, 0x7d, 0x3c, 0x2d, 0x66, 0xe6, 0xb3, 0xcc, 0xdf,
+       0x3e, 0x89, 0x7c, 0xc2, 0x38, 0x42, 0x99, 0x34, 0xa9, 0x78, 0xd5, 0xb7,
+       0x3d, 0xf8, 0xf2, 0xf9, 0xa8, 0xbc, 0xf7, 0x50, 0x4c, 0x7e, 0x75, 0x2f,
+       0xbf, 0x95, 0x59, 0xba, 0x7e, 0xc5, 0x76, 0xb4, 0xc1, 0xf7, 0x43, 0x48,
+       0x24, 0x94, 0xdf, 0xe1, 0x3b, 0x81, 0x3d, 0xdb, 0x78, 0xce, 0x67, 0x5b,
+       0xe4, 0x42, 0xf3, 0x8d, 0xe4, 0x74, 0x1d, 0xf6, 0xfb, 0xe6, 0x6a, 0x39,
+       0xdd, 0xd5, 0x6b, 0x7f, 0x4b, 0x39, 0x1d, 0x71, 0xb6, 0x59, 0xd7, 0x7b,
+       0x98, 0xd7, 0xec, 0xd7, 0xd8, 0xc9, 0x7b, 0xe4, 0xaa, 0x1e, 0xf2, 0x57,
+       0xc8, 0xf6, 0x35, 0xc4, 0x4b, 0xaf, 0x7a, 0xc8, 0x59, 0x3d, 0xe4, 0xaa,
+       0x1e, 0x72, 0x55, 0x0f, 0xb9, 0xaa, 0xd7, 0xa5, 0x73, 0xde, 0x01, 0x5d,
+       0xd7, 0xe7, 0xf7, 0x70, 0xd6, 0x0b, 0x8a, 0xf0, 0x25, 0xe3, 0x3c, 0x63,
+       0x61, 0xe6, 0xd2, 0xeb, 0x82, 0x73, 0x48, 0xba, 0xe6, 0xdd, 0xaa, 0x6b,
+       0x30, 0x75, 0x37, 0x29, 0xdf, 0x6c, 0xbe, 0xd1, 0xe0, 0x7f, 0x33, 0xe7,
+       0xf9, 0x8f, 0x3f, 0x44, 0x5c, 0xc2, 0x1a, 0xd8, 0x04, 0x6d, 0xb4, 0x62,
+       0x66, 0x58, 0x63, 0x11, 0xd3, 0xcc, 0x7c, 0x01, 0xef, 0x6c, 0xc3, 0x1e,
+       0xea, 0x69, 0xdb, 0x11, 0x33, 0xd3, 0x48, 0x9e, 0x1a, 0x66, 0x66, 0xbd,
+       0x9e, 0xeb, 0x6f, 0x1a, 0xfc, 0xd8, 0xaa, 0x93, 0x6d, 0xcb, 0x64, 0x9c,
+       0xa0, 0x62, 0xed, 0xa0, 0x7f, 0x4f, 0xf3, 0xf2, 0xb5, 0xa2, 0x0a, 0xdf,
+       0x73, 0xe9, 0x87, 0x31, 0x9f, 0x3a, 0xdb, 0x54, 0xe5, 0xb7, 0xb9, 0x26,
+       0xbf, 0xa3, 0x9a, 0xdf, 0x3e, 0x8f, 0x23, 0x1c, 0xa7, 0xea, 0xbe, 0xe4,
+       0x75, 0x30, 0x9f, 0xaa, 0xe1, 0x61, 0x1d, 0x75, 0x8e, 0x03, 0xd7, 0xbb,
+       0xa2, 0xd2, 0x34, 0x78, 0x20, 0xea, 0x86, 0xd7, 0x25, 0x46, 0xf5, 0x2e,
+       0xfb, 0xfe, 0xb4, 0xf6, 0x9a, 0xed, 0xea, 0xdb, 0x99, 0xef, 0x33, 0xa2,
+       0x4a, 0x07, 0x2d, 0x75, 0x36, 0xef, 0xd7, 0xea, 0xcc, 0x0d, 0xf5, 0x2f,
+       0x8f, 0x3c, 0x66, 0xbc, 0xa7, 0x23, 0x69, 0x99, 0x7f, 0xd1, 0xc0, 0x5a,
+       0x6b, 0x5f, 0x39, 0xc0, 0x3d, 0xae, 0x57, 0xeb, 0xc7, 0x59, 0x27, 0x0b,
+       0xf0, 0x4c, 0x36, 0xfb, 0xf5, 0xb3, 0x4f, 0x63, 0x4b, 0x0d, 0x35, 0xb6,
+       0x14, 0xec, 0xd3, 0xcf, 0x57, 0xf9, 0xdd, 0x7a, 0xb5, 0xb3, 0x13, 0x0b,
+       0xe5, 0xd0, 0xf7, 0x8f, 0xaa, 0x6e, 0xf0, 0x5c, 0xcb, 0x83, 0xd0, 0x41,
+       0xd6, 0xfe, 0xf7, 0xc0, 0x8e, 0x2a, 0x95, 0x3e, 0xd6, 0x93, 0xb7, 0x3f,
+       0xa0, 0xcf, 0x27, 0x3c, 0xa3, 0xea, 0x09, 0xd6, 0x8a, 0x7a, 0x42, 0x1f,
+       0x74, 0x05, 0x31, 0x00, 0x6c, 0xb0, 0xa0, 0x64, 0xc9, 0x78, 0xa0, 0xf6,
+       0xfb, 0xca, 0xf9, 0x46, 0x9f, 0x0f, 0xb7, 0x37, 0xfa, 0xdf, 0x18, 0x7e,
+       0xe9, 0x2c, 0x6f, 0xf3, 0xfd, 0x44, 0x63, 0x70, 0xce, 0x67, 0xf8, 0x4c,
+       0x1f, 0x74, 0xb1, 0x4e, 0xf2, 0x6a, 0x3e, 0xc4, 0xbb, 0xcf, 0xff, 0xac,
+       0x79, 0xf9, 0x78, 0xf4, 0x9d, 0x09, 0xc6, 0x37, 0xd7, 0x8c, 0x6f, 0xc6,
+       0xf8, 0x7f, 0xaf, 0x19, 0xdf, 0x1c, 0x1a, 0xef, 0xd4, 0x8c, 0x77, 0x30,
+       0xbe, 0x7e, 0xd3, 0xf2, 0xf1, 0x4e, 0x68, 0x7c, 0x4b, 0xcd, 0xf8, 0x16,
+       0x8c, 0x6f, 0xa8, 0x19, 0x8f, 0xbe, 0x33, 0x75, 0xfa, 0xbb, 0x17, 0x31,
+       0xf6, 0x88, 0xce, 0xbb, 0x71, 0x2d, 0xd5, 0x7e, 0x4b, 0xa1, 0xde, 0xb5,
+       0x42, 0x06, 0xc1, 0x39, 0x3b, 0xda, 0x6b, 0x16, 0xf6, 0xba, 0x14, 0xcb,
+       0xf8, 0xfa, 0x18, 0xd6, 0x45, 0xe2, 0x43, 0x51, 0x22, 0x2e, 0x74, 0x67,
+       0x1e, 0x3a, 0x34, 0x1f, 0xf8, 0x24, 0x9e, 0x99, 0x4a, 0x75, 0xf9, 0x7a,
+       0x6a, 0x48, 0xd4, 0x5d, 0xd0, 0x39, 0xd8, 0x4e, 0xd2, 0x0e, 0xbc, 0x0c,
+       0x30, 0x53, 0x4e, 0xf9, 0x76, 0x43, 0xfd, 0xe5, 0xfc, 0xda, 0x7e, 0xa8,
+       0xab, 0x7a, 0x9d, 0xbe, 0x15, 0xb8, 0x96, 0x5c, 0x51, 0xab, 0x8a, 0x5c,
+       0x07, 0xae, 0x0d, 0x54, 0x71, 0xed, 0x41, 0x99, 0xad, 0xe6, 0xdb, 0xfd,
+       0x72, 0xd4, 0xdb, 0xcb, 0xf3, 0x38, 0xa7, 0xb2, 0xf2, 0xd9, 0xe4, 0xdb,
+       0x7b, 0xab, 0x7e, 0x32, 0x35, 0x91, 0x95, 0x0b, 0xc7, 0x99, 0x43, 0x05,
+       0xb5, 0xd6, 0x71, 0xef, 0x5b, 0x94, 0x0b, 0x6c, 0xe3, 0x46, 0xf3, 0x6d,
+       0xce, 0xe7, 0xc8, 0x51, 0xff, 0x2c, 0x44, 0x75, 0xde, 0x62, 0x75, 0xde,
+       0x84, 0xb6, 0x37, 0xfa, 0xe0, 0x25, 0x7f, 0x99, 0x87, 0xbf, 0x1c, 0x42,
+       0xce, 0xbd, 0xe0, 0xad, 0x56, 0xef, 0xbc, 0x51, 0x7f, 0x59, 0x5b, 0x37,
+       0xae, 0xf5, 0x97, 0x5c, 0xa7, 0xb6, 0x56, 0x9c, 0xac, 0xc1, 0x7f, 0xea,
+       0xd3, 0x53, 0x3a, 0xa6, 0xc6, 0x75, 0xfe, 0x29, 0xd8, 0xa3, 0x29, 0x43,
+       0x4a, 0x7f, 0xd9, 0x0e, 0x72, 0xcb, 0x03, 0xd5, 0xdc, 0x72, 0x29, 0x1f,
+       0x44, 0xec, 0xda, 0x75, 0x9f, 0xc6, 0x47, 0xc6, 0xc8, 0xe3, 0xe8, 0x3f,
+       0x05, 0x1d, 0xe0, 0x33, 0xd6, 0x3f, 0xef, 0x90, 0x2f, 0x5b, 0xbe, 0x7f,
+       0xf2, 0xeb, 0x50, 0x07, 0x54, 0xfc, 0xcf, 0xfa, 0xff, 0x70, 0x7a, 0xa3,
+       0x8e, 0xf7, 0xae, 0x85, 0xab, 0xcb, 0x73, 0x53, 0xd3, 0x3c, 0x81, 0x77,
+       0x99, 0x9b, 0x3e, 0x10, 0x27, 0x86, 0xe6, 0xca, 0x57, 0x7d, 0xbf, 0x48,
+       0xff, 0x32, 0xac, 0xbe, 0xfb, 0xa9, 0x3c, 0x14, 0xe3, 0x16, 0xf4, 0xfb,
+       0x7e, 0x1e, 0x9a, 0x2b, 0x6f, 0x89, 0xfb, 0x38, 0x78, 0xb5, 0x9c, 0xe5,
+       0x58, 0x9c, 0xb5, 0xbc, 0x05, 0xef, 0x5a, 0xb4, 0xae, 0xcc, 0x7b, 0x23,
+       0x2b, 0xf2, 0xde, 0x41, 0x9d, 0xd7, 0x7e, 0x45, 0xe5, 0xbd, 0x3e, 0x8f,
+       0xb9, 0x97, 0x70, 0x1e, 0xe5, 0x02, 0x0b, 0xf9, 0x8d, 0x84, 0xf8, 0x30,
+       0xaa, 0xfc, 0x56, 0x61, 0xf2, 0x77, 0xd4, 0xf9, 0x89, 0x95, 0x7a, 0xf3,
+       0x79, 0xfb, 0x89, 0x60, 0xef, 0x4f, 0x89, 0x5f, 0xaf, 0xdb, 0x03, 0x5a,
+       0x98, 0x5b, 0x45, 0xb5, 0x3e, 0xa4, 0x34, 0x5e, 0x07, 0xe3, 0x82, 0x3c,
+       0xbe, 0xfa, 0x5d, 0xb5, 0x98, 0x5d, 0x56, 0x3f, 0xd9, 0x42, 0x18, 0x86,
+       0xdc, 0xb3, 0x37, 0xf0, 0x1d, 0xe2, 0xd3, 0x9c, 0x7f, 0xa8, 0xf5, 0x6b,
+       0xfc, 0x46, 0xda, 0xaa, 0xcf, 0xc7, 0xb9, 0xb0, 0x01, 0x9e, 0x65, 0x0e,
+       0xe3, 0xab, 0x3a, 0x03, 0x17, 0x73, 0x32, 0x62, 0xec, 0x23, 0x7d, 0xe9,
+       0x7f, 0xd6, 0xfb, 0x4c, 0xc8, 0x91, 0x29, 0xbf, 0xbe, 0x69, 0xae, 0x71,
+       0xfe, 0xcd, 0x34, 0xaf, 0xab, 0xbe, 0x79, 0x03, 0xe7, 0xdf, 0x5e, 0x8f,
+       0x07, 0xf5, 0xcd, 0xda, 0xf3, 0x6f, 0x91, 0xeb, 0x3c, 0xff, 0xe6, 0xd7,
+       0x37, 0x39, 0x4f, 0xb8, 0xbe, 0x79, 0x8f, 0x3a, 0x43, 0x36, 0x3a, 0xd5,
+       0xa3, 0xce, 0x23, 0xb7, 0x75, 0xaf, 0x8d, 0xb3, 0xfb, 0x3e, 0xb3, 0x7c,
+       0xe4, 0x3f, 0xe3, 0xe1, 0x7c, 0x64, 0xdf, 0xe7, 0x92, 0x8f, 0x70, 0x2f,
+       0xbf, 0xef, 0x7f, 0xb7, 0xad, 0x39, 0xfb, 0x95, 0xfb, 0x1c, 0x6b, 0x98,
+       0x47, 0x54, 0x0d, 0x73, 0xcb, 0xfa, 0x70, 0x0d, 0xd3, 0xbc, 0xc6, 0xd9,
+       0xaf, 0x23, 0xab, 0xd4, 0x30, 0xa3, 0xa1, 0xb3, 0x5f, 0x51, 0x7d, 0xf6,
+       0x6b, 0xa3, 0x8b, 0xbc, 0x51, 0xd7, 0x2c, 0xcd, 0xab, 0x9e, 0xfd, 0xea,
+       0x59, 0xff, 0x49, 0x6a, 0x96, 0xb9, 0x65, 0x35, 0xcb, 0x15, 0x67, 0xbf,
+       0xe0, 0xd7, 0x36, 0x4b, 0x32, 0x94, 0xe3, 0xe4, 0x6e, 0xf0, 0x6c, 0x43,
+       0xfe, 0x3a, 0xe2, 0x80, 0x7d, 0x55, 0x5b, 0xe5, 0xd9, 0xfd, 0x3a, 0xec,
+       0x39, 0x2a, 0x7b, 0x1d, 0xea, 0x27, 0xcf, 0x38, 0x76, 0xc2, 0x16, 0x70,
+       0x2d, 0xb3, 0xdd, 0x45, 0x19, 0x19, 0x03, 0x9d, 0xcb, 0xcf, 0x17, 0x2c,
+       0x9d, 0xd3, 0x8d, 0x55, 0xcf, 0xe9, 0x9e, 0x84, 0xde, 0x98, 0x53, 0x31,
+       0x99, 0x0b, 0xe9, 0xd4, 0x38, 0x62, 0x3b, 0x73, 0xc6, 0xd6, 0xcf, 0x93,
+       0x12, 0x99, 0x72, 0x80, 0x6f, 0x3c, 0xdb, 0xdb, 0x24, 0x91, 0x19, 0xff,
+       0x7b, 0xa3, 0xa9, 0xf0, 0x33, 0x81, 0x31, 0x3c, 0xdb, 0x19, 0x95, 0xa3,
+       0xaa, 0x3e, 0x11, 0xe8, 0xf2, 0x37, 0xc1, 0xe3, 0x4d, 0xd9, 0xa5, 0xb6,
+       0xb3, 0x8a, 0x8f, 0x47, 0xcc, 0x38, 0x45, 0x7d, 0xbe, 0x5b, 0xf2, 0xba,
+       0xf6, 0x33, 0x5c, 0xde, 0xa9, 0x73, 0x09, 0xf5, 0xcd, 0x06, 0xbc, 0x6c,
+       0xd3, 0xfe, 0x16, 0xd7, 0xf9, 0x36, 0xfa, 0x37, 0xc6, 0xcc, 0xd2, 0x37,
+       0xb9, 0x2d, 0x31, 0x02, 0x6c, 0x1b, 0x52, 0x6b, 0xde, 0x08, 0xcf, 0x8d,
+       0x15, 0xf1, 0xd7, 0x8d, 0xf1, 0x3d, 0x88, 0x85, 0xdf, 0xc4, 0xfe, 0xda,
+       0xa0, 0x1f, 0x8f, 0x4b, 0xfe, 0xcc, 0x1d, 0xd2, 0x37, 0x9d, 0x02, 0x3d,
+       0xbf, 0xae, 0x0c, 0xa7, 0x11, 0x37, 0x3f, 0xcf, 0x33, 0x60, 0xc0, 0x4b,
+       0xf0, 0xed, 0x95, 0x15, 0xdf, 0xa0, 0xc3, 0xe7, 0xc6, 0xba, 0xaa, 0xe7,
+       0x80, 0x5e, 0x2a, 0x4b, 0xac, 0x99, 0x34, 0x4f, 0x2d, 0x9d, 0x09, 0x5f,
+       0x28, 0xef, 0x56, 0x7e, 0xec, 0xc5, 0xf2, 0xff, 0x52, 0x77, 0x6d, 0xb1,
+       0x6d, 0x9d, 0xf7, 0xfd, 0xcf, 0x43, 0xea, 0x12, 0xdd, 0x7c, 0x24, 0xd3,
+       0x32, 0x2d, 0xd1, 0xf2, 0x39, 0xd2, 0xb1, 0xc5, 0xd8, 0x5a, 0xc7, 0x6a,
+       0xca, 0x26, 0xac, 0x5a, 0xc2, 0x52, 0xf4, 0x65, 0x59, 0x36, 0xd0, 0x97,
+       0x76, 0x1e, 0x16, 0xa0, 0x0e, 0x65, 0x3b, 0x1d, 0xd0, 0x07, 0xb7, 0xd9,
+       0x80, 0xa4, 0x03, 0x6c, 0x96, 0xb2, 0x1c, 0xaf, 0x53, 0x4d, 0x36, 0x66,
+       0xd5, 0xac, 0x1b, 0x50, 0x4e, 0x92, 0x9d, 0xb4, 0x50, 0xc0, 0x64, 0xbd,
+       0x60, 0xd8, 0x43, 0xad, 0xc9, 0xf6, 0xf6, 0xb2, 0x87, 0x6c, 0xd8, 0x83,
+       0x81, 0x0d, 0x98, 0x63, 0x05, 0x68, 0x96, 0x02, 0x49, 0x87, 0x15, 0x43,
+       0x1e, 0x36, 0x70, 0xff, 0xdf, 0x77, 0x21, 0x0f, 0x0f, 0x0f, 0x75, 0x89,
+       0x9d, 0x01, 0x33, 0x60, 0x88, 0xe7, 0x9c, 0xef, 0x9c, 0xf3, 0x7d, 0xff,
+       0xef, 0x7f, 0xbf, 0x9d, 0x3a, 0x3f, 0x8f, 0xd8, 0xc3, 0xdc, 0xca, 0x5b,
+       0x0c, 0x8b, 0xbb, 0x42, 0x96, 0xcd, 0xe5, 0x69, 0x28, 0x48, 0xd8, 0x0f,
+       0x0a, 0x30, 0x0c, 0x44, 0x6e, 0x86, 0x8c, 0xcd, 0x47, 0xc5, 0xbe, 0x4a,
+       0x5e, 0x71, 0xcc, 0x95, 0x5b, 0x51, 0xdb, 0x5b, 0x99, 0x73, 0x21, 0xf7,
+       0x42, 0xe6, 0x85, 0x00, 0x9e, 0xab, 0x17, 0x8f, 0x3b, 0x32, 0x2f, 0x64,
+       0x64, 0x01, 0xe7, 0xfa, 0x3d, 0x72, 0xae, 0x9d, 0x71, 0x00, 0x39, 0x44,
+       0xc8, 0x05, 0xc7, 0x9c, 0x85, 0x5f, 0xc3, 0x37, 0x2e, 0xbd, 0x3d, 0xff,
+       0xaa, 0x7c, 0xe7, 0xb0, 0x78, 0xe7, 0x2e, 0xc5, 0xb3, 0x74, 0x0e, 0x78,
+       0x3c, 0x30, 0x93, 0x1f, 0x8d, 0x04, 0x19, 0xbf, 0x67, 0xca, 0xb0, 0xa5,
+       0x9b, 0xe9, 0x6b, 0x1b, 0xc1, 0x33, 0xd1, 0x00, 0xcf, 0x7a, 0x9a, 0x60,
+       0xdb, 0xbb, 0xca, 0xbb, 0x25, 0xec, 0xe4, 0x79, 0xe4, 0xb7, 0xeb, 0xfc,
+       0x04, 0x09, 0xbb, 0x2a, 0x0d, 0x5d, 0x73, 0xe7, 0x26, 0xd4, 0x60, 0x77,
+       0xa6, 0x0a, 0xbb, 0xdd, 0xff, 0x8f, 0x60, 0x77, 0x4f, 0xe8, 0xba, 0x6f,
+       0x95, 0x91, 0x83, 0xa6, 0xe5, 0xbd, 0xae, 0x5d, 0x02, 0x1c, 0xc1, 0x4f,
+       0xed, 0xd2, 0x2a, 0x81, 0xa7, 0x22, 0x6f, 0xb8, 0x52, 0xf9, 0x41, 0xbc,
+       0xea, 0x93, 0x64, 0x1b, 0x04, 0xb6, 0x08, 0x7c, 0x77, 0xcd, 0x65, 0xe4,
+       0xf1, 0x8f, 0x25, 0x23, 0xa1, 0x17, 0x79, 0x6d, 0x91, 0x1f, 0xf5, 0xb8,
+       0x6d, 0x91, 0xe3, 0xdb, 0xb4, 0x45, 0x2e, 0x48, 0x5b, 0x24, 0xbb, 0x75,
+       0x5b, 0x64, 0xa0, 0x21, 0x5f, 0xab, 0xb6, 0x9e, 0xed, 0xdb, 0x22, 0xc6,
+       0x86, 0xb6, 0xc8, 0x88, 0xcb, 0xef, 0x82, 0xf9, 0xfe, 0x2e, 0x65, 0x4f,
+       0x80, 0xc7, 0x69, 0x38, 0x03, 0xc6, 0x27, 0x3c, 0x3e, 0xe0, 0x4f, 0x12,
+       0xd6, 0xe6, 0x8e, 0xff, 0x5b, 0x58, 0x0f, 0x36, 0xf8, 0xb7, 0x6b, 0xeb,
+       0xa1, 0xf0, 0xce, 0x6d, 0xe9, 0xec, 0x5e, 0x58, 0x0f, 0x36, 0xf5, 0x93,
+       0x36, 0xcf, 0x45, 0xac, 0xf7, 0x93, 0x0e, 0x1b, 0xcd, 0x78, 0xfb, 0x77,
+       0x5d, 0xfe, 0x53, 0x37, 0x7f, 0x07, 0x4d, 0x51, 0xe0, 0xf8, 0xa8, 0x7e,
+       0x17, 0x68, 0xc9, 0xce, 0x66, 0x09, 0xf6, 0x11, 0xde, 0x17, 0x11, 0xb4,
+       0xe6, 0xd1, 0xb7, 0xf8, 0x7d, 0xbc, 0xbe, 0xd7, 0x9e, 0x15, 0x72, 0x4a,
+       0xfa, 0x1a, 0x30, 0x3e, 0x16, 0x38, 0x2b, 0xc6, 0xca, 0xdc, 0x24, 0xe5,
+       0x7b, 0x50, 0x7a, 0x7e, 0x33, 0x9f, 0x43, 0xa3, 0xcc, 0xdb, 0x9e, 0x5d,
+       0xa0, 0x69, 0x7c, 0x1f, 0xef, 0x4b, 0xa4, 0xce, 0xae, 0x02, 0xff, 0xbc,
+       0xc0, 0x7a, 0xc1, 0x70, 0x55, 0x27, 0xa8, 0xdf, 0x9b, 0xcb, 0xc2, 0x7e,
+       0xd3, 0xbc, 0x33, 0x2d, 0xf2, 0xdd, 0x24, 0xef, 0x84, 0x9e, 0xa6, 0x79,
+       0xa7, 0x57, 0x0f, 0xde, 0xe7, 0x83, 0x17, 0xbe, 0x75, 0xa7, 0x7a, 0xef,
+       0x2c, 0xe4, 0x8f, 0xa7, 0x7c, 0xf7, 0xae, 0x5a, 0x77, 0x95, 0xad, 0x8d,
+       0x95, 0xf7, 0xa7, 0xc4, 0xba, 0xa2, 0x4f, 0x27, 0x51, 0x13, 0x57, 0xad,
+       0x09, 0xf2, 0xd6, 0x41, 0x41, 0x0e, 0x68, 0x3a, 0xd4, 0x75, 0xe2, 0x80,
+       0x45, 0xcc, 0xa7, 0x0e, 0xca, 0x2d, 0x4b, 0x70, 0x9f, 0x17, 0x16, 0x35,
+       0x39, 0x32, 0xa7, 0xe4, 0xc8, 0xa2, 0x8b, 0x8f, 0x37, 0xea, 0xed, 0x7d,
+       0x3e, 0x7a, 0xbb, 0xbb, 0xb6, 0x43, 0xd4, 0xb8, 0x35, 0xa9, 0xed, 0xf0,
+       0xab, 0x99, 0xc2, 0xd8, 0x17, 0x59, 0x5f, 0xf9, 0x14, 0xf4, 0x15, 0x13,
+       0x35, 0x4b, 0x52, 0x67, 0xc1, 0x75, 0x96, 0x49, 0xaf, 0x45, 0x18, 0xa7,
+       0x8e, 0xd1, 0x79, 0xd6, 0xc9, 0x6f, 0xd2, 0xe3, 0xca, 0x66, 0x4b, 0xb8,
+       0xf2, 0x4c, 0x91, 0xdf, 0x1f, 0xa0, 0xec, 0xb3, 0x76, 0x2c, 0x41, 0xc7,
+       0xe8, 0x9c, 0xc8, 0x99, 0x41, 0xcc, 0x0f, 0x79, 0x08, 0x07, 0xc5, 0x3c,
+       0xa5, 0x7f, 0xe3, 0x51, 0xe4, 0xcd, 0x6d, 0x3d, 0x67, 0x5f, 0xd7, 0xfa,
+       0x25, 0xc5, 0x3b, 0x97, 0x15, 0xed, 0x89, 0x73, 0x7c, 0xff, 0x8b, 0x46,
+       0xe3, 0xfd, 0x09, 0x23, 0x55, 0x4e, 0x19, 0xc9, 0x25, 0x8c, 0x7b, 0xd1,
+       0x98, 0x2e, 0xc3, 0xd6, 0xd4, 0xb8, 0x64, 0xc7, 0x41, 0x97, 0x6b, 0xb4,
+       0x79, 0x7c, 0x62, 0x91, 0x3c, 0xf5, 0x13, 0x5b, 0x98, 0xf7, 0x91, 0xba,
+       0x79, 0x6b, 0xf8, 0xe2, 0x37, 0x7c, 0x40, 0x09, 0x86, 0xa9, 0xd6, 0x7f,
+       0x3b, 0xe0, 0x73, 0x8f, 0x65, 0x69, 0x23, 0xfd, 0xd7, 0x6e, 0xd0, 0x7f,
+       0x17, 0x37, 0x9d, 0xf7, 0xc3, 0xf2, 0x02, 0x59, 0xc3, 0x1d, 0x74, 0x84,
+       0x9e, 0xcb, 0xf3, 0xae, 0xd3, 0x81, 0x3d, 0x38, 0x85, 0x31, 0xda, 0x37,
+       0xae, 0x7d, 0x63, 0x3d, 0x2a, 0x1f, 0x58, 0xe7, 0x2c, 0x74, 0x28, 0x3c,
+       0xc6, 0x75, 0xd8, 0x62, 0xab, 0x3c, 0x3f, 0xd8, 0x65, 0x4f, 0x8a, 0x39,
+       0xb2, 0x5d, 0x66, 0x4d, 0x93, 0xf4, 0x7f, 0x9f, 0x2d, 0xd7, 0xd5, 0x8f,
+       0xfa, 0xd4, 0x51, 0x0e, 0xfb, 0xd4, 0x51, 0xba, 0x69, 0x32, 0xe4, 0xa2,
+       0xc9, 0x88, 0x4b, 0xbf, 0x8b, 0xb2, 0x7d, 0xd3, 0xc5, 0xbc, 0x06, 0xf6,
+       0x4d, 0x07, 0x05, 0x5f, 0x71, 0xdb, 0x37, 0xde, 0xba, 0x7d, 0xd0, 0x27,
+       0x74, 0x38, 0x69, 0xeb, 0xa4, 0x8a, 0xd5, 0x9a, 0x7f, 0x5e, 0x77, 0xad,
+       0x66, 0x71, 0xa9, 0xa1, 0xbe, 0xd2, 0x6f, 0xbe, 0x43, 0x0d, 0xf3, 0x85,
+       0x9c, 0x4b, 0x34, 0xd5, 0xfd, 0xfc, 0xec, 0xaf, 0x47, 0x35, 0x3f, 0x2f,
+       0xdf, 0xc3, 0xbb, 0x86, 0x85, 0x1f, 0x3c, 0x5b, 0xe5, 0x79, 0x93, 0x72,
+       0xbe, 0xf9, 0x7a, 0x7b, 0x24, 0x78, 0x8d, 0x14, 0xec, 0xfc, 0x65, 0xc0,
+       0xf6, 0x7c, 0x6a, 0x9d, 0x1e, 0xf9, 0x3c, 0xd1, 0x2b, 0x7d, 0x65, 0x2d,
+       0x2a, 0xd7, 0x7a, 0x97, 0xb2, 0x0b, 0x37, 0xc3, 0x77, 0x9c, 0x6b, 0x51,
+       0xfe, 0x45, 0xdb, 0x2a, 0x11, 0xf0, 0xfc, 0xc4, 0xe9, 0x16, 0xc7, 0x54,
+       0xf1, 0x2d, 0xc4, 0xb0, 0x80, 0xf7, 0xfa, 0xf9, 0xb2, 0xd6, 0x6a, 0xf3,
+       0x3d, 0xb3, 0x1a, 0xf6, 0x4c, 0xe2, 0x15, 0x6c, 0x32, 0xe4, 0x10, 0x8f,
+       0x79, 0xf2, 0xb8, 0x1f, 0x06, 0x16, 0x3d, 0x3e, 0xb9, 0xcd, 0xc8, 0x4d,
+       0x6e, 0x36, 0xcf, 0xfb, 0x2e, 0xfd, 0x1d, 0xf3, 0xad, 0x54, 0xde, 0x8c,
+       0x0f, 0x48, 0x99, 0x5d, 0xf6, 0xd7, 0xa5, 0xcc, 0x2d, 0xcf, 0xcf, 0x2b,
+       0xa3, 0xf7, 0x6c, 0x51, 0x46, 0x8b, 0x7e, 0x28, 0x81, 0xc3, 0x82, 0x07,
+       0xa0, 0x06, 0x1b, 0x39, 0xd6, 0x9f, 0x06, 0xcd, 0x33, 0x9f, 0x75, 0xd5,
+       0xaa, 0xf9, 0xef, 0x63, 0x35, 0xce, 0x12, 0x42, 0x2f, 0x88, 0x09, 0xe4,
+       0x9b, 0xf4, 0x31, 0xef, 0xc1, 0xf8, 0xfd, 0xd6, 0x1d, 0xf8, 0x80, 0x95,
+       0x9f, 0x2a, 0xa5, 0xe4, 0xcb, 0xe1, 0x2d, 0xc4, 0x5b, 0xb6, 0xc7, 0xa7,
+       0x6d, 0x6b, 0x95, 0x10, 0x0b, 0x42, 0x4e, 0xf0, 0x0b, 0x3d, 0xd4, 0x73,
+       0xaa, 0xad, 0xcd, 0xb9, 0xdb, 0x2b, 0xe3, 0x53, 0xb8, 0xd6, 0x45, 0x37,
+       0x8a, 0xc8, 0xd7, 0xc6, 0xb5, 0xdf, 0xe3, 0x6b, 0x7e, 0x3c, 0x4a, 0xe7,
+       0x9b, 0x43, 0xe7, 0x93, 0xfb, 0x53, 0x22, 0xd8, 0x54, 0x15, 0xfa, 0xa7,
+       0xf8, 0xaf, 0xc8, 0x18, 0x47, 0xf9, 0x51, 0xc7, 0x6f, 0xfc, 0xfc, 0x8a,
+       0x46, 0xdf, 0xc7, 0xcd, 0x97, 0xfc, 0xf2, 0x96, 0xfc, 0x8a, 0xc8, 0xbb,
+       0xdf, 0x4a, 0x1c, 0x45, 0xc7, 0x8b, 0x27, 0x44, 0xed, 0xa9, 0x1b, 0x0f,
+       0x1e, 0x4d, 0xcc, 0x18, 0xf8, 0x30, 0xd4, 0xc0, 0xab, 0x1e, 0x3e, 0x06,
+       0xe0, 0x85, 0x6b, 0x87, 0xaf, 0x4f, 0xcb, 0x3f, 0x36, 0x8c, 0x3c, 0x00,
+       0xf8, 0xb3, 0x9f, 0xa2, 0xb3, 0xd7, 0x81, 0xc3, 0x06, 0x63, 0xdb, 0x08,
+       0xcd, 0x86, 0x51, 0x57, 0x24, 0x6a, 0x73, 0x54, 0x2c, 0x51, 0xd6, 0x0a,
+       0x9d, 0x15, 0x75, 0x8f, 0xfb, 0x23, 0xeb, 0x94, 0x66, 0xb9, 0x97, 0xa5,
+       0x73, 0x2c, 0x63, 0xcf, 0x2d, 0xd5, 0x74, 0xfc, 0xc6, 0xda, 0xc7, 0x7a,
+       0x1c, 0x5f, 0x17, 0x38, 0x1e, 0xdd, 0x10, 0xc7, 0x8f, 0x56, 0x71, 0x7c,
+       0xae, 0x4f, 0xe2, 0xf3, 0x45, 0x7e, 0x56, 0x0f, 0x1d, 0x16, 0xcf, 0xcd,
+       0xf2, 0xef, 0x4e, 0x3a, 0x2c, 0xfb, 0x62, 0xf0, 0xbb, 0x99, 0xc7, 0xe7,
+       0xb3, 0x74, 0xfe, 0x7a, 0x36, 0x90, 0x12, 0x35, 0x0a, 0xee, 0xbe, 0x1e,
+       0xfa, 0x7e, 0x8c, 0x6b, 0x86, 0xff, 0x9a, 0x2f, 0xc9, 0x9a, 0xab, 0x92,
+       0xe4, 0x4f, 0xf4, 0x76, 0x7c, 0xd0, 0x83, 0xff, 0xf5, 0x36, 0xe6, 0x05,
+       0x25, 0x03, 0x4f, 0x6c, 0xe0, 0xff, 0x68, 0xc4, 0xcb, 0x5e, 0x1f, 0xbd,
+       0xf9, 0x8d, 0x3e, 0x19, 0xbb, 0xda, 0xc8, 0xff, 0xe1, 0xc6, 0xd1, 0xba,
+       0x58, 0x3e, 0xf3, 0xfd, 0x84, 0xaa, 0xff, 0x7b, 0xa7, 0x4f, 0xca, 0x0b,
+       0xd4, 0x04, 0xa6, 0x19, 0x0e, 0x6f, 0xb2, 0xae, 0x32, 0x48, 0xad, 0xaf,
+       0xe8, 0xb5, 0x0e, 0x0a, 0x7e, 0xeb, 0xf6, 0xe7, 0x5c, 0x56, 0xb5, 0xe0,
+       0x39, 0xd7, 0x9a, 0x2e, 0x0b, 0x5b, 0xa8, 0x39, 0xbd, 0x35, 0xcf, 0xc3,
+       0x8a, 0x7a, 0x64, 0x82, 0x17, 0xdf, 0xd0, 0x2f, 0x05, 0xfb, 0x4b, 0x86,
+       0xd4, 0x83, 0x27, 0x59, 0xbf, 0xdd, 0x6e, 0x0c, 0xe9, 0x61, 0x75, 0x44,
+       0x6f, 0x4f, 0x0e, 0xef, 0x6f, 0xec, 0x83, 0xb4, 0x39, 0x32, 0xaf, 0x3d,
+       0x25, 0x78, 0xc1, 0xe5, 0xb1, 0x0a, 0x4d, 0xc7, 0xbb, 0x29, 0x33, 0xc6,
+       0xef, 0x9e, 0x44, 0x4f, 0xac, 0x20, 0x65, 0x99, 0x7e, 0x33, 0x63, 0x8f,
+       0x29, 0x7d, 0x51, 0xfb, 0xdd, 0xdb, 0x54, 0xee, 0xc3, 0x45, 0x11, 0xab,
+       0x94, 0xfd, 0x84, 0xf8, 0xf7, 0x92, 0x7e, 0xf6, 0x45, 0x11, 0x33, 0xcd,
+       0x5c, 0x6f, 0x55, 0xe3, 0x3a, 0x5d, 0xe3, 0x30, 0xa6, 0x53, 0x8d, 0xc5,
+       0x33, 0xb5, 0x4e, 0xd1, 0xae, 0xf8, 0x2d, 0xe8, 0x30, 0xad, 0x6a, 0xf5,
+       0x70, 0xfd, 0x02, 0xcd, 0x54, 0xd7, 0xd2, 0xc9, 0x63, 0xff, 0x5b, 0xf5,
+       0xf2, 0xe8, 0x64, 0x9d, 0x17, 0xf3, 0x6e, 0x9c, 0x13, 0xd6, 0x12, 0x14,
+       0x71, 0x24, 0xfe, 0xad, 0xde, 0x73, 0xa6, 0x3a, 0x27, 0xe4, 0x6d, 0xd8,
+       0x11, 0xf9, 0x2c, 0x3d, 0xae, 0xd3, 0x35, 0x4e, 0xf3, 0x0a, 0x1d, 0xa7,
+       0xf8, 0x57, 0x9e, 0xc7, 0x3f, 0xa8, 0xbc, 0x5e, 0x53, 0xc4, 0x54, 0x65,
+       0xde, 0x86, 0xfe, 0x0d, 0x3f, 0x34, 0xf2, 0x2c, 0x90, 0x3b, 0xe1, 0xe6,
+       0x37, 0x72, 0xbd, 0x21, 0xc8, 0xa2, 0x32, 0x62, 0xa9, 0x88, 0x6b, 0x34,
+       0xd3, 0x9d, 0xf7, 0x20, 0x5f, 0x7f, 0x1b, 0x3a, 0xe8, 0x56, 0xe8, 0xcf,
+       0xf2, 0xa1, 0x3f, 0xf7, 0xfb, 0x51, 0xeb, 0x86, 0x9a, 0xb7, 0x6c, 0xcc,
+       0xa0, 0x0a, 0xdb, 0x0a, 0x06, 0x95, 0xcc, 0x00, 0x9d, 0x77, 0xec, 0xf8,
+       0x12, 0xc9, 0x9a, 0xc9, 0xe9, 0x79, 0x3b, 0xb6, 0x4a, 0x87, 0xcc, 0x73,
+       0x24, 0x7b, 0x25, 0x94, 0x58, 0x06, 0x9f, 0xa1, 0x18, 0xdb, 0x47, 0x6c,
+       0x7f, 0x9e, 0x42, 0x5c, 0x46, 0xef, 0x0b, 0x6a, 0xe3, 0xf1, 0x37, 0xc6,
+       0x70, 0xba, 0xb9, 0x93, 0x3a, 0x12, 0xfc, 0xcc, 0x18, 0xf8, 0x13, 0x3f,
+       0x27, 0x4d, 0x49, 0xb6, 0x93, 0x60, 0xb3, 0x9e, 0x39, 0x65, 0x9b, 0x25,
+       0x32, 0x78, 0x2c, 0x6c, 0x57, 0x3c, 0x07, 0xf7, 0x27, 0xcc, 0x16, 0xf2,
+       0xd6, 0xe1, 0x5e, 0x14, 0x75, 0x8a, 0x6f, 0xc7, 0x0f, 0x92, 0xd1, 0x0f,
+       0x7e, 0x85, 0x7d, 0x1b, 0x55, 0xf1, 0xa4, 0x4b, 0xfc, 0xdb, 0x51, 0xbf,
+       0xbf, 0x2a, 0xea, 0xdd, 0xe4, 0x6f, 0xe0, 0xf6, 0x2f, 0xab, 0x3d, 0xab,
+       0xcb, 0x09, 0x89, 0x8c, 0x18, 0x5f, 0xa5, 0x0b, 0x4b, 0x1b, 0xf9, 0x66,
+       0xfc, 0xea, 0x5b, 0xbb, 0xb6, 0x58, 0xdf, 0xba, 0xbe, 0x53, 0xd6, 0x8c,
+       0xe1, 0xfd, 0x7e, 0xba, 0x97, 0x77, 0x6d, 0xee, 0x7a, 0xd5, 0xef, 0xd0,
+       0xb4, 0xac, 0x35, 0x56, 0xb8, 0x70, 0xbd, 0x89, 0x7f, 0xf3, 0x49, 0x21,
+       0x2f, 0xcf, 0xca, 0x38, 0xc3, 0x80, 0xec, 0x6d, 0x16, 0xa2, 0xe5, 0x6a,
+       0xed, 0x67, 0x50, 0xd5, 0x7f, 0x30, 0x53, 0x7c, 0xa4, 0x75, 0x9f, 0x3a,
+       0x57, 0x15, 0x71, 0xa7, 0xb4, 0x2b, 0x8f, 0x22, 0xa4, 0xf2, 0x24, 0x70,
+       0xdf, 0x48, 0x18, 0x75, 0x5b, 0xb2, 0xd6, 0x12, 0x63, 0x50, 0xe7, 0x08,
+       0x1b, 0x12, 0x75, 0xae, 0xf0, 0xfb, 0x35, 0xab, 0x05, 0xc5, 0x78, 0xf8,
+       0x9f, 0xb4, 0x5d, 0x78, 0x5a, 0xd0, 0x98, 0x7c, 0xa7, 0xac, 0xd9, 0x5c,
+       0x5c, 0x39, 0x23, 0xea, 0x24, 0x93, 0xaa, 0xf6, 0x33, 0x43, 0x5d, 0x42,
+       0x6f, 0xfa, 0xf8, 0x35, 0x9b, 0xe7, 0xc2, 0xdb, 0xaf, 0xd9, 0x74, 0xdf,
+       0xb3, 0xbd, 0x9a, 0x4d, 0x93, 0xd7, 0x6e, 0x2c, 0xc8, 0x9a, 0xcd, 0xfa,
+       0x58, 0x80, 0xf4, 0x43, 0x65, 0x5c, 0xf2, 0x48, 0xea, 0x7f, 0x5f, 0x72,
+       0xe5, 0x08, 0xcb, 0x7a, 0xcc, 0xc5, 0xaa, 0x0e, 0x24, 0xeb, 0x31, 0x65,
+       0x4e, 0xb1, 0xbb, 0x0f, 0x89, 0x8c, 0x39, 0xc8, 0xf7, 0x74, 0x7b, 0x62,
+       0x0e, 0x2d, 0x4c, 0xa3, 0xa3, 0xaa, 0xe6, 0xbc, 0x19, 0x6e, 0xd6, 0xd9,
+       0x2a, 0x4c, 0x73, 0x15, 0xfa, 0x69, 0xfc, 0xd3, 0x74, 0x3f, 0x1c, 0x51,
+       0xb9, 0x74, 0xc8, 0x9d, 0x3b, 0xa8, 0xe0, 0xa8, 0xf5, 0x0f, 0xf2, 0xd1,
+       0x3f, 0x7e, 0x5b, 0xe4, 0x10, 0x4b, 0xfd, 0x65, 0x50, 0xd1, 0x24, 0xe8,
+       0x36, 0xe2, 0xa2, 0xdb, 0x5d, 0x4d, 0xe8, 0x16, 0xf4, 0xf9, 0xdd, 0x1d,
+       0xb2, 0x4f, 0x01, 0xe2, 0xde, 0xdf, 0x57, 0xbf, 0x37, 0xa3, 0xbf, 0xf7,
+       0x78, 0x6f, 0x40, 0x83, 0x78, 0xc6, 0x87, 0xe1, 0x1a, 0x1d, 0xea, 0xdf,
+       0x98, 0xcb, 0x7e, 0xd7, 0x5c, 0x86, 0x5d, 0x73, 0xd9, 0xd7, 0x64, 0x2e,
+       0xac, 0x4f, 0x94, 0x2f, 0xf0, 0xff, 0x8f, 0x3b, 0x27, 0xe1, 0xab, 0x65,
+       0x5a, 0x8d, 0x0b, 0xf9, 0x9a, 0x03, 0x1c, 0x85, 0x9e, 0x32, 0xaa, 0xea,
+       0xe0, 0xdd, 0xf3, 0x6c, 0x66, 0xab, 0x41, 0x16, 0xa0, 0xd7, 0x41, 0x82,
+       0xef, 0xeb, 0x6c, 0xd2, 0xeb, 0x00, 0x3a, 0x86, 0x5f, 0xaf, 0x03, 0x37,
+       0x8f, 0x77, 0xeb, 0x52, 0xd0, 0x7d, 0x21, 0x03, 0xa1, 0xf3, 0xa2, 0x57,
+       0xc1, 0x2f, 0xd1, 0x85, 0xaa, 0x8e, 0x79, 0x90, 0xd2, 0x4a, 0xc7, 0xbc,
+       0xb0, 0xa4, 0xf7, 0x7c, 0xd8, 0xb3, 0xe7, 0x7e, 0x3a, 0xe7, 0x90, 0xca,
+       0xf1, 0xd1, 0xb0, 0xca, 0xba, 0x60, 0x95, 0xf5, 0x81, 0x95, 0x78, 0x47,
+       0x93, 0x79, 0x03, 0x3e, 0xb8, 0x07, 0xff, 0xbf, 0x13, 0x41, 0x8f, 0x16,
+       0xa2, 0xdf, 0xd8, 0x55, 0xf3, 0x0b, 0xe8, 0xdf, 0x98, 0x63, 0xd3, 0xdc,
+       0x4f, 0xa5, 0x0f, 0x0e, 0x06, 0x8e, 0x5c, 0x67, 0x03, 0x9d, 0x65, 0x5e,
+       0xbd, 0x2d, 0xa8, 0x75, 0x85, 0x03, 0x82, 0xef, 0xdd, 0x0f, 0x22, 0x77,
+       0x45, 0x9f, 0xeb, 0xd6, 0xbe, 0x5c, 0xb5, 0xfe, 0xd6, 0x3a, 0x7d, 0xa2,
+       0xa6, 0x4b, 0xe8, 0x1c, 0x54, 0xfd, 0x5b, 0xcb, 0xc0, 0x7b, 0x75, 0xfe,
+       0x89, 0x5b, 0x75, 0xfd, 0x06, 0xe1, 0x0b, 0xea, 0x4e, 0x1b, 0x4e, 0x4a,
+       0xe4, 0x91, 0xf6, 0x3a, 0xf0, 0x7b, 0x25, 0x99, 0x37, 0xf7, 0xa6, 0x91,
+       0xb3, 0xdc, 0x7b, 0xcd, 0xa2, 0x93, 0xf9, 0x2f, 0xed, 0x95, 0x74, 0x7a,
+       0x89, 0x86, 0xc7, 0x79, 0xfc, 0x14, 0x7c, 0xbd, 0x76, 0x2c, 0xc9, 0x4a,
+       0xe4, 0x5c, 0xb9, 0x8d, 0x16, 0x59, 0x5b, 0x0f, 0x3a, 0x25, 0xe1, 0xbb,
+       0x63, 0x99, 0x51, 0x40, 0x6f, 0x55, 0x63, 0xa1, 0x95, 0x9f, 0xdb, 0x4f,
+       0xcb, 0x45, 0xd0, 0x7c, 0x8b, 0xea, 0x11, 0x82, 0xb1, 0x01, 0xea, 0x73,
+       0xfe, 0x84, 0xe1, 0xf5, 0x05, 0x91, 0x47, 0xb9, 0x58, 0xb8, 0x24, 0xff,
+       0x96, 0x5e, 0x52, 0xef, 0xe0, 0xf7, 0x95, 0xff, 0x86, 0x12, 0x7d, 0x96,
+       0xcb, 0x36, 0x73, 0xff, 0xf3, 0xd7, 0x3f, 0x8e, 0x6f, 0x4b, 0xff, 0xc8,
+       0xa6, 0x6b, 0xfa, 0x87, 0xfb, 0xd9, 0x5a, 0x17, 0x39, 0xd6, 0x2f, 0xfb,
+       0x37, 0x00, 0x06, 0x9d, 0xd0, 0xad, 0xd2, 0x80, 0xa5, 0x31, 0x65, 0x47,
+       0x92, 0xc1, 0x49, 0x9a, 0x2d, 0x47, 0x8d, 0x4c, 0x01, 0x3a, 0x30, 0xff,
+       0x2d, 0x5d, 0xd9, 0x2d, 0x7d, 0x2e, 0xfa, 0x1e, 0xf0, 0xf5, 0x9d, 0x3c,
+       0xfe, 0x3f, 0xfa, 0x65, 0xee, 0xb5, 0xfb, 0x7c, 0x0f, 0x9f, 0x7f, 0x2e,
+       0x52, 0x7f, 0xfe, 0x31, 0x3e, 0xdf, 0xc7, 0xe7, 0xe1, 0x87, 0x84, 0x9f,
+       0x31, 0x46, 0x39, 0xde, 0x9f, 0xd9, 0x32, 0xf3, 0xa9, 0x57, 0x58, 0x5e,
+       0x2c, 0xe9, 0x71, 0xbb, 0x50, 0x97, 0x23, 0xf6, 0xc4, 0xe0, 0x31, 0x97,
+       0xf3, 0x63, 0x3c, 0x6e, 0x90, 0x82, 0xaf, 0x58, 0x34, 0xbb, 0xa4, 0x71,
+       0x52, 0xe7, 0xd4, 0xbf, 0xc3, 0xf0, 0x45, 0xde, 0xce, 0x47, 0xbb, 0x25,
+       0xfc, 0x62, 0xc2, 0x87, 0x89, 0x3c, 0x8e, 0x2b, 0x02, 0xf7, 0xec, 0x49,
+       0xab, 0xfa, 0x7e, 0xe0, 0x96, 0x88, 0x73, 0xf0, 0x1a, 0x58, 0x2e, 0x4d,
+       0x39, 0x66, 0xae, 0x9a, 0x8f, 0xf6, 0xe7, 0x03, 0xf2, 0xfe, 0xff, 0xda,
+       0x25, 0xfb, 0xa3, 0xbe, 0x3f, 0xa0, 0xfb, 0x24, 0x4a, 0x9d, 0x00, 0x39,
+       0xca, 0x01, 0x01, 0x9b, 0xe0, 0x02, 0xe4, 0x95, 0xc1, 0xbf, 0x79, 0x3d,
+       0x69, 0xcc, 0xb1, 0xad, 0x5f, 0xf7, 0x7c, 0x91, 0xeb, 0x3a, 0xc6, 0xf3,
+       0x4d, 0xf1, 0xba, 0xf4, 0xf9, 0x04, 0x1f, 0xfb, 0xed, 0x2f, 0x9e, 0xd5,
+       0x91, 0x46, 0x5d, 0x70, 0xe6, 0x54, 0x47, 0x3a, 0x13, 0x93, 0xfb, 0x5c,
+       0xf3, 0xd1, 0x46, 0xaa, 0x3e, 0xda, 0xb9, 0xfc, 0x78, 0x3f, 0xfc, 0x15,
+       0xc6, 0x35, 0xde, 0xef, 0xf0, 0x15, 0x1e, 0x8b, 0x7a, 0x84, 0x1c, 0xff,
+       0xed, 0x52, 0xf9, 0x3c, 0x8d, 0xb8, 0x22, 0xf3, 0x23, 0xb4, 0x5e, 0x81,
+       0x7b, 0x9f, 0xe0, 0x67, 0x48, 0xdd, 0xa2, 0xf9, 0x7b, 0xa8, 0x21, 0xff,
+       0xa5, 0x11, 0xc7, 0x36, 0xf2, 0xab, 0x8a, 0x38, 0xa2, 0x0f, 0x9e, 0x6d,
+       0xd4, 0x83, 0xe0, 0x9e, 0xf0, 0x8b, 0x4d, 0x37, 0xd0, 0x2b, 0xe8, 0x38,
+       0x44, 0x2f, 0xcc, 0x67, 0xe9, 0x31, 0xde, 0xab, 0x3f, 0x30, 0x3e, 0x83,
+       0x38, 0x3b, 0xc9, 0x5c, 0x27, 0x86, 0x71, 0xde, 0x89, 0x9d, 0x33, 0x52,
+       0xe0, 0x8b, 0x95, 0x90, 0xd3, 0x45, 0xad, 0x4c, 0xab, 0xbf, 0x49, 0x23,
+       0x6c, 0xcf, 0x81, 0x66, 0x9d, 0x48, 0x8a, 0x40, 0x6f, 0xb6, 0x79, 0x84,
+       0x71, 0x62, 0xba, 0x0c, 0x7c, 0x36, 0xe8, 0x8b, 0x45, 0xa2, 0xe7, 0x8b,
+       0x23, 0xe6, 0xf7, 0xc8, 0xb1, 0x6a, 0xd7, 0x6d, 0x33, 0xc9, 0xf3, 0x48,
+       0x95, 0x5f, 0xa2, 0xf7, 0x44, 0xdf, 0x12, 0xc0, 0x51, 0xef, 0xfb, 0x1f,
+       0xd1, 0x99, 0x34, 0xe6, 0xbd, 0x75, 0xfa, 0x3c, 0xb9, 0x2d, 0xfa, 0xec,
+       0xf0, 0xa1, 0xcf, 0x7f, 0x54, 0x78, 0x53, 0x61, 0x1c, 0xed, 0xa0, 0x99,
+       0x02, 0x72, 0xbf, 0x3e, 0x8b, 0xfe, 0x52, 0x85, 0x0c, 0xf3, 0xa5, 0x4c,
+       0x8d, 0x2f, 0x5d, 0x4d, 0x06, 0x13, 0xa0, 0x71, 0xf4, 0x65, 0x53, 0xf9,
+       0x3e, 0x58, 0xc7, 0x00, 0x8d, 0x2c, 0x74, 0x22, 0xf6, 0xb5, 0x9a, 0x9c,
+       0x48, 0xa8, 0xfa, 0x7c, 0xdb, 0x9a, 0x66, 0xfe, 0x38, 0xc7, 0xb4, 0x9c,
+       0x2b, 0x1c, 0xa4, 0xc5, 0x70, 0x94, 0x86, 0x17, 0x74, 0xbf, 0x12, 0x11,
+       0x37, 0x89, 0x4a, 0x9e, 0xa4, 0xd7, 0xfd, 0x84, 0xf0, 0x45, 0x58, 0x37,
+       0x3f, 0xa9, 0x75, 0x77, 0x6e, 0xc2, 0x97, 0xde, 0x57, 0x34, 0x5b, 0xb9,
+       0x95, 0x8c, 0x53, 0x36, 0x39, 0xf1, 0xef, 0x02, 0xff, 0x87, 0x6f, 0xc2,
+       0xaf, 0x06, 0x1e, 0x6d, 0x51, 0x3a, 0xef, 0x85, 0x45, 0x94, 0xd7, 0x8d,
+       0xeb, 0x95, 0x0f, 0x67, 0xe2, 0x2f, 0x09, 0xdd, 0x6b, 0xe4, 0x26, 0x8f,
+       0x13, 0xf2, 0x48, 0xf3, 0x0d, 0x3f, 0x3c, 0xd4, 0x3d, 0x29, 0x35, 0x2e,
+       0xca, 0x7c, 0x4e, 0x93, 0x9f, 0x9b, 0x0e, 0x7a, 0x71, 0xf2, 0x5e, 0xe0,
+       0xf8, 0xbc, 0x45, 0x27, 0xf2, 0xf6, 0xab, 0x59, 0x9a, 0x64, 0xba, 0x76,
+       0xcb, 0x0b, 0x1e, 0x4f, 0xc0, 0xb3, 0x29, 0xd0, 0x3e, 0x65, 0x0a, 0x96,
+       0xcc, 0xb7, 0x13, 0x3d, 0xe5, 0x70, 0x8c, 0xda, 0xe2, 0xee, 0xdd, 0x5a,
+       0x1e, 0x64, 0x0a, 0xa8, 0x15, 0xe4, 0xbf, 0x25, 0x1e, 0x8f, 0xfc, 0xfe,
+       0x22, 0x9e, 0x03, 0x19, 0x87, 0xb9, 0xf3, 0xf1, 0xb2, 0xdc, 0xd7, 0x61,
+       0x7e, 0xf6, 0xc8, 0x38, 0xbf, 0xb3, 0x3c, 0xc6, 0xfb, 0xdb, 0x23, 0x78,
+       0xb3, 0xdc, 0xcf, 0x29, 0xba, 0xec, 0xcb, 0x57, 0xe4, 0xbe, 0x64, 0x5c,
+       0xf4, 0x9d, 0x11, 0xf4, 0x3d, 0x25, 0xf6, 0x23, 0x53, 0x34, 0x58, 0x5f,
+       0xd6, 0xbe, 0x04, 0xb6, 0x9b, 0x8b, 0x21, 0xc5, 0x43, 0x70, 0xed, 0x89,
+       0xdd, 0x22, 0x1f, 0x11, 0xf6, 0x74, 0x11, 0x7f, 0xa7, 0xe8, 0x0a, 0xeb,
+       0xfd, 0x2f, 0xe7, 0xdb, 0xe8, 0x4e, 0xa1, 0x8d, 0xee, 0x16, 0xa2, 0x74,
+       0x7b, 0x7e, 0x07, 0x5d, 0x66, 0x9b, 0xe6, 0xb2, 0x13, 0xb2, 0x72, 0xb4,
+       0x03, 0xf1, 0x42, 0xe4, 0x0a, 0x31, 0xdd, 0x61, 0x3c, 0xf4, 0xef, 0xe4,
+       0x1e, 0xc6, 0x39, 0xb6, 0x8d, 0xda, 0xe9, 0x5d, 0x7e, 0x67, 0x2e, 0xaf,
+       0x73, 0x1c, 0xe0, 0x63, 0xdf, 0x5f, 0xb5, 0x1f, 0x36, 0xc7, 0x11, 0x73,
+       0x13, 0x1c, 0x99, 0x12, 0xbc, 0x7e, 0x76, 0x3e, 0x8a, 0xbe, 0xca, 0xd9,
+       0x16, 0xf8, 0x49, 0x99, 0x3f, 0x3f, 0x17, 0xc2, 0x78, 0x9c, 0x73, 0x64,
+       0x8e, 0xa4, 0x58, 0x5b, 0x84, 0x8f, 0x03, 0xa2, 0x0e, 0x5a, 0xc2, 0xa1,
+       0x9d, 0xd7, 0x17, 0x10, 0xe3, 0x33, 0xcb, 0xed, 0x74, 0xb6, 0x68, 0xf2,
+       0x71, 0x90, 0xf5, 0x44, 0x8c, 0xed, 0xdd, 0xa7, 0xfb, 0xcb, 0x5e, 0xe6,
+       0xb9, 0xe7, 0xc4, 0x38, 0xfe, 0xbb, 0xdc, 0x43, 0xb3, 0xc5, 0x2e, 0x75,
+       0x7c, 0x50, 0xe6, 0xf2, 0x8a, 0x5c, 0x6c, 0x5c, 0xdb, 0x88, 0xbf, 0xbd,
+       0xcd, 0x38, 0x05, 0x99, 0x2a, 0x75, 0x7c, 0xf0, 0x9a, 0x5b, 0x0d, 0xfd,
+       0x90, 0x81, 0x73, 0x93, 0xf4, 0x4d, 0x96, 0xb7, 0xc3, 0xaf, 0xc0, 0x1f,
+       0xfc, 0xfb, 0xc0, 0x9b, 0x52, 0x96, 0x06, 0xf9, 0x18, 0x7d, 0x8e, 0x82,
+       0xa2, 0x96, 0x69, 0x3a, 0x1c, 0x13, 0xf5, 0x1f, 0x92, 0x46, 0x4f, 0x89,
+       0x9e, 0x73, 0x3f, 0x12, 0xbc, 0xc9, 0xce, 0x5a, 0x06, 0xf4, 0x11, 0xf8,
+       0x54, 0x64, 0xee, 0xd5, 0x49, 0xa7, 0xf7, 0xed, 0x5d, 0x53, 0xa3, 0x94,
+       0xe8, 0x07, 0xde, 0x4b, 0x9a, 0x55, 0x3d, 0x04, 0x04, 0xbf, 0x37, 0x0f,
+       0xe8, 0x9a, 0x48, 0x7d, 0xac, 0x65, 0x85, 0x3e, 0xee, 0xf2, 0x5c, 0x37,
+       0x3d, 0xd7, 0xab, 0x79, 0x72, 0x2c, 0xf3, 0x58, 0xce, 0x93, 0xec, 0x39,
+       0x84, 0xbe, 0x71, 0xc0, 0x3f, 0xf3, 0xc0, 0x7e, 0xf3, 0x73, 0xca, 0x06,
+       0xca, 0xac, 0x8c, 0x44, 0x7a, 0x8d, 0x98, 0x91, 0x19, 0xfb, 0x97, 0x4a,
+       0x22, 0x0d, 0xbd, 0xe8, 0xc6, 0x6e, 0xc9, 0xe3, 0x30, 0xaf, 0x6c, 0x1c,
+       0xaa, 0xdb, 0xa9, 0x95, 0x2e, 0x5a, 0x15, 0x7d, 0xb5, 0xa0, 0x63, 0xe0,
+       0x7e, 0x3c, 0x27, 0x6b, 0xb6, 0xb0, 0x7d, 0x77, 0xc3, 0x01, 0x8d, 0x1f,
+       0x8a, 0xdc, 0xe4, 0xfd, 0x4c, 0xad, 0x7c, 0x54, 0x39, 0x23, 0xfa, 0xd2,
+       0x60, 0x6c, 0x0f, 0xcd, 0x08, 0x9b, 0x8b, 0xf5, 0x97, 0x3a, 0xbb, 0x76,
+       0x12, 0xf3, 0xcc, 0x22, 0x56, 0x62, 0x38, 0xdf, 0x0e, 0x64, 0x4a, 0x32,
+       0xf6, 0x9d, 0xf2, 0xc4, 0xbe, 0x4f, 0x89, 0xd8, 0x37, 0xe2, 0xde, 0x80,
+       0x2b, 0x60, 0xe9, 0x97, 0xcb, 0x82, 0x7d, 0x8c, 0xf3, 0x3e, 0x5a, 0x34,
+       0x77, 0x5d, 0xf0, 0x9b, 0xc9, 0xe9, 0x60, 0xa2, 0xb7, 0x85, 0xac, 0x40,
+       0xd2, 0xb1, 0xe3, 0x0f, 0x58, 0x87, 0xb8, 0x5d, 0xc0, 0x3c, 0x5f, 0xa2,
+       0xf5, 0x52, 0x0b, 0xd3, 0x89, 0xcd, 0x78, 0xb7, 0xca, 0x3a, 0xed, 0x2c,
+       0xbd, 0x5b, 0x22, 0xba, 0x5d, 0xbc, 0x8a, 0x5e, 0xbb, 0xb1, 0x07, 0x4c,
+       0x2b, 0x88, 0x05, 0x67, 0x62, 0xf0, 0xb1, 0xb1, 0x5e, 0x1b, 0x6b, 0x55,
+       0xb8, 0xd9, 0xc5, 0xb6, 0xa3, 0xc9, 0xff, 0x1d, 0xfe, 0x1f, 0x89, 0x00,
+       0x2e, 0x6b, 0xc5, 0x31, 0xc1, 0x4b, 0x97, 0xf8, 0xfc, 0x12, 0x9f, 0x87,
+       0x4c, 0x5d, 0x2b, 0x56, 0xde, 0x49, 0xc6, 0x13, 0x56, 0x72, 0xe2, 0xa4,
+       0x1c, 0xc3, 0x38, 0x77, 0xf9, 0x7a, 0x62, 0x4f, 0x88, 0xe7, 0x31, 0xc3,
+       0xf3, 0x58, 0x27, 0x99, 0xeb, 0x9d, 0x12, 0xef, 0x26, 0xba, 0x23, 0xde,
+       0xcb, 0x3a, 0x53, 0xfc, 0x71, 0x3a, 0x13, 0x96, 0xef, 0xcf, 0xc5, 0x51,
+       0x73, 0xd5, 0x49, 0xb3, 0x63, 0xa3, 0xaa, 0xe6, 0xea, 0xcd, 0x26, 0x35,
+       0x57, 0xed, 0xb4, 0x36, 0x0f, 0xbb, 0xb7, 0x9d, 0xe9, 0xdd, 0x14, 0xb9,
+       0x7a, 0x6b, 0xf3, 0xa2, 0x1f, 0x3e, 0xaf, 0xa7, 0xb2, 0x3e, 0xc3, 0xaa,
+       0x79, 0x26, 0xde, 0x2d, 0x74, 0xa7, 0xdb, 0xcb, 0xbf, 0xc5, 0xf3, 0x49,
+       0x58, 0x99, 0x09, 0xf7, 0x3a, 0xc4, 0x7c, 0xd7, 0xa7, 0xc5, 0xb8, 0xa0,
+       0x67, 0x5c, 0x82, 0x32, 0x13, 0x98, 0xbf, 0x18, 0xf3, 0x3f, 0xc9, 0xb8,
+       0x5e, 0x8f, 0xfb, 0x7e, 0x8b, 0x72, 0x42, 0xdf, 0xe7, 0xbf, 0x4b, 0x3d,
+       0x81, 0xf5, 0x02, 0xfc, 0x26, 0x06, 0xe3, 0x3f, 0xe6, 0x66, 0x51, 0x76,
+       0x89, 0xd7, 0x75, 0xbd, 0x2b, 0xf0, 0xa0, 0xf0, 0x93, 0x4a, 0xa6, 0x2e,
+       0xb7, 0xa5, 0xde, 0xbf, 0x2e, 0x6d, 0xae, 0x28, 0x39, 0xd7, 0x20, 0x4b,
+       0x21, 0x47, 0xb3, 0x95, 0xa0, 0x03, 0xbd, 0x0f, 0xb6, 0xd0, 0x25, 0xe6,
+       0x63, 0x32, 0x3f, 0x89, 0x79, 0x2a, 0xf3, 0x32, 0x49, 0x47, 0xa9, 0xba,
+       0xcf, 0x32, 0x48, 0x5c, 0x1e, 0xae, 0xe5, 0x45, 0xba, 0xe2, 0xe6, 0x21,
+       0x57, 0xdc, 0xdc, 0x74, 0xe5, 0x45, 0x86, 0x85, 0x9e, 0x56, 0xd3, 0xad,
+       0xc2, 0x4a, 0xb7, 0x8a, 0x8a, 0x9e, 0xf4, 0xe0, 0x71, 0x8b, 0x55, 0x1e,
+       0xb7, 0x73, 0x13, 0x1e, 0xe7, 0x67, 0x9b, 0xae, 0x2a, 0x7e, 0x62, 0xc7,
+       0x21, 0x6b, 0x6e, 0x31, 0xdf, 0xf8, 0x71, 0x79, 0x82, 0xf9, 0x49, 0x9c,
+       0xf9, 0xc9, 0x18, 0xf3, 0x93, 0x18, 0xf3, 0x13, 0x87, 0x61, 0x60, 0xf1,
+       0xda, 0xef, 0x05, 0x6e, 0xcf, 0x43, 0x8e, 0x4c, 0xd2, 0x95, 0x32, 0x78,
+       0xf3, 0x18, 0xeb, 0x42, 0xf7, 0x02, 0x6b, 0xf3, 0x3d, 0x8c, 0xc7, 0x52,
+       0xff, 0xa9, 0xb7, 0x6f, 0xec, 0x57, 0x51, 0x1f, 0x97, 0x8c, 0xaf, 0x81,
+       0xff, 0xbc, 0x99, 0xa5, 0xee, 0xc0, 0xed, 0x42, 0x57, 0x60, 0xad, 0xf0,
+       0x13, 0xf4, 0xa5, 0x78, 0x1d, 0x34, 0x8e, 0xbe, 0xbf, 0x3f, 0x1c, 0x9d,
+       0xe4, 0xb9, 0x77, 0x07, 0x66, 0x79, 0x5f, 0xbe, 0x12, 0x4f, 0xf4, 0xf6,
+       0x49, 0x5a, 0xc8, 0xe6, 0xc0, 0x3d, 0x17, 0x76, 0xd0, 0xfe, 0xf1, 0xe4,
+       0x9e, 0x5e, 0xa6, 0x5b, 0xe0, 0x7b, 0xad, 0xef, 0x4e, 0x90, 0xf1, 0xb0,
+       0x43, 0xf5, 0xeb, 0xb1, 0x58, 0x5e, 0x7e, 0xc8, 0xf7, 0x7f, 0x10, 0xc8,
+       0x15, 0x5e, 0xe3, 0x67, 0xe3, 0xf8, 0x4f, 0xe1, 0xdf, 0x64, 0x7b, 0x01,
+       0xbd, 0x7e, 0x3a, 0x79, 0x0c, 0xc6, 0xe2, 0xd8, 0x8e, 0x31, 0x6f, 0x8b,
+       0xaf, 0x1a, 0xf6, 0x64, 0xc2, 0x78, 0x3e, 0x8a, 0x9e, 0xf1, 0x3f, 0x2c,
+       0x3f, 0x15, 0x95, 0x31, 0xb6, 0xe7, 0xf6, 0x48, 0x3e, 0xc2, 0xb8, 0x19,
+       0x4e, 0x08, 0x9b, 0xad, 0xe5, 0x9a, 0x94, 0x9b, 0x8b, 0xbc, 0xbf, 0x4b,
+       0xf1, 0x18, 0xef, 0x6f, 0x97, 0x92, 0x99, 0x59, 0xbe, 0x2e, 0xe4, 0x31,
+       0xcb, 0x4e, 0x86, 0x77, 0x91, 0x4c, 0xd1, 0x03, 0xe2, 0x14, 0xfa, 0xea,
+       0x3c, 0x83, 0xe7, 0x31, 0xb6, 0x82, 0x6f, 0x7c, 0x18, 0xc8, 0x14, 0xf0,
+       0x5e, 0xe0, 0x1f, 0xff, 0x2e, 0x4d, 0xd2, 0xd5, 0xbc, 0x9e, 0xc3, 0x80,
+       0x61, 0x7c, 0x13, 0xf3, 0x08, 0xd0, 0x4e, 0xe7, 0xdf, 0x18, 0x4e, 0x7c,
+       0xfc, 0x97, 0xde, 0x39, 0x9d, 0x57, 0x73, 0x42, 0x9f, 0xca, 0x36, 0x5e,
+       0xc3, 0x4e, 0x42, 0xff, 0xa2, 0x45, 0xd1, 0x47, 0xb2, 0x55, 0xd8, 0xaa,
+       0x8b, 0xc2, 0xe6, 0x38, 0xba, 0xa7, 0xd6, 0xdb, 0xf2, 0x71, 0xcf, 0xb9,
+       0x9f, 0x07, 0x72, 0xf3, 0x87, 0x85, 0x6e, 0x36, 0x3c, 0xbe, 0x47, 0xd5,
+       0x9c, 0x7e, 0x5e, 0x5c, 0x33, 0x16, 0x70, 0xed, 0x49, 0x75, 0xed, 0xd7,
+       0x84, 0x4e, 0x8c, 0xfc, 0xb8, 0xd0, 0x35, 0x81, 0xdf, 0xbc, 0xaf, 0x4e,
+       0x8c, 0xf1, 0x3b, 0xb2, 0x04, 0xdf, 0xbc, 0x80, 0xa7, 0x86, 0x07, 0x60,
+       0x01, 0x9c, 0xef, 0x52, 0xf8, 0x6e, 0x5b, 0xa9, 0xa0, 0x5e, 0x77, 0x33,
+       0x38, 0xb3, 0x8e, 0x93, 0xc7, 0x5a, 0xb1, 0xa6, 0xdd, 0x81, 0x44, 0xc9,
+       0x32, 0x72, 0xf3, 0xb0, 0x71, 0xe0, 0x7f, 0xdc, 0x8b, 0xbc, 0x28, 0x9e,
+       0xc3, 0x6e, 0x4a, 0xa4, 0x31, 0x2f, 0x8c, 0xd3, 0x30, 0x18, 0xf7, 0xc0,
+       0xc2, 0x7d, 0xdf, 0x0e, 0x75, 0x5f, 0xbb, 0xd8, 0x0b, 0x32, 0xf0, 0x1e,
+       0xfd, 0x6e, 0xbc, 0x17, 0xef, 0xc7, 0x7d, 0x78, 0x9e, 0x7c, 0xee, 0x2e,
+       0xe6, 0xd7, 0xc9, 0x09, 0xf9, 0x2c, 0xe3, 0xa6, 0xbc, 0xb6, 0xcb, 0xf1,
+       0x9f, 0xaf, 0xdc, 0x3f, 0xdc, 0xab, 0xf7, 0x6f, 0x07, 0x95, 0x84, 0x5f,
+       0x09, 0xd7, 0xba, 0xc5, 0xb5, 0xa4, 0xd3, 0x2d, 0xf6, 0x75, 0x8e, 0x8f,
+       0xcf, 0x16, 0x7a, 0x02, 0xb0, 0xd5, 0x73, 0xe9, 0xee, 0x40, 0xa9, 0x84,
+       0xf5, 0x76, 0x07, 0x52, 0x8c, 0xf3, 0xd3, 0x85, 0x23, 0x95, 0x59, 0xc1,
+       0x5b, 0x58, 0xc7, 0xed, 0xb3, 0xcd, 0x33, 0xc6, 0xcf, 0xc4, 0x9a, 0xf8,
+       0x7d, 0xfc, 0x9b, 0xe9, 0x2e, 0xcf, 0x74, 0x97, 0x67, 0xba, 0xcb, 0x33,
+       0xdd, 0xb1, 0x8d, 0xfa, 0x83, 0x3c, 0xd3, 0x1d, 0xcb, 0x90, 0xb7, 0x58,
+       0x86, 0x48, 0x5a, 0x4d, 0x28, 0xdf, 0x9e, 0xa6, 0x55, 0x6f, 0x4d, 0xa6,
+       0xa6, 0x4d, 0xc8, 0x6d, 0x0a, 0x1c, 0x1d, 0xad, 0xa7, 0xd1, 0x3b, 0x4c,
+       0xa3, 0x2d, 0x53, 0xfd, 0xf4, 0xa0, 0x88, 0x3d, 0xb3, 0xad, 0x39, 0xe6,
+       0xd1, 0xa9, 0x20, 0x74, 0xac, 0x10, 0xd3, 0x13, 0x74, 0x4c, 0x9b, 0xe1,
+       0xde, 0x4f, 0xeb, 0xc5, 0x76, 0x1e, 0x03, 0x9a, 0xdd, 0xab, 0x8e, 0xf3,
+       0x4c, 0xb3, 0x90, 0x7b, 0xd7, 0x02, 0x77, 0x0a, 0x06, 0xeb, 0x62, 0x21,
+       0x33, 0x43, 0xe0, 0x9f, 0x42, 0x3f, 0xe3, 0x7d, 0x5f, 0x65, 0x7e, 0x0f,
+       0xdf, 0x29, 0x7a, 0x77, 0x95, 0x20, 0x3b, 0x22, 0xb7, 0x99, 0x7f, 0x5e,
+       0x28, 0x5e, 0x63, 0x3a, 0xef, 0xa3, 0x2f, 0x17, 0x21, 0x9f, 0x01, 0x23,
+       0x3e, 0x2e, 0x91, 0xf0, 0x7d, 0x19, 0x53, 0x58, 0xfb, 0xfe, 0xac, 0x21,
+       0xf0, 0xe4, 0xaf, 0x01, 0x07, 0x86, 0xfd, 0xdd, 0x3d, 0xe8, 0x69, 0x9f,
+       0x30, 0x5a, 0x95, 0x8f, 0x17, 0xbf, 0x31, 0x1e, 0x63, 0x01, 0x37, 0x1c,
+       0x37, 0x8b, 0x2f, 0xe2, 0x1b, 0x11, 0x71, 0x86, 0x87, 0x97, 0x5f, 0x5d,
+       0xe5, 0xfb, 0x05, 0xbc, 0x26, 0x93, 0x41, 0xd4, 0x87, 0xd3, 0xd7, 0x82,
+       0x53, 0x93, 0xf4, 0x72, 0x19, 0xf3, 0xbe, 0x42, 0xb3, 0x61, 0xf0, 0x1f,
+       0x3b, 0x7e, 0x9f, 0x24, 0xec, 0xda, 0x59, 0xdf, 0xfc, 0xa2, 0x3f, 0x4f,
+       0xb3, 0x92, 0x42, 0x3f, 0x6e, 0x63, 0x7b, 0x07, 0xb0, 0x79, 0x83, 0x71,
+       0x2d, 0x0e, 0x1f, 0x80, 0xe2, 0x67, 0xdf, 0x67, 0x9e, 0x83, 0x3d, 0xc3,
+       0x71, 0x3d, 0x0f, 0x5b, 0x53, 0x3c, 0xcc, 0x71, 0xf1, 0xb0, 0x5c, 0x95,
+       0x87, 0x31, 0x2e, 0x08, 0xde, 0x05, 0xde, 0x74, 0x82, 0xf5, 0x45, 0xf9,
+       0x1b, 0x7a, 0xe0, 0x4e, 0xc1, 0xab, 0x98, 0xb7, 0xb3, 0xfd, 0xb0, 0x58,
+       0xce, 0x06, 0x8e, 0x08, 0x9e, 0xa1, 0xf1, 0xf9, 0xa9, 0x01, 0x49, 0x07,
+       0xed, 0xd2, 0x1f, 0x79, 0x0a, 0x7c, 0xca, 0x6f, 0xfc, 0x67, 0x78, 0x1c,
+       0xc6, 0x3b, 0x91, 0xd7, 0x99, 0x7f, 0x2d, 0xc6, 0x63, 0x22, 0x06, 0x22,
+       0x6d, 0x9c, 0x2c, 0xdb, 0x01, 0xbb, 0x90, 0x6b, 0x69, 0x25, 0xab, 0xfc,
+       0x4b, 0xd7, 0x1f, 0xc1, 0xaf, 0x88, 0x3d, 0x4e, 0xf4, 0x1a, 0x72, 0x1d,
+       0x16, 0xd6, 0x31, 0x5b, 0xa4, 0xd0, 0x4c, 0x1c, 0xb9, 0x71, 0xe0, 0xeb,
+       0x1f, 0xf0, 0xba, 0xb1, 0xaf, 0x1f, 0x60, 0x5f, 0xe5, 0xb5, 0x89, 0x63,
+       0x62, 0x5e, 0xb3, 0xcb, 0x35, 0xfe, 0x37, 0x97, 0x1f, 0x30, 0x16, 0x0b,
+       0x72, 0x6e, 0x4b, 0xa3, 0x92, 0xc7, 0x2d, 0x96, 0xd0, 0xab, 0x4b, 0xcc,
+       0x91, 0xe7, 0xa6, 0xd7, 0x85, 0xf7, 0x6a, 0x7a, 0xdf, 0x0a, 0x6d, 0x3d,
+       0xc3, 0x74, 0x84, 0x3d, 0xc8, 0xba, 0x70, 0xe4, 0x5b, 0xfc, 0x7e, 0x9c,
+       0x6b, 0x9c, 0xff, 0x83, 0xea, 0xfc, 0x9f, 0xe4, 0xf9, 0x63, 0xcc, 0x07,
+       0x2c, 0xef, 0xe5, 0xfc, 0x1f, 0x54, 0xe7, 0x5f, 0x54, 0xf3, 0xa7, 0x9c,
+       0x31, 0xd5, 0xab, 0xf4, 0xf7, 0xa6, 0xcf, 0x6a, 0x9f, 0x99, 0x10, 0x63,
+       0xcd, 0x19, 0xe8, 0x44, 0xa6, 0x9e, 0x8b, 0xb6, 0x0d, 0xdd, 0x73, 0xb1,
+       0x63, 0xf7, 0xe9, 0x8f, 0x49, 0xea, 0x1d, 0x43, 0xac, 0x77, 0xe0, 0x3c,
+       0xcd, 0x82, 0xcf, 0xe6, 0xc2, 0xe8, 0x11, 0x3b, 0xc8, 0x30, 0x62, 0x3b,
+       0x6a, 0x82, 0xff, 0x0a, 0xbf, 0x18, 0x9e, 0xa3, 0xef, 0xff, 0x43, 0x5a,
+       0x9f, 0x07, 0x2f, 0x86, 0xfe, 0x29, 0xfb, 0xc8, 0xae, 0xaf, 0x48, 0xff,
+       0x6b, 0xca, 0xd7, 0xff, 0x0a, 0xdf, 0xeb, 0x04, 0xf4, 0x73, 0x13, 0x7e,
+       0xda, 0x69, 0xf5, 0xed, 0x8f, 0x5c, 0x19, 0xcf, 0xf2, 0xe3, 0x2b, 0x93,
+       0xae, 0x1c, 0x35, 0xe4, 0x8c, 0x64, 0x99, 0x4f, 0x38, 0x66, 0x8b, 0x21,
+       0x6b, 0x64, 0x6e, 0x95, 0xb5, 0xae, 0x73, 0x8c, 0xf7, 0xc4, 0x89, 0x1b,
+       0x46, 0x4a, 0xf8, 0x08, 0xda, 0x9d, 0x2e, 0x6a, 0x63, 0x39, 0x78, 0x8e,
+       0xd0, 0xe7, 0xcc, 0xb6, 0x10, 0x3b, 0xb9, 0xca, 0x38, 0x36, 0x1b, 0xb7,
+       0x23, 0xcf, 0x0b, 0x7b, 0x12, 0xf2, 0x01, 0xdf, 0x4e, 0x01, 0xac, 0x30,
+       0x07, 0xfe, 0xbd, 0x8c, 0x9e, 0x95, 0x71, 0x5e, 0x3f, 0x7c, 0xbd, 0x23,
+       0xd6, 0x5d, 0x96, 0x2b, 0x57, 0x85, 0x3f, 0xe5, 0x12, 0xeb, 0x92, 0xb6,
+       0x79, 0x54, 0xd0, 0x99, 0x31, 0xc4, 0x54, 0xc1, 0x74, 0x82, 0x1c, 0x81,
+       0xfd, 0xa2, 0xa7, 0x8e, 0xb4, 0x51, 0x78, 0x95, 0x2b, 0xaa, 0x57, 0x41,
+       0x1a, 0xb4, 0xbf, 0x75, 0x5f, 0x42, 0xfa, 0xa1, 0x7d, 0x28, 0x6e, 0x1d,
+       0xca, 0xeb, 0xa7, 0x86, 0x3d, 0x66, 0x89, 0xde, 0x8c, 0x80, 0x9d, 0xf0,
+       0x03, 0x1a, 0x63, 0x0c, 0x37, 0xfd, 0x9d, 0x1a, 0xb7, 0xbd, 0x7f, 0x5e,
+       0xd4, 0xdc, 0xbf, 0x59, 0x96, 0x32, 0x34, 0xc7, 0xb6, 0xf8, 0xec, 0xb8,
+       0x5b, 0xa7, 0xb0, 0x0b, 0xd3, 0xc2, 0x07, 0x33, 0x40, 0xc9, 0x85, 0x31,
+       0xfa, 0x7c, 0x1e, 0x3c, 0x88, 0xee, 0x27, 0x1d, 0xf1, 0xcd, 0x25, 0x9e,
+       0xd3, 0x18, 0xa5, 0xca, 0x80, 0x51, 0x80, 0x66, 0x99, 0xcb, 0xe7, 0x0a,
+       0x88, 0xbd, 0xf3, 0xef, 0x12, 0xbe, 0xa9, 0xf2, 0x3b, 0xca, 0xb7, 0x1d,
+       0xa5, 0xe9, 0x05, 0xca, 0x66, 0xe2, 0x4f, 0x8b, 0x3e, 0xd3, 0x99, 0xf8,
+       0xa8, 0xf2, 0xc9, 0x44, 0xf8, 0x3c, 0xfc, 0x5c, 0x16, 0x7d, 0x2e, 0x6f,
+       0x67, 0x33, 0x24, 0x7d, 0x0d, 0xc4, 0x73, 0x30, 0x58, 0x76, 0xee, 0x64,
+       0x9e, 0x70, 0x52, 0xf8, 0x1b, 0x58, 0xd3, 0x98, 0xc7, 0x78, 0xf8, 0x0a,
+       0xfa, 0x08, 0xf6, 0x55, 0xa6, 0xf0, 0x92, 0x1a, 0x5b, 0x21, 0x93, 0x71,
+       0xc1, 0xfc, 0x55, 0x27, 0x1b, 0x37, 0x6a, 0xf7, 0xc3, 0x57, 0x71, 0x52,
+       0xe8, 0x7d, 0x43, 0xb4, 0x24, 0x68, 0xbd, 0x52, 0x99, 0x11, 0x7e, 0x07,
+       0x3e, 0x2e, 0x4d, 0x0e, 0x4a, 0x5e, 0x25, 0xcf, 0x4b, 0x7f, 0x04, 0x3f,
+       0xb3, 0xc4, 0xf3, 0xa8, 0xcb, 0x7f, 0x8f, 0x52, 0x62, 0x1b, 0xfe, 0xa1,
+       0x53, 0x8f, 0xd4, 0x3f, 0xc4, 0xb0, 0x66, 0xd9, 0x71, 0x8b, 0x69, 0xe3,
+       0xc7, 0x9b, 0xda, 0x6d, 0xef, 0x69, 0x19, 0xcc, 0xb0, 0x32, 0xc5, 0xb7,
+       0x2b, 0xa0, 0x33, 0xcf, 0x96, 0xe7, 0xf0, 0x1d, 0x99, 0x40, 0x5a, 0xe8,
+       0xb2, 0x11, 0xd6, 0x4d, 0xa0, 0xa3, 0x8c, 0x88, 0x78, 0x62, 0xe2, 0x59,
+       0xcb, 0x98, 0x5d, 0xc1, 0xb7, 0xa1, 0xa0, 0x9b, 0xe9, 0x9c, 0x86, 0x76,
+       0x91, 0xa7, 0x2e, 0xe3, 0xbc, 0x90, 0xaf, 0xe0, 0x79, 0x3f, 0x0f, 0x64,
+       0x56, 0x9e, 0xde, 0xa5, 0xf3, 0xd5, 0x12, 0x61, 0x9d, 0x0f, 0xa3, 0x79,
+       0x8a, 0xc6, 0x3d, 0x1d, 0xa3, 0x70, 0x7f, 0xcb, 0x0b, 0xb4, 0xeb, 0xd6,
+       0x09, 0xe0, 0x57, 0x12, 0x7b, 0x74, 0x15, 0xb1, 0x31, 0xa3, 0x2e, 0xfe,
+       0xd0, 0xc6, 0xfb, 0x64, 0x31, 0x6e, 0xc0, 0x5f, 0xf7, 0x05, 0xfe, 0x8b,
+       0x38, 0x42, 0x69, 0x10, 0x7a, 0x50, 0xaf, 0xc3, 0x38, 0x33, 0x81, 0xe3,
+       0x7e, 0x5a, 0x2c, 0x6a, 0xbd, 0x55, 0xfa, 0x90, 0x16, 0x97, 0xf5, 0x7e,
+       0xc1, 0x7f, 0x34, 0xac, 0x7a, 0x08, 0xd8, 0x64, 0xf5, 0x01, 0x4e, 0x9f,
+       0x14, 0x3d, 0x6e, 0x16, 0x73, 0xd8, 0x4a, 0xce, 0x11, 0xbe, 0x2f, 0x86,
+       0x9e, 0x99, 0xfb, 0x00, 0x7b, 0xde, 0x23, 0x77, 0x4c, 0x62, 0x4e, 0x7d,
+       0xff, 0xe7, 0x51, 0xed, 0xdb, 0x63, 0x3e, 0xfb, 0xf6, 0xd1, 0xa0, 0x8c,
+       0x73, 0x3d, 0xa7, 0xc6, 0xf8, 0xe5, 0x99, 0xfe, 0xf3, 0x0b, 0xf0, 0x1f,
+       0xd5, 0xea, 0x25, 0xee, 0x09, 0xbe, 0xd2, 0xe8, 0xc3, 0x8e, 0x30, 0x3f,
+       0x95, 0x74, 0x7c, 0xd2, 0x87, 0x8e, 0xfb, 0x78, 0x8f, 0x4f, 0x3c, 0x04,
+       0x1d, 0x9f, 0x68, 0x4a, 0xc7, 0x87, 0xa2, 0xd2, 0x87, 0xda, 0x48, 0xc7,
+       0xa8, 0xd9, 0x39, 0x59, 0x6e, 0xe6, 0xaf, 0xc2, 0x3e, 0xa0, 0xf6, 0x1c,
+       0xfe, 0x04, 0xc0, 0x4a, 0xfb, 0x14, 0x10, 0xdb, 0x03, 0x3e, 0x22, 0x56,
+       0xf2, 0x17, 0x94, 0x9a, 0xf7, 0xc6, 0x38, 0x37, 0xba, 0xe7, 0x7d, 0x9f,
+       0x7b, 0xa0, 0x6b, 0x83, 0x16, 0xec, 0x88, 0xb4, 0xd5, 0x35, 0xbc, 0xde,
+       0x0d, 0x1c, 0x29, 0xda, 0xd9, 0x12, 0x18, 0x63, 0x4f, 0x98, 0xce, 0x23,
+       0x8e, 0xaf, 0x7c, 0xbe, 0xc7, 0xf3, 0x72, 0xdd, 0xe6, 0xb8, 0xc0, 0x07,
+       0xe8, 0xa3, 0x91, 0x74, 0x30, 0xcd, 0x7b, 0x2a, 0xfd, 0xbd, 0x99, 0xe5,
+       0x88, 0xda, 0x27, 0x1e, 0x8b, 0xe7, 0xf9, 0xd6, 0xf3, 0x61, 0x7f, 0xec,
+       0x57, 0x57, 0xab, 0x79, 0xc1, 0x90, 0x05, 0x15, 0xfa, 0x05, 0xcb, 0xb9,
+       0xe0, 0xb8, 0x29, 0xfa, 0x28, 0xdc, 0x2a, 0x8f, 0xb3, 0x7e, 0x88, 0x3d,
+       0x84, 0xaf, 0x50, 0xfb, 0x72, 0x7f, 0x31, 0x44, 0x3d, 0x87, 0x58, 0xea,
+       0x1b, 0xe4, 0xb0, 0x7e, 0x68, 0x8c, 0x23, 0xbf, 0xdb, 0xe2, 0x7b, 0xd0,
+       0xff, 0x69, 0xbf, 0x95, 0xa2, 0x2e, 0xf8, 0x09, 0xd0, 0xa7, 0xd9, 0xca,
+       0xd5, 0xd1, 0xd4, 0x69, 0x41, 0x53, 0xa9, 0x95, 0xd3, 0x8a, 0xa6, 0x4e,
+       0x2b, 0x7f, 0xf9, 0x69, 0x45, 0x53, 0xa7, 0x15, 0x4d, 0x9d, 0x56, 0x34,
+       0x75, 0x9a, 0xf1, 0x7a, 0xc4, 0xec, 0x13, 0x3a, 0xbb, 0xf6, 0x57, 0xf6,
+       0x50, 0xa6, 0x88, 0xf3, 0x90, 0xc7, 0x5e, 0xba, 0x7a, 0x75, 0x48, 0xd2,
+       0xd5, 0x24, 0x2d, 0xca, 0x3c, 0x39, 0x7e, 0x17, 0xf6, 0xe0, 0xeb, 0x83,
+       0xd4, 0x73, 0x2f, 0x70, 0x76, 0x1e, 0x73, 0x0d, 0xd0, 0xb4, 0xe8, 0xe1,
+       0xda, 0x42, 0x49, 0xb7, 0x2e, 0x6b, 0xa2, 0x7e, 0x4b, 0xda, 0x6a, 0xd9,
+       0xa6, 0xb5, 0x5c, 0x1a, 0x2f, 0xa6, 0xd4, 0x7e, 0x79, 0xed, 0x98, 0x36,
+       0x4a, 0x17, 0x00, 0x57, 0xe4, 0x32, 0x5a, 0xbc, 0x37, 0x02, 0x4e, 0x59,
+       0xd3, 0x07, 0x06, 0xc7, 0x15, 0x0c, 0xbe, 0x22, 0xd6, 0x88, 0x5c, 0x40,
+       0xf8, 0x1c, 0x9b, 0xc3, 0x21, 0x97, 0x1f, 0xe1, 0xe7, 0x30, 0xee, 0x8f,
+       0x47, 0x98, 0x07, 0x6d, 0x1d, 0x0e, 0xb5, 0xb5, 0x37, 0xe3, 0x35, 0x5b,
+       0xad, 0x87, 0xb9, 0xef, 0x92, 0x1d, 0x11, 0x25, 0x37, 0xa4, 0x9e, 0xfb,
+       0x98, 0x63, 0xa7, 0xb3, 0x3c, 0xb7, 0xbf, 0x8f, 0xb7, 0xef, 0xa5, 0x8e,
+       0x0a, 0x1d, 0x8b, 0x03, 0x9f, 0x7b, 0xd8, 0x6e, 0xe4, 0x39, 0xec, 0xaf,
+       0xd0, 0xd5, 0xf8, 0x01, 0xb6, 0x4d, 0xf0, 0x2d, 0xa6, 0x11, 0xfe, 0xef,
+       0x24, 0x82, 0x01, 0xcc, 0xab, 0x8b, 0xef, 0x0d, 0x93, 0xd1, 0x9b, 0xe8,
+       0x6d, 0x57, 0xba, 0x29, 0xfc, 0x6e, 0xac, 0x9b, 0x1a, 0x33, 0xf1, 0x1d,
+       0xaa, 0xa6, 0x0c, 0xbe, 0x6a, 0xc4, 0xb1, 0x7e, 0x56, 0x91, 0xbd, 0x00,
+       0xa2, 0xea, 0xf8, 0xa7, 0x95, 0x44, 0x14, 0xc7, 0x26, 0xdd, 0x60, 0x7b,
+       0x39, 0x11, 0x18, 0xd9, 0x2b, 0x74, 0xf6, 0x80, 0x7d, 0x4c, 0xe6, 0x30,
+       0xd8, 0xa6, 0x15, 0xf0, 0xc3, 0x77, 0xa9, 0xeb, 0xd4, 0xf2, 0x4c, 0x81,
+       0xff, 0x15, 0xfa, 0x4f, 0xa6, 0x55, 0x93, 0x10, 0xb3, 0x98, 0x14, 0xb5,
+       0xce, 0xc8, 0x33, 0x3e, 0x3b, 0x0f, 0x9a, 0x85, 0xdf, 0xd0, 0x51, 0x7b,
+       0xfc, 0x29, 0xe4, 0x89, 0x15, 0x16, 0x69, 0x63, 0x59, 0x01, 0xbf, 0xd8,
+       0xc8, 0xc2, 0x5a, 0x6f, 0x58, 0xd4, 0x5e, 0xc3, 0xcf, 0xa9, 0xf3, 0x89,
+       0xf7, 0xf3, 0xf3, 0x43, 0xe2, 0xdb, 0x72, 0xd3, 0xd7, 0x30, 0xae, 0x95,
+       0x86, 0x17, 0x2a, 0x4f, 0xf1, 0x75, 0x11, 0x2f, 0xcc, 0x50, 0xbb, 0x8a,
+       0x05, 0x74, 0xa9, 0xf8, 0x51, 0x84, 0x69, 0xa8, 0x56, 0x53, 0x3c, 0x5c,
+       0xf5, 0x9d, 0x01, 0xb7, 0xbd, 0xbe, 0xb3, 0xaf, 0x6d, 0x22, 0x67, 0x36,
+       0xc3, 0x67, 0xe4, 0x82, 0xb6, 0x91, 0xf2, 0x09, 0x5a, 0xb3, 0xb4, 0xd5,
+       0xda, 0xb9, 0x6d, 0xdf, 0xd3, 0xde, 0x3a, 0xb5, 0x7a, 0xf1, 0xae, 0xd3,
+       0xa1, 0xf0, 0xa8, 0x95, 0xce, 0x16, 0x3b, 0x58, 0x56, 0xa3, 0xce, 0x09,
+       0xf0, 0x0a, 0x46, 0x51, 0x27, 0xf2, 0x5c, 0xa8, 0x95, 0x96, 0x97, 0x91,
+       0xd3, 0xf0, 0x67, 0x7b, 0x65, 0x7e, 0x6e, 0x9a, 0xe1, 0x72, 0x88, 0xe5,
+       0x9a, 0xa1, 0x62, 0x35, 0x38, 0x07, 0x9e, 0x20, 0x7a, 0x78, 0x86, 0x9e,
+       0x1e, 0xed, 0x60, 0x7d, 0x5e, 0xfa, 0xfa, 0x0f, 0xf3, 0xb3, 0xbf, 0x57,
+       0x4c, 0xc3, 0x4f, 0x65, 0x1e, 0xe5, 0xe7, 0x4f, 0xb3, 0x1e, 0x90, 0xa0,
+       0x56, 0x5a, 0x5a, 0x6e, 0x65, 0x7d, 0xbe, 0x95, 0xf5, 0x80, 0x11, 0x73,
+       0x38, 0x20, 0xde, 0x25, 0x6a, 0x52, 0x3e, 0x1b, 0x3a, 0x64, 0x1e, 0x13,
+       0x79, 0x36, 0x7f, 0xa5, 0xde, 0xe5, 0x7d, 0xc7, 0x07, 0x15, 0x1c, 0x1f,
+       0x0d, 0xae, 0x5e, 0xbc, 0xe3, 0x98, 0x8c, 0x7f, 0x93, 0xac, 0xf3, 0x86,
+       0xc5, 0xf7, 0x17, 0x8d, 0xa9, 0x29, 0xd6, 0xff, 0xf1, 0x8d, 0xb7, 0x67,
+       0x28, 0x5b, 0x3e, 0x45, 0x5f, 0x2f, 0xbb, 0x7d, 0xaf, 0xcf, 0xf0, 0x9c,
+       0x65, 0xed, 0x7c, 0x1b, 0xcf, 0xeb, 0x3d, 0xc7, 0xcb, 0x2b, 0x3a, 0x28,
+       0xf8, 0xad, 0x30, 0xb5, 0x7e, 0x03, 0x3e, 0x8f, 0x0a, 0x15, 0xe2, 0xf6,
+       0xd5, 0xfb, 0x24, 0xfd, 0xbc, 0x37, 0x44, 0x5e, 0x2a, 0xdf, 0xcf, 0xcf,
+       0x9c, 0xc3, 0xb8, 0x1b, 0x16, 0xdd, 0x76, 0x24, 0xbc, 0xff, 0x36, 0x14,
+       0xa6, 0xe0, 0x1b, 0xc8, 0xf5, 0x82, 0x8e, 0xb5, 0x7a, 0xd1, 0x39, 0xc0,
+       0x7c, 0xfa, 0x1b, 0xb8, 0x8f, 0xff, 0xbe, 0x81, 0xe3, 0x0e, 0x5e, 0x27,
+       0xe4, 0x2c, 0x72, 0x4a, 0xc0, 0xdf, 0x0e, 0x45, 0x4c, 0x81, 0x7f, 0xcf,
+       0x30, 0x4e, 0xb5, 0x08, 0x1f, 0x5f, 0x1f, 0xc6, 0x3a, 0x83, 0xac, 0x13,
+       0xac, 0x5e, 0x1c, 0x3d, 0x80, 0xe3, 0x44, 0x6f, 0x90, 0x61, 0x24, 0x71,
+       0xa8, 0xe1, 0x9b, 0x75, 0xa1, 0xc3, 0xa3, 0xe4, 0xfa, 0x6e, 0x1d, 0x7a,
+       0x26, 0x75, 0x50, 0x8a, 0xdf, 0x31, 0x5d, 0x94, 0xeb, 0x9e, 0x2b, 0x07,
+       0x49, 0xfa, 0x87, 0x52, 0x43, 0xfa, 0xfb, 0x84, 0xd4, 0x8f, 0x67, 0x6b,
+       0x5a, 0xc1, 0xef, 0x1e, 0x7a, 0x50, 0xec, 0xa2, 0x75, 0x15, 0x43, 0x7a,
+       0x20, 0xec, 0x29, 0xe6, 0xc5, 0xe9, 0x1e, 0xba, 0xbf, 0xdc, 0x42, 0xd4,
+       0xd7, 0x21, 0x62, 0xbc, 0x0f, 0x8a, 0x8b, 0x94, 0x7c, 0xed, 0xc9, 0x21,
+       0xe9, 0x4f, 0xa9, 0xe1, 0xc8, 0x03, 0x1f, 0x1c, 0x79, 0x57, 0xe0, 0xc8,
+       0xf0, 0xd0, 0xc6, 0x38, 0xb2, 0x47, 0xe7, 0x22, 0x52, 0xab, 0xc2, 0x8f,
+       0xd7, 0x19, 0x3f, 0x5e, 0x66, 0xfc, 0x38, 0xd2, 0x04, 0x3f, 0x0c, 0x0f,
+       0x7e, 0x1c, 0x15, 0xf8, 0xf1, 0xeb, 0x43, 0x1b, 0xe1, 0xc7, 0x91, 0xe0,
+       0x46, 0x3e, 0x1e, 0x8d, 0x9b, 0x03, 0xb4, 0x54, 0x74, 0x68, 0x79, 0xde,
+       0x8e, 0x27, 0x68, 0x35, 0x22, 0x63, 0x83, 0x53, 0xa2, 0x4e, 0x65, 0x51,
+       0xe0, 0x55, 0x5a, 0xf8, 0x2f, 0xfd, 0xbf, 0x1b, 0x68, 0x29, 0xf8, 0xcb,
+       0x3d, 0x99, 0xce, 0xaf, 0x5e, 0xfc, 0x3b, 0xde, 0xc7, 0xdb, 0x2b, 0xa1,
+       0x10, 0xae, 0x05, 0xa7, 0xc2, 0xb4, 0xb6, 0x82, 0xef, 0x12, 0x46, 0xe8,
+       0x4e, 0x31, 0x4a, 0xb7, 0x8b, 0x03, 0xb4, 0x56, 0x1c, 0xa2, 0xbb, 0x45,
+       0xbc, 0x03, 0x30, 0xe7, 0x63, 0x01, 0x73, 0x83, 0x0e, 0x87, 0x79, 0xcc,
+       0xf2, 0x00, 0xad, 0x2e, 0x6b, 0x7c, 0x05, 0xae, 0x62, 0xff, 0xe1, 0x27,
+       0xf0, 0xc7, 0x81, 0xe9, 0x3a, 0x1c, 0x90, 0xf7, 0x60, 0xef, 0x67, 0x1b,
+       0x6b, 0x64, 0x45, 0x9e, 0xa5, 0xc9, 0x38, 0xd2, 0x32, 0x65, 0x0b, 0x5f,
+       0xea, 0xe1, 0x20, 0x74, 0xd9, 0xc4, 0x3e, 0xea, 0xe1, 0x3d, 0x70, 0x90,
+       0x27, 0x34, 0xc4, 0x7a, 0xe9, 0x0e, 0xa1, 0x87, 0x26, 0x9d, 0x50, 0x64,
+       0x9a, 0x2a, 0x97, 0x0c, 0x07, 0x3d, 0x0f, 0xd3, 0xfc, 0x3c, 0x43, 0xf9,
+       0x71, 0xba, 0x5d, 0xf8, 0xe4, 0xd5, 0x39, 0x11, 0x8b, 0x7d, 0x96, 0xe7,
+       0x0c, 0xf9, 0x58, 0x8b, 0x73, 0x50, 0x35, 0xce, 0xd1, 0xce, 0xeb, 0x96,
+       0xb4, 0x34, 0xe3, 0xf0, 0xb8, 0x32, 0x8f, 0x2b, 0x23, 0x76, 0xc6, 0xe7,
+       0x97, 0x11, 0xb7, 0x8d, 0xd2, 0xda, 0x3c, 0x68, 0x0e, 0x7e, 0x89, 0x5a,
+       0xac, 0x74, 0x6d, 0x05, 0xe7, 0xe1, 0x9b, 0xa8, 0xc5, 0x4a, 0xd7, 0x54,
+       0xac, 0x74, 0x6d, 0x65, 0x4a, 0xf0, 0xe1, 0xd9, 0xff, 0xdd, 0x14, 0x60,
+       0x19, 0x30, 0x85, 0x19, 0xba, 0x4e, 0x53, 0x0d, 0x7a, 0xbf, 0x4e, 0x0c,
+       0x78, 0x6c, 0x58, 0x50, 0x05, 0x7f, 0x18, 0xba, 0x62, 0x84, 0xa1, 0x0d,
+       0xb8, 0xfd, 0xe3, 0x02, 0x34, 0xd3, 0x79, 0x4a, 0x0c, 0x30, 0x3c, 0x23,
+       0x80, 0x79, 0x49, 0x18, 0x9a, 0x97, 0x60, 0x73, 0xaf, 0xfc, 0x0c, 0x90,
+       0xbb, 0x7a, 0x6c, 0xc0, 0x6d, 0x7c, 0x48, 0xf9, 0x23, 0x83, 0x56, 0xfe,
+       0x30, 0xb0, 0x38, 0xa9, 0x43, 0xf4, 0x37, 0xad, 0x7f, 0x2c, 0x07, 0x1b,
+       0x5f, 0x6b, 0x02, 0x9a, 0xdb, 0x3c, 0x85, 0x94, 0xb9, 0x5b, 0x60, 0xbd,
+       0x89, 0x75, 0x5d, 0x26, 0xb1, 0x76, 0xc3, 0xd2, 0x42, 0x0c, 0x19, 0xe9,
+       0x09, 0x62, 0x06, 0x22, 0x3d, 0xd9, 0x00, 0xcb, 0x4e, 0x16, 0x60, 0x5e,
+       0x11, 0x02, 0xd6, 0x0f, 0x0c, 0xd0, 0x3a, 0xe6, 0x00, 0x78, 0x2c, 0xa1,
+       0x89, 0x01, 0x74, 0x07, 0x27, 0xd0, 0xfe, 0x7e, 0x65, 0xf0, 0xba, 0xe3,
+       0x06, 0x09, 0x88, 0xa1, 0x8b, 0x7a, 0x14, 0xe5, 0x41, 0x79, 0xd4, 0x49,
+       0x85, 0x81, 0xc4, 0xfc, 0x04, 0xf2, 0x1f, 0xd0, 0x1f, 0x20, 0x3f, 0x02,
+       0xf3, 0x93, 0x33, 0x50, 0x0e, 0xb4, 0x36, 0xaa, 0x79, 0x0d, 0x48, 0x1f,
+       0x28, 0x0c, 0x41, 0x65, 0x2a, 0x68, 0x8c, 0x03, 0xc8, 0x5e, 0x22, 0x04,
+       0x0d, 0x3b, 0x20, 0x0d, 0x64, 0x37, 0x4f, 0x11, 0x01, 0xf3, 0x93, 0x02,
+       0x84, 0x18, 0x1a, 0xe0, 0xf9, 0x89, 0x1d, 0xe8, 0x52, 0x98, 0x9b, 0xfe,
+       0xff, 0x3f, 0xa6, 0xc2, 0x02, 0x4c, 0x7b, 0xa0, 0xb5, 0xb5, 0xbf, 0xff,
+       0x1f, 0x10, 0x61, 0x61, 0x68, 0x81, 0xaf, 0xd1, 0x0b, 0x94, 0x07, 0x95,
+       0x73, 0x0b, 0x80, 0xac, 0x36, 0x78, 0xbd, 0x0d, 0x92, 0x07, 0x89, 0xfd,
+       0x02, 0x96, 0x2b, 0xff, 0xff, 0x2f, 0x85, 0xab, 0x05, 0x01, 0x00, 0xb3,
+       0x28, 0x79, 0xae, 0x58, 0x7d, 0x00, 0x00, 0x00 };
 
-static u32 bnx2_COM_b06FwData[(0x0/4) + 1] = { 0x0 };
-static u32 bnx2_COM_b06FwRodata[(0x58/4) + 1] = {
-       0x08002428, 0x0800245c, 0x0800245c, 0x0800245c, 0x0800245c, 0x0800245c,
-       0x08002380, 0x0800245c, 0x080023e4, 0x0800245c, 0x0800231c, 0x0800245c,
-       0x0800245c, 0x0800245c, 0x08002328, 0x00000000, 0x08003240, 0x08003270,
-       0x080032a0, 0x080032d0, 0x08003300, 0x00000000, 0x00000000 };
-static u32 bnx2_COM_b06FwBss[(0x88/4) + 1] = { 0x0 };
-static u32 bnx2_COM_b06FwSbss[(0x1c/4) + 1] = { 0x0 };
+static const u32 bnx2_COM_b06FwData[(0x0/4) + 1] = { 0x0 };
+static const u32 bnx2_COM_b06FwRodata[(0x88/4) + 1] = {
+       0x08001c1c, 0x08001c4c, 0x08001c4c, 0x08001c4c, 0x08001c4c, 0x08001c4c,
+       0x08001b74, 0x08001c4c, 0x08001bdc, 0x08001c4c, 0x08001b08, 0x08001c4c,
+       0x08001c4c, 0x08001c4c, 0x08001b14, 0x00000000, 0x08002b58, 0x08002ba8,
+       0x08002bd8, 0x08002c08, 0x08002c38, 0x00000000, 0x080060cc, 0x080060cc,
+       0x080060cc, 0x080060cc, 0x080060cc, 0x08006100, 0x08006100, 0x08006140,
+       0x0800614c, 0x0800614c, 0x080060cc, 0x00000000, 0x00000000 };
+static const u32 bnx2_COM_b06FwBss[(0x88/4) + 1] = { 0x0 };
+static const u32 bnx2_COM_b06FwSbss[(0x60/4) + 1] = { 0x0 };
 
 static struct fw_info bnx2_com_fw_06 = {
-       .ver_major                      = 0x1,
-       .ver_minor                      = 0x0,
-       .ver_fix                        = 0x0,
+       .ver_major                      = 0x3,
+       .ver_minor                      = 0x4,
+       .ver_fix                        = 0x3,
 
-       .start_addr                     = 0x080008b4,
+       .start_addr                     = 0x080000b4,
 
        .text_addr                      = 0x08000000,
-       .text_len                       = 0x57bc,
+       .text_len                       = 0x7d54,
        .text_index                     = 0x0,
        .gz_text                        = bnx2_COM_b06FwText,
        .gz_text_len                    = sizeof(bnx2_COM_b06FwText),
 
-       .data_addr                      = 0x08005840,
+       .data_addr                      = 0x08007e00,
        .data_len                       = 0x0,
        .data_index                     = 0x0,
        .data                           = bnx2_COM_b06FwData,
 
-       .sbss_addr                      = 0x08005840,
-       .sbss_len                       = 0x1c,
+       .sbss_addr                      = 0x08007e00,
+       .sbss_len                       = 0x60,
        .sbss_index                     = 0x0,
        .sbss                           = bnx2_COM_b06FwSbss,
 
-       .bss_addr                       = 0x08005860,
+       .bss_addr                       = 0x08007e60,
        .bss_len                        = 0x88,
        .bss_index                      = 0x0,
        .bss                            = bnx2_COM_b06FwBss,
 
-       .rodata_addr                    = 0x080057c0,
-       .rodata_len                     = 0x58,
+       .rodata_addr                    = 0x08007d58,
+       .rodata_len                     = 0x88,
        .rodata_index                   = 0x0,
        .rodata                         = bnx2_COM_b06FwRodata,
 };
index 680c769..2c06753 100644 (file)
@@ -1,13 +1,13 @@
 /* bnx2_fw2.h: Broadcom NX2 network driver.
  *
- * Copyright (c) 2006 Broadcom Corporation
+ * Copyright (c) 2004, 2005, 2006, 2007 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, except as noted below.
  *
  * This file contains firmware data derived from proprietary unpublished
- * source code, Copyright (c) 2006 Broadcom Corporation.
+ * source code, Copyright (c) 2004, 2005, 2006, 2007 Broadcom Corporation.
  *
  * Permission is hereby granted for the distribution of this firmware data
  * in hexadecimal or equivalent format, provided this copyright notice is
  */
 
 static u8 bnx2_COM_b09FwText[] = {
-       0x1f, 0x8b, 0x08, 0x08, 0xac, 0xfb, 0x2f, 0x45, 0x00, 0x03, 0x74, 0x65,
-       0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xdc, 0x5b, 0x6b, 0x70,
-       0x1b, 0xd7, 0x75, 0x3e, 0xfb, 0x00, 0x09, 0x91, 0x10, 0xb5, 0xa4, 0x60,
-       0x1a, 0x96, 0x68, 0x07, 0x20, 0x57, 0x22, 0x6a, 0xb1, 0x29, 0x4c, 0x33,
-       0x16, 0x9b, 0xc2, 0x12, 0x02, 0x50, 0xae, 0x26, 0xc3, 0x3a, 0x94, 0xcd,
-       0xd8, 0x4a, 0xaa, 0xc9, 0x30, 0x00, 0xa5, 0xf4, 0x61, 0xb7, 0x92, 0xab,
-       0xa9, 0x5d, 0xd7, 0xaa, 0x21, 0x92, 0x6a, 0xf5, 0x83, 0xe5, 0x2a, 0x16,
-       0x43, 0xa9, 0xd3, 0x74, 0xc2, 0x12, 0x56, 0xac, 0x4e, 0x31, 0x85, 0xfc,
-       0xd6, 0x38, 0xb1, 0xc9, 0x4a, 0x76, 0xeb, 0xf4, 0xe1, 0xa6, 0x33, 0xcd,
-       0xa3, 0x9d, 0x36, 0xf6, 0xa8, 0x3f, 0xea, 0xe9, 0xd3, 0x33, 0x6e, 0xa7,
-       0xea, 0xd8, 0x0e, 0xfa, 0x7d, 0x77, 0x77, 0x81, 0x25, 0x48, 0xbd, 0xfc,
-       0xc8, 0x8f, 0x70, 0x06, 0xb3, 0x7b, 0xef, 0xde, 0xbd, 0xf7, 0xdc, 0xf3,
-       0xf8, 0xce, 0x63, 0x2f, 0xfb, 0x44, 0x5a, 0xc4, 0xfb, 0x5b, 0x8b, 0x5f,
-       0xfc, 0xfe, 0x5f, 0x2d, 0x7c, 0x7c, 0xf0, 0xe3, 0xfd, 0x22, 0xb7, 0xdc,
-       0xa2, 0xb7, 0x86, 0x75, 0xf6, 0x1b, 0xf8, 0x45, 0xf1, 0xeb, 0xf7, 0xee,
-       0x57, 0xfb, 0xb3, 0xf0, 0x7b, 0x13, 0x0f, 0xc7, 0xfe, 0x55, 0x44, 0xbb,
-       0xc4, 0x98, 0xe0, 0x5f, 0xb5, 0x7a, 0xf9, 0xe7, 0x5c, 0x38, 0x7e, 0x89,
-       0x67, 0x86, 0xbb, 0x9c, 0xa2, 0x97, 0x3f, 0x09, 0xeb, 0x69, 0x39, 0x94,
-       0xb5, 0x25, 0x6c, 0xa4, 0xdf, 0x3c, 0x54, 0xb0, 0x45, 0x32, 0xe5, 0x2d,
-       0xf1, 0x9c, 0xbc, 0x57, 0x2d, 0x46, 0x4d, 0x61, 0xff, 0x8d, 0xe9, 0x77,
-       0xbf, 0xf6, 0xe2, 0xd6, 0xc4, 0x5b, 0xf3, 0x86, 0x84, 0xad, 0xf4, 0x19,
-       0xb1, 0x36, 0x4b, 0xb8, 0x0b, 0xef, 0x7c, 0xb5, 0xf7, 0x3d, 0x91, 0x36,
-       0x7f, 0xae, 0x37, 0xab, 0x2f, 0xf6, 0x4a, 0x71, 0x43, 0x3a, 0x2c, 0x7a,
-       0x7a, 0xd3, 0xf7, 0xb3, 0x86, 0x35, 0x66, 0xa4, 0x2d, 0x59, 0xac, 0xc8,
-       0xc8, 0xde, 0x69, 0x09, 0x87, 0xd3, 0x47, 0x9b, 0x9b, 0x37, 0x49, 0xd8,
-       0x4c, 0x8f, 0x1d, 0xfa, 0x6d, 0xfb, 0xd1, 0xaa, 0x6e, 0xdb, 0xc9, 0x05,
-       0x89, 0x0c, 0x9e, 0x1a, 0xc0, 0xf3, 0x72, 0x22, 0x29, 0xb2, 0x55, 0x74,
-       0xbb, 0x18, 0x31, 0xec, 0xb0, 0x64, 0x2b, 0xb6, 0xe4, 0x2a, 0x22, 0x7f,
-       0x5e, 0xd6, 0xe4, 0x94, 0xdd, 0x29, 0x0b, 0x7d, 0xef, 0x56, 0x33, 0xa0,
-       0xe5, 0xcf, 0xec, 0xb1, 0x43, 0x53, 0x36, 0xe9, 0x9d, 0x6d, 0x76, 0xe9,
-       0x9d, 0x6a, 0x2a, 0xd8, 0xa6, 0x4c, 0x94, 0xd9, 0x37, 0xa2, 0xb3, 0x2f,
-       0x94, 0x7e, 0x68, 0xcd, 0x29, 0x3b, 0xe2, 0xf5, 0xed, 0xdc, 0x9e, 0xc5,
-       0x7c, 0x93, 0x65, 0x8e, 0x3d, 0x93, 0x2a, 0xd8, 0x51, 0xaf, 0x3f, 0x79,
-       0x5b, 0xd6, 0x8e, 0xa1, 0xbf, 0xcb, 0x7b, 0x76, 0xf2, 0xbe, 0x82, 0x6d,
-       0x7b, 0xcf, 0xbe, 0x8a, 0xb9, 0x93, 0x5e, 0xff, 0x7d, 0xdb, 0x0a, 0x76,
-       0x9f, 0xd7, 0x3f, 0xbd, 0x2d, 0x6b, 0xa7, 0xbc, 0xfe, 0xe4, 0xee, 0x82,
-       0x3d, 0xe0, 0xf5, 0x9f, 0xbd, 0x3d, 0x6b, 0x0f, 0x7a, 0xfd, 0x0f, 0x6d,
-       0x2d, 0xd8, 0x69, 0xf4, 0x1f, 0x6d, 0xd6, 0x37, 0x59, 0x72, 0xa4, 0x1c,
-       0xc7, 0x2f, 0x83, 0x67, 0x43, 0xe8, 0xdb, 0x89, 0xdf, 0x30, 0x7e, 0xbf,
-       0xb8, 0x4e, 0xda, 0x46, 0x70, 0xfd, 0xc6, 0x46, 0x97, 0x77, 0xe0, 0x91,
-       0x13, 0x96, 0x37, 0x8c, 0x98, 0xbc, 0xd8, 0xfb, 0x06, 0x78, 0x68, 0xc9,
-       0x99, 0x8a, 0x68, 0x23, 0xbd, 0x31, 0xf0, 0x2e, 0x2a, 0x4f, 0x56, 0x5a,
-       0xc5, 0x78, 0xcc, 0x00, 0x6f, 0x3e, 0x2f, 0xf9, 0x68, 0x58, 0xda, 0xe7,
-       0x34, 0xe9, 0xee, 0x0f, 0x4b, 0xc6, 0x52, 0x72, 0x13, 0x7d, 0x26, 0x2a,
-       0xc6, 0x5c, 0x66, 0xbd, 0x2e, 0x9b, 0xac, 0x9c, 0x14, 0xc1, 0xbb, 0xef,
-       0x51, 0x27, 0xf1, 0x2c, 0x2e, 0xb9, 0xe9, 0x9b, 0x65, 0xcc, 0x22, 0x5d,
-       0x3b, 0x6f, 0x74, 0xd7, 0x0a, 0x6b, 0xd9, 0x13, 0x23, 0x72, 0xc4, 0x89,
-       0x68, 0xb9, 0x13, 0xdb, 0x24, 0x9b, 0x92, 0x28, 0xde, 0x8b, 0xe5, 0xf1,
-       0xa4, 0x54, 0x1e, 0x91, 0x29, 0x47, 0xb4, 0xac, 0x43, 0x7e, 0x76, 0xe2,
-       0x79, 0x9b, 0x1a, 0x8b, 0xbe, 0x2e, 0x43, 0xcd, 0x1d, 0x46, 0xbf, 0x85,
-       0xfe, 0x0e, 0x6d, 0x48, 0xcd, 0xa1, 0xfa, 0xe3, 0x93, 0x12, 0x91, 0xc7,
-       0xcb, 0x51, 0x6f, 0x6c, 0xb5, 0x9a, 0x4d, 0x59, 0x18, 0x37, 0x22, 0x93,
-       0x4e, 0x54, 0xc6, 0x70, 0x9d, 0x70, 0xb8, 0x7e, 0x0c, 0x3a, 0xf5, 0xda,
-       0xa1, 0xfc, 0xac, 0x9a, 0x2f, 0x6e, 0xa4, 0x39, 0x5f, 0x17, 0xc6, 0x4d,
-       0x80, 0x2e, 0x4d, 0x4c, 0x25, 0xcb, 0x8c, 0xe4, 0xa7, 0x35, 0xe8, 0x1b,
-       0xae, 0x8a, 0xaf, 0x43, 0xa0, 0xdf, 0x14, 0xbb, 0x5f, 0x93, 0x02, 0x64,
-       0x55, 0xb4, 0xd0, 0x2e, 0x9f, 0xd5, 0xb3, 0x4e, 0xb3, 0xe4, 0xcc, 0xb8,
-       0x18, 0x33, 0x4a, 0x97, 0x64, 0x12, 0xef, 0xe8, 0x36, 0xc7, 0x5c, 0xc4,
-       0xbe, 0xc7, 0x94, 0x1c, 0x9a, 0xd2, 0x45, 0x3d, 0x57, 0xe9, 0x14, 0x7d,
-       0x6e, 0x8f, 0xbc, 0x3c, 0x2d, 0x96, 0x91, 0x7e, 0xb7, 0x9a, 0xb5, 0xa7,
-       0xf4, 0xec, 0x13, 0xa6, 0x84, 0x66, 0x34, 0x99, 0xb2, 0x13, 0xb0, 0x80,
-       0xa3, 0xfa, 0x8e, 0xca, 0x59, 0x8c, 0xe3, 0x7b, 0x18, 0x57, 0xd6, 0xc1,
-       0x57, 0xde, 0x6f, 0xb1, 0x74, 0xa5, 0xcf, 0x1c, 0x03, 0x19, 0x60, 0x1f,
-       0x4f, 0x3a, 0x90, 0x89, 0x92, 0x51, 0x1c, 0x32, 0x7a, 0x15, 0x32, 0x1a,
-       0x80, 0x6c, 0x52, 0xf2, 0x52, 0xa5, 0x4f, 0x9e, 0xaf, 0x24, 0xe5, 0x39,
-       0xe8, 0xeb, 0xb3, 0x95, 0xb8, 0x3c, 0x53, 0xe9, 0x92, 0xa7, 0x2b, 0x31,
-       0x79, 0x4a, 0xc9, 0x2d, 0x07, 0xdb, 0x50, 0xb2, 0x0c, 0x5f, 0x9f, 0x96,
-       0x70, 0x27, 0xe4, 0xd1, 0x01, 0xfd, 0x69, 0x87, 0x6e, 0x7e, 0xa5, 0x37,
-       0x2c, 0xb3, 0xbd, 0x92, 0x59, 0x8f, 0xfe, 0x9b, 0xd2, 0xa6, 0xe2, 0x91,
-       0x89, 0xe7, 0x93, 0xd3, 0x21, 0xc9, 0x59, 0x8f, 0xcb, 0x85, 0x19, 0x53,
-       0x26, 0x2b, 0xdb, 0x6f, 0x72, 0x65, 0xc6, 0xf6, 0xbc, 0x9c, 0x9f, 0x69,
-       0xc2, 0xb3, 0x79, 0x79, 0x79, 0xb3, 0x2e, 0x13, 0xb3, 0x6f, 0x89, 0x09,
-       0x1e, 0x0e, 0x29, 0x79, 0x3f, 0x2e, 0xff, 0xfc, 0x27, 0x22, 0x23, 0xe0,
-       0x8b, 0xde, 0xff, 0xef, 0xd5, 0x8c, 0x05, 0x7e, 0xf4, 0xf7, 0x41, 0x3f,
-       0x74, 0x5c, 0x29, 0xcf, 0x38, 0xc6, 0x98, 0x5a, 0xce, 0x39, 0x0d, 0x9b,
-       0x6a, 0xd5, 0xb2, 0xc7, 0x45, 0x0a, 0xc7, 0xab, 0x52, 0x48, 0x85, 0xe4,
-       0x01, 0xab, 0x2a, 0x43, 0xa9, 0x26, 0x39, 0x60, 0x75, 0xca, 0x44, 0xdf,
-       0xcf, 0x68, 0x3e, 0x96, 0x7d, 0xa5, 0x92, 0xc6, 0x3d, 0xfb, 0x44, 0x66,
-       0xd5, 0xbd, 0xdb, 0x5f, 0xac, 0x84, 0x24, 0x13, 0x2d, 0xc6, 0x4c, 0xb9,
-       0xa0, 0xb9, 0xb4, 0xed, 0xf4, 0x9f, 0x41, 0x5e, 0x63, 0xc0, 0x90, 0x84,
-       0xd2, 0xa5, 0xfc, 0xf4, 0x9a, 0x8b, 0x19, 0xd5, 0x1d, 0x52, 0x7a, 0x6a,
-       0xa4, 0x4d, 0xd2, 0x31, 0xa6, 0xa5, 0xa3, 0xd2, 0xad, 0xec, 0x64, 0x00,
-       0x63, 0x06, 0xb5, 0xbb, 0x2b, 0x94, 0x37, 0xee, 0xcb, 0xa4, 0x75, 0x03,
-       0xc6, 0x9a, 0xb8, 0x66, 0x3c, 0x9a, 0x83, 0x74, 0x72, 0x2e, 0xd2, 0xc9,
-       0xeb, 0xde, 0x00, 0x9d, 0xfb, 0x6a, 0xf7, 0xb3, 0x81, 0xfb, 0x62, 0xe5,
-       0xd7, 0x5b, 0x5c, 0xfa, 0xc8, 0xd7, 0x41, 0x99, 0x98, 0x7e, 0xc8, 0x5b,
-       0x0b, 0xf7, 0x65, 0xae, 0xb1, 0x00, 0x3e, 0xa9, 0x91, 0x57, 0x58, 0xab,
-       0x18, 0x58, 0xeb, 0x70, 0x60, 0xad, 0xc3, 0x81, 0xb5, 0x8a, 0xe0, 0xad,
-       0xac, 0xd3, 0x81, 0x33, 0x79, 0xc2, 0xbc, 0x1c, 0xc5, 0x9c, 0x6f, 0x88,
-       0x91, 0xa6, 0x2d, 0xf8, 0x36, 0xf9, 0x07, 0x18, 0x9f, 0x96, 0x73, 0x0e,
-       0x78, 0x73, 0x3c, 0x24, 0x77, 0xa9, 0x71, 0xff, 0xb1, 0xc6, 0xa5, 0x31,
-       0xf8, 0x2c, 0x2c, 0xbb, 0xa2, 0xbc, 0xf7, 0x9f, 0x99, 0xe0, 0x37, 0xdb,
-       0x93, 0x37, 0xb8, 0x6d, 0xde, 0x9f, 0xf5, 0xf6, 0xd2, 0xee, 0xbe, 0x57,
-       0x79, 0x53, 0x61, 0xc6, 0x62, 0x85, 0xb6, 0x2d, 0x29, 0xc3, 0x96, 0xfd,
-       0x43, 0xa9, 0x4e, 0x99, 0xb4, 0xb4, 0xd4, 0x44, 0xb2, 0x99, 0xfc, 0xcf,
-       0xe8, 0x76, 0x2b, 0xec, 0x47, 0xe2, 0x3a, 0x71, 0x51, 0xed, 0xeb, 0x5b,
-       0x1e, 0xfd, 0x16, 0xdb, 0x23, 0xba, 0xdd, 0xd1, 0xd0, 0x4f, 0xfd, 0xff,
-       0x4b, 0xdc, 0xd3, 0x06, 0xfa, 0x75, 0x77, 0xed, 0xbf, 0x42, 0x9b, 0x58,
-       0x15, 0xf1, 0xda, 0xfe, 0xf3, 0xff, 0x32, 0x96, 0xb7, 0x8f, 0x6d, 0x5c,
-       0xde, 0xf6, 0x6d, 0x29, 0x88, 0x73, 0xdc, 0x2b, 0x6c, 0xd8, 0xa6, 0xfe,
-       0x85, 0x40, 0x6b, 0x0a, 0x36, 0xdc, 0xec, 0xd1, 0xf0, 0xba, 0x47, 0x03,
-       0x68, 0xc5, 0xb8, 0x89, 0x0a, 0xdf, 0x51, 0xa2, 0x6c, 0x68, 0x93, 0xf7,
-       0xfe, 0xfd, 0x5a, 0xf5, 0xfc, 0x0d, 0x83, 0xeb, 0xf8, 0x57, 0xd1, 0x86,
-       0x60, 0x67, 0x93, 0xb3, 0xa6, 0xe4, 0x53, 0x31, 0x65, 0x0f, 0xf9, 0x54,
-       0x1d, 0x3f, 0x26, 0xa7, 0x1b, 0xf1, 0x83, 0xef, 0x11, 0x3f, 0x5c, 0xec,
-       0x98, 0x98, 0x25, 0x8e, 0xd4, 0x71, 0xe3, 0xc8, 0xb4, 0x8f, 0x25, 0x9c,
-       0x9b, 0x18, 0xe2, 0xe3, 0x07, 0xdf, 0x23, 0x7e, 0x18, 0x90, 0x15, 0xe7,
-       0xf4, 0xd7, 0x9f, 0x6a, 0x98, 0x7b, 0x4a, 0x61, 0x93, 0x8b, 0xcb, 0x6f,
-       0x06, 0x70, 0xbe, 0x0b, 0x18, 0x1d, 0x85, 0xfc, 0x7c, 0x8c, 0x26, 0x76,
-       0xc6, 0x80, 0xeb, 0xe0, 0x91, 0xc2, 0xe4, 0x08, 0x70, 0xcc, 0xf4, 0x30,
-       0x35, 0xec, 0x61, 0x6a, 0x04, 0x78, 0xca, 0xb6, 0xe5, 0xb5, 0xa3, 0x5e,
-       0x3b, 0x86, 0x36, 0xfc, 0xef, 0x1c, 0x6d, 0xec, 0xb5, 0x43, 0xe3, 0xb3,
-       0x0a, 0xa7, 0x89, 0xf1, 0xc0, 0x0a, 0xe2, 0x2c, 0xf1, 0xb6, 0x4b, 0x16,
-       0xca, 0x58, 0xaf, 0x86, 0x69, 0x94, 0x47, 0x90, 0x1e, 0xd2, 0xb2, 0x46,
-       0xf4, 0xc7, 0xdc, 0xfd, 0xe8, 0xe9, 0xcf, 0xeb, 0xd2, 0xc2, 0x7d, 0x90,
-       0xee, 0x1b, 0x41, 0x2b, 0xf7, 0xf6, 0xa3, 0xa4, 0x95, 0xeb, 0x35, 0xd2,
-       0x7b, 0x1a, 0xf4, 0x66, 0x80, 0xb7, 0xa2, 0x8d, 0xf6, 0x8e, 0x82, 0xde,
-       0x11, 0x60, 0xf1, 0x30, 0xb0, 0x78, 0x27, 0xb0, 0x78, 0x08, 0x58, 0x9c,
-       0x06, 0x0e, 0x0f, 0x02, 0x87, 0x07, 0x80, 0xc3, 0x29, 0xec, 0x2b, 0x2a,
-       0xf3, 0xc0, 0xe5, 0x79, 0xe0, 0xf3, 0x3c, 0xe4, 0x35, 0x31, 0x27, 0xda,
-       0x17, 0xb0, 0xfe, 0x63, 0x33, 0x89, 0xd3, 0xd0, 0xcd, 0x58, 0x51, 0x87,
-       0x3d, 0xa5, 0x06, 0xa1, 0x23, 0x49, 0x29, 0x55, 0x46, 0xa5, 0x40, 0x3f,
-       0xb6, 0xb9, 0x07, 0xb6, 0x0b, 0xfb, 0x89, 0xf9, 0x71, 0xd3, 0x5a, 0xef,
-       0xfa, 0xf7, 0x22, 0xf6, 0x1f, 0x83, 0x27, 0x89, 0xb8, 0xc8, 0xb0, 0xe4,
-       0x9d, 0x1e, 0x2b, 0xab, 0x27, 0x31, 0x8e, 0xed, 0xb8, 0xb6, 0xf7, 0x78,
-       0x42, 0x1b, 0x3f, 0xce, 0x3d, 0x4d, 0x03, 0xe3, 0xaa, 0x32, 0x95, 0xa2,
-       0xad, 0x56, 0xe5, 0x54, 0x2a, 0x31, 0x58, 0x94, 0x56, 0x39, 0x12, 0x9d,
-       0x56, 0xfe, 0xcd, 0x4c, 0x1f, 0x53, 0xfa, 0x51, 0xb0, 0x71, 0x2d, 0x77,
-       0x6b, 0xf9, 0xe3, 0xf4, 0x3b, 0x3d, 0xf8, 0x85, 0x40, 0x0b, 0xe7, 0x37,
-       0x65, 0x68, 0x40, 0xb4, 0x7d, 0xbd, 0x45, 0xa0, 0x62, 0xc2, 0x3a, 0x87,
-       0x95, 0x73, 0xd3, 0x3d, 0xb1, 0x9c, 0x6e, 0xca, 0x98, 0xa9, 0xc9, 0x04,
-       0xec, 0x65, 0x28, 0xf5, 0x7f, 0xd5, 0x23, 0x51, 0x3e, 0x6f, 0x96, 0xdf,
-       0x51, 0x38, 0x8b, 0xb5, 0x4b, 0xb3, 0x58, 0x37, 0x04, 0xfe, 0x71, 0x5d,
-       0xce, 0x83, 0x36, 0x30, 0xcf, 0xb4, 0x13, 0xa7, 0x8b, 0xb2, 0x1d, 0x76,
-       0xb7, 0x4e, 0xb2, 0x7d, 0x4d, 0x92, 0x19, 0x89, 0xcb, 0xc4, 0xcc, 0x76,
-       0xe0, 0x1e, 0x64, 0x60, 0xb7, 0x48, 0x7e, 0x34, 0x2e, 0x5f, 0x9e, 0x61,
-       0x5f, 0x06, 0xfb, 0x4f, 0x1c, 0xcd, 0x08, 0xf7, 0x1f, 0x52, 0xfb, 0x8a,
-       0xeb, 0x19, 0x39, 0xe0, 0xbc, 0xa4, 0xbb, 0x76, 0xe9, 0xb6, 0xf7, 0x42,
-       0x1e, 0xa7, 0xc0, 0xef, 0xbc, 0x63, 0xcb, 0x02, 0xfc, 0x4a, 0xee, 0x38,
-       0x70, 0xd5, 0x6e, 0x03, 0x06, 0x26, 0xce, 0xd2, 0x3e, 0x0c, 0xc4, 0x5a,
-       0x25, 0xc5, 0xeb, 0x2e, 0x39, 0x3e, 0xa3, 0xcb, 0xb3, 0xb7, 0xc5, 0xd1,
-       0x06, 0xd6, 0xa6, 0x12, 0x67, 0xc6, 0xf4, 0x2e, 0xb9, 0xb5, 0x23, 0x86,
-       0xf7, 0x52, 0x5a, 0xde, 0xf9, 0x37, 0xf2, 0xf2, 0x64, 0x5c, 0xe7, 0x58,
-       0x5d, 0x72, 0x29, 0x03, 0x3a, 0x56, 0xc4, 0xf8, 0x7f, 0x40, 0x7f, 0x97,
-       0xcc, 0x21, 0xbe, 0x99, 0x03, 0x4d, 0xd9, 0x14, 0xb1, 0x30, 0x71, 0x72,
-       0x49, 0x07, 0x66, 0xcd, 0x41, 0x37, 0x47, 0x11, 0x3f, 0xcc, 0xfc, 0x37,
-       0xc6, 0xc4, 0x21, 0xd3, 0x1e, 0x6b, 0x02, 0xf8, 0x92, 0xe9, 0xe2, 0x3d,
-       0xe7, 0xb4, 0xe5, 0x94, 0x43, 0x1d, 0x8a, 0xcb, 0xe3, 0x15, 0xbe, 0xd7,
-       0x73, 0xf6, 0x69, 0xb1, 0xe5, 0x41, 0xe7, 0x7f, 0x30, 0xfe, 0x1d, 0xc4,
-       0x9e, 0x96, 0x94, 0x20, 0xb7, 0x02, 0x78, 0x99, 0x89, 0xb9, 0xed, 0x89,
-       0xb9, 0xc4, 0xd9, 0x0b, 0x3a, 0xef, 0xed, 0xe2, 0x82, 0x7e, 0xb3, 0x48,
-       0x07, 0xf9, 0x99, 0x02, 0x2f, 0x6d, 0x4b, 0xd7, 0x37, 0x7b, 0xf1, 0x16,
-       0x6d, 0xc0, 0x06, 0x7d, 0xa6, 0x2c, 0xf4, 0x07, 0x6d, 0x80, 0x7e, 0xd6,
-       0xb7, 0x81, 0x44, 0x6c, 0x49, 0xd7, 0xf1, 0xdc, 0x94, 0x63, 0xaa, 0xad,
-       0x81, 0xd6, 0x44, 0x8c, 0xfb, 0x9b, 0x2c, 0x27, 0xe5, 0x71, 0x87, 0xe3,
-       0xc1, 0xe7, 0xe9, 0x88, 0x37, 0x1e, 0xf1, 0x8e, 0xc3, 0x98, 0x29, 0x09,
-       0x9a, 0x5d, 0xbb, 0x58, 0x98, 0x8e, 0xaa, 0x67, 0x47, 0x1c, 0x37, 0x36,
-       0xd2, 0x11, 0x3f, 0xcd, 0x23, 0x7e, 0xca, 0x29, 0x1b, 0xb1, 0x32, 0x88,
-       0xaf, 0xe1, 0x67, 0x5d, 0xfb, 0x28, 0x95, 0x49, 0xcb, 0x3d, 0xa0, 0x2f,
-       0x51, 0x04, 0x31, 0xc7, 0x74, 0xb8, 0xeb, 0xec, 0x80, 0x14, 0x19, 0x63,
-       0x9d, 0x33, 0x1e, 0x91, 0xb1, 0x12, 0xfd, 0x1b, 0x7e, 0x8e, 0x6d, 0x31,
-       0xa6, 0xcf, 0x28, 0xdf, 0xd3, 0x03, 0x3d, 0x80, 0x5f, 0x4a, 0xb5, 0x8b,
-       0xeb, 0x07, 0xf7, 0x40, 0x9e, 0xc3, 0x90, 0x7b, 0x5a, 0xc6, 0x4f, 0x8c,
-       0x53, 0xa7, 0x93, 0x25, 0x49, 0x24, 0x8f, 0xc8, 0x16, 0x6b, 0x01, 0xbe,
-       0x30, 0x33, 0x5a, 0xdd, 0xae, 0xa7, 0xf9, 0xce, 0xa3, 0x78, 0x07, 0xd7,
-       0xd2, 0xb8, 0x3c, 0x50, 0x61, 0xdf, 0x9d, 0x86, 0xb4, 0xc0, 0x56, 0x06,
-       0xf6, 0x78, 0x76, 0x80, 0xf9, 0x4c, 0x7f, 0xbe, 0x71, 0x6f, 0x3e, 0x8e,
-       0xe3, 0x18, 0xbe, 0x53, 0x9f, 0x77, 0x07, 0x7d, 0x1b, 0xb0, 0x64, 0x87,
-       0x5e, 0xdd, 0x1e, 0xc2, 0xf3, 0x53, 0x03, 0xbc, 0xc7, 0x3c, 0xf0, 0x6d,
-       0x96, 0x3d, 0x8c, 0xb1, 0xa3, 0x98, 0x73, 0x8d, 0x64, 0x3b, 0x7d, 0x7a,
-       0xa9, 0x03, 0x8c, 0x3f, 0xd8, 0x8e, 0xae, 0x77, 0x79, 0xff, 0x25, 0xc3,
-       0xd5, 0xc9, 0x11, 0xb4, 0x69, 0x7f, 0x07, 0x25, 0xe7, 0x24, 0xb0, 0x4f,
-       0xf0, 0xb6, 0x32, 0xe1, 0xed, 0x11, 0xfc, 0x1f, 0x39, 0x0c, 0x3e, 0x48,
-       0xd1, 0xe5, 0x0d, 0xf9, 0x42, 0x9e, 0xfc, 0x16, 0x74, 0xff, 0x61, 0x8c,
-       0x81, 0x7f, 0x50, 0x3c, 0x58, 0xea, 0x70, 0x63, 0xd1, 0x44, 0x31, 0xc3,
-       0xfc, 0xa9, 0x83, 0x98, 0x07, 0xfc, 0xa9, 0x40, 0xb1, 0x30, 0xf7, 0x92,
-       0xbe, 0x86, 0xf4, 0xc6, 0x97, 0x0c, 0x83, 0xed, 0xe4, 0x12, 0x74, 0xb8,
-       0x04, 0xf9, 0x64, 0xfb, 0x68, 0xb3, 0x36, 0xe4, 0x31, 0x63, 0x50, 0x5f,
-       0x4b, 0x88, 0x05, 0xf3, 0xce, 0x16, 0xeb, 0x5e, 0xf2, 0xcd, 0xb2, 0xe4,
-       0x69, 0x27, 0x88, 0x1d, 0x3b, 0x30, 0x94, 0x7a, 0x18, 0x85, 0x1e, 0x98,
-       0xf0, 0xc9, 0x31, 0xc8, 0xfc, 0xc5, 0x0e, 0x77, 0x2f, 0xbc, 0x37, 0x65,
-       0xde, 0xc2, 0x9a, 0xce, 0xef, 0xaf, 0x73, 0xfb, 0x78, 0xcf, 0xb8, 0xc8,
-       0x97, 0xab, 0x4f, 0x3b, 0xe5, 0xdb, 0x28, 0xd3, 0x43, 0xd8, 0x0b, 0xfb,
-       0x71, 0x2d, 0x1d, 0x94, 0x71, 0xd0, 0x56, 0x18, 0xd8, 0x14, 0x3b, 0x8f,
-       0xf1, 0x39, 0xe0, 0x79, 0xd1, 0xe4, 0xb3, 0x8b, 0x5a, 0xfd, 0x1d, 0xc4,
-       0x5c, 0x36, 0xfd, 0xd9, 0x92, 0xf6, 0x85, 0xca, 0xcb, 0x5a, 0xb6, 0x74,
-       0x51, 0xcb, 0x41, 0x4f, 0x4a, 0x0e, 0x73, 0x06, 0xda, 0x8f, 0x85, 0xb5,
-       0x13, 0xb1, 0xb7, 0xf5, 0x9e, 0xf8, 0x02, 0xb0, 0x60, 0x2f, 0x6c, 0x3a,
-       0x67, 0xee, 0x94, 0x02, 0xb0, 0x35, 0x7f, 0x62, 0x0b, 0xec, 0x2d, 0x1e,
-       0xa0, 0x8b, 0x78, 0x56, 0xa4, 0x4f, 0xd5, 0x76, 0x38, 0x52, 0x6c, 0x4a,
-       0x13, 0xd7, 0x36, 0x41, 0x77, 0xd0, 0x57, 0xae, 0xeb, 0xdf, 0x1d, 0x2b,
-       0x68, 0x45, 0x7e, 0x39, 0xb0, 0x9c, 0xde, 0x92, 0x5c, 0x99, 0xde, 0x1d,
-       0x35, 0x7a, 0x89, 0x19, 0xc0, 0x7f, 0xd8, 0xcd, 0x4b, 0xd0, 0xdf, 0xe7,
-       0x1d, 0xe0, 0xbf, 0x03, 0xfc, 0x87, 0x4d, 0x3d, 0x03, 0xdd, 0x7b, 0xda,
-       0x81, 0x0f, 0x70, 0xe0, 0x03, 0x1c, 0xf8, 0x00, 0x27, 0x0b, 0x39, 0x11,
-       0xe7, 0xe9, 0x43, 0x76, 0xd7, 0x7c, 0x9e, 0x1b, 0x37, 0xdd, 0xe0, 0xc5,
-       0x22, 0xa3, 0x88, 0x45, 0x36, 0xc8, 0x44, 0xf2, 0x7a, 0xec, 0xad, 0x05,
-       0xd7, 0x56, 0x5c, 0xb1, 0x46, 0xf2, 0x76, 0xcf, 0x4e, 0x1e, 0x06, 0x5d,
-       0x88, 0xbf, 0x93, 0x3f, 0x0d, 0x3d, 0x6c, 0x02, 0x3d, 0x3f, 0xe5, 0xc5,
-       0x2c, 0x0f, 0x9a, 0xae, 0x1e, 0xb6, 0xa2, 0xef, 0x93, 0xe8, 0x6b, 0xc5,
-       0x98, 0x03, 0x18, 0xc3, 0x98, 0xa7, 0xcd, 0xeb, 0x0b, 0x8e, 0x63, 0xec,
-       0xf3, 0x19, 0xac, 0x95, 0xc0, 0xb8, 0x36, 0xcc, 0xdd, 0x85, 0x31, 0xdb,
-       0x30, 0xe6, 0x46, 0xb4, 0x19, 0x33, 0x6f, 0x44, 0xfb, 0x13, 0x0d, 0xef,
-       0x7c, 0x0c, 0x7d, 0xb7, 0x37, 0xf4, 0x9d, 0x43, 0x1f, 0xf2, 0x50, 0xeb,
-       0xbc, 0xf7, 0x5e, 0x11, 0xed, 0xce, 0x86, 0x31, 0xaf, 0xa2, 0x0f, 0x71,
-       0xaf, 0xf5, 0x2d, 0x5c, 0x91, 0x7f, 0x5a, 0xa4, 0xc9, 0x7f, 0xc6, 0xb8,
-       0x37, 0x8e, 0xfe, 0x90, 0x17, 0xbb, 0xfe, 0xa6, 0x09, 0xbd, 0xd3, 0x86,
-       0x9c, 0xdf, 0x30, 0xdd, 0x58, 0xef, 0x4e, 0xcb, 0xd5, 0x43, 0xbf, 0xfd,
-       0x70, 0x43, 0x9b, 0x63, 0x17, 0x1a, 0xfa, 0xfe, 0xa5, 0xa1, 0xfd, 0xdd,
-       0xd0, 0xca, 0x77, 0x06, 0xdb, 0x97, 0xf7, 0x15, 0x3a, 0x96, 0xb7, 0xed,
-       0xa6, 0x95, 0xef, 0xe8, 0xeb, 0x96, 0xf7, 0xdd, 0xb8, 0xbe, 0x61, 0x0c,
-       0x74, 0x2a, 0x8a, 0x1c, 0xc9, 0x1f, 0x1f, 0xbe, 0xce, 0x7d, 0x4e, 0xfe,
-       0x36, 0xea, 0x92, 0xda, 0x3a, 0xda, 0x3a, 0xe4, 0xb0, 0xa4, 0xc1, 0x9e,
-       0x2c, 0x3d, 0xfd, 0xb2, 0x96, 0x83, 0x4e, 0x65, 0x2b, 0xfe, 0x7c, 0xb4,
-       0xd9, 0xc6, 0xdc, 0xdc, 0xcf, 0xc9, 0x19, 0x2b, 0x45, 0xa0, 0x37, 0xf7,
-       0xd0, 0x27, 0x1d, 0x2d, 0x4a, 0xdd, 0x3e, 0xbb, 0xf5, 0x4b, 0xd9, 0xe7,
-       0xed, 0x1e, 0x46, 0x1d, 0x06, 0x9d, 0x55, 0x19, 0x49, 0x35, 0xd3, 0xc7,
-       0x78, 0xd8, 0x45, 0xdc, 0xa9, 0x56, 0x8d, 0xcd, 0x55, 0xd9, 0x9f, 0x7a,
-       0xa7, 0x2a, 0x0a, 0xf3, 0x06, 0x15, 0xee, 0xc4, 0xf5, 0x1e, 0xc8, 0xc8,
-       0x42, 0x6e, 0x82, 0x7c, 0x3a, 0x4a, 0x9f, 0x74, 0x90, 0xf1, 0xc9, 0xa3,
-       0x2e, 0xa6, 0x12, 0x77, 0xd0, 0x46, 0x5e, 0x96, 0x3f, 0xce, 0xf5, 0x71,
-       0x2d, 0x11, 0xc7, 0x47, 0x95, 0x4f, 0xc9, 0x5b, 0x9c, 0x77, 0x35, 0x6c,
-       0x3c, 0x6b, 0x32, 0xa6, 0x33, 0xed, 0xd3, 0xf0, 0x6f, 0x7c, 0xc6, 0x58,
-       0xe1, 0x34, 0xe3, 0x92, 0x00, 0x56, 0x6d, 0x35, 0xe0, 0x32, 0x8b, 0xcb,
-       0xf7, 0xb5, 0x81, 0x79, 0xc4, 0x55, 0xec, 0x75, 0x75, 0x2c, 0xea, 0xd1,
-       0xaf, 0x6c, 0xdb, 0xbb, 0x6a, 0xb6, 0xed, 0xeb, 0xde, 0x6a, 0x39, 0xf8,
-       0xf7, 0x95, 0x2c, 0x9e, 0xaa, 0x24, 0x8e, 0x15, 0x61, 0x4b, 0x8b, 0x2a,
-       0xef, 0xf6, 0xe5, 0xc2, 0x18, 0x27, 0x71, 0x72, 0x1e, 0x6f, 0x8e, 0xab,
-       0x1c, 0x83, 0xf9, 0x45, 0x55, 0x76, 0xa4, 0x5a, 0xa3, 0xe4, 0x43, 0x46,
-       0xff, 0x76, 0x88, 0x31, 0xc3, 0xa2, 0x43, 0x9e, 0xa5, 0xf0, 0x3c, 0x05,
-       0x4c, 0xf8, 0x27, 0xc9, 0x45, 0xd9, 0xf7, 0x76, 0x75, 0x01, 0x71, 0x95,
-       0x8a, 0x8f, 0x94, 0xbf, 0x67, 0x7c, 0xb7, 0x1f, 0xfc, 0x22, 0x4f, 0x47,
-       0xc0, 0x67, 0x3f, 0x06, 0x78, 0x8d, 0x75, 0x15, 0x59, 0x1e, 0x07, 0x8b,
-       0x3c, 0x50, 0x7e, 0x19, 0x73, 0xea, 0x6e, 0xac, 0xc2, 0x3c, 0xdc, 0x66,
-       0x7f, 0x47, 0x88, 0xb1, 0x9c, 0xeb, 0xeb, 0x0d, 0xac, 0x87, 0xdc, 0xbe,
-       0xfc, 0x8f, 0x2a, 0x6e, 0x2a, 0x28, 0x79, 0x20, 0x86, 0xaa, 0xf0, 0x19,
-       0xfb, 0xc2, 0x5e, 0xec, 0x1c, 0xf1, 0x62, 0x65, 0xcb, 0x8b, 0x95, 0x49,
-       0x07, 0x6b, 0x6f, 0x7e, 0x5c, 0x40, 0x99, 0x2d, 0x1d, 0xd2, 0x37, 0x33,
-       0x2e, 0x68, 0x93, 0xd5, 0xe3, 0x02, 0x9f, 0xa6, 0x6d, 0xa0, 0x89, 0x71,
-       0x9e, 0xaa, 0xbd, 0x74, 0xb8, 0xf5, 0x1e, 0xd2, 0xe0, 0xfb, 0x47, 0xe5,
-       0x87, 0x8f, 0xc2, 0xe5, 0x61, 0x6f, 0x69, 0xd0, 0xba, 0x53, 0xb2, 0xd3,
-       0xdb, 0x3c, 0x7f, 0xcb, 0x1c, 0x80, 0xf1, 0xb7, 0xab, 0xb3, 0xd9, 0xd4,
-       0x84, 0x3f, 0x4f, 0x27, 0x3c, 0x64, 0xa0, 0x2e, 0xc4, 0xb5, 0x18, 0xc7,
-       0xf8, 0x31, 0xcd, 0x4e, 0x2f, 0xa6, 0x19, 0x96, 0xfd, 0x8e, 0x1b, 0xf3,
-       0x8f, 0xa0, 0x3f, 0xef, 0x28, 0xda, 0x63, 0x8c, 0x2d, 0x75, 0xc4, 0xdc,
-       0x99, 0x3d, 0x09, 0x24, 0x0f, 0xee, 0x5e, 0xba, 0xb1, 0x97, 0x52, 0x6d,
-       0x2f, 0xad, 0x4b, 0xcb, 0xf7, 0x32, 0xaa, 0xde, 0x9d, 0x5a, 0xf1, 0xae,
-       0x60, 0x1f, 0xbb, 0x2f, 0xf1, 0x8c, 0x7b, 0x64, 0xdc, 0x60, 0x79, 0x7b,
-       0xf4, 0xe5, 0x74, 0x00, 0x7b, 0x4c, 0x6a, 0x79, 0x15, 0x6b, 0xed, 0x51,
-       0x3c, 0xcf, 0x97, 0xc7, 0x70, 0xa5, 0x7d, 0xa8, 0x79, 0x94, 0x8d, 0x4c,
-       0x28, 0x3e, 0x8f, 0xab, 0x7d, 0x2c, 0x94, 0x7f, 0x41, 0x0a, 0x27, 0x7e,
-       0x09, 0x7e, 0x2f, 0x58, 0x0f, 0x63, 0x2d, 0x91, 0xfc, 0x28, 0x06, 0xf0,
-       0x93, 0x7b, 0x65, 0xad, 0xeb, 0x0f, 0x43, 0x6e, 0x7e, 0x10, 0x81, 0x8c,
-       0x35, 0xf7, 0xb9, 0x5a, 0xdf, 0xe7, 0x6b, 0x53, 0x80, 0x9e, 0x2a, 0x62,
-       0xce, 0x18, 0x68, 0x08, 0xbe, 0x73, 0x50, 0x86, 0x1c, 0xca, 0xa3, 0x27,
-       0x36, 0x2e, 0xb6, 0x95, 0x17, 0x3f, 0xce, 0xe0, 0xfa, 0xb4, 0xf9, 0x5c,
-       0xcc, 0x10, 0xd6, 0x2f, 0x7d, 0xde, 0xf9, 0x7c, 0x8b, 0x2c, 0x35, 0xea,
-       0xc0, 0x14, 0xe8, 0x29, 0x38, 0xe4, 0x93, 0xaf, 0x9b, 0xfe, 0xda, 0xaf,
-       0xaa, 0xfd, 0x4c, 0xaa, 0x9a, 0xdd, 0x73, 0x35, 0x1d, 0x9d, 0x40, 0x0c,
-       0xe2, 0xea, 0xdc, 0x7d, 0x1e, 0x6f, 0x7c, 0xdd, 0x8c, 0x78, 0x72, 0x66,
-       0x1e, 0x47, 0xdb, 0xf1, 0xf5, 0x60, 0x93, 0x75, 0xb7, 0xe2, 0x05, 0x9f,
-       0x11, 0x53, 0x5c, 0x59, 0x8e, 0xd5, 0x64, 0xb9, 0xb6, 0x41, 0x2f, 0xbf,
-       0xb7, 0xce, 0xb5, 0x43, 0xda, 0x1b, 0xec, 0x16, 0xf4, 0x3d, 0xb5, 0xcc,
-       0xbe, 0x93, 0x97, 0xa8, 0x83, 0x46, 0xc4, 0x98, 0xfb, 0x53, 0xf0, 0xf2,
-       0x63, 0xc8, 0x55, 0x44, 0xcc, 0x19, 0xe2, 0x10, 0xe3, 0x8d, 0x7a, 0xbc,
-       0xbb, 0x20, 0xab, 0xc5, 0xba, 0x57, 0x8a, 0x35, 0x7e, 0xf2, 0x2a, 0x63,
-       0x8d, 0x78, 0x93, 0xb4, 0x10, 0x8b, 0x86, 0x11, 0xdb, 0x6a, 0xd2, 0x64,
-       0x3f, 0x08, 0x1f, 0x76, 0xc6, 0x6c, 0xb6, 0x7d, 0x4c, 0x88, 0x48, 0xfb,
-       0xdc, 0x06, 0x85, 0x0b, 0xd6, 0x4c, 0x1d, 0x17, 0x26, 0xc0, 0xfb, 0x11,
-       0xb7, 0xb6, 0x1a, 0x6d, 0x97, 0xab, 0xcd, 0x8d, 0xeb, 0x71, 0xff, 0x58,
-       0x2d, 0xee, 0xbf, 0xa1, 0x81, 0x8f, 0xab, 0xe1, 0xe2, 0x19, 0xf0, 0x2d,
-       0x8d, 0xfc, 0x97, 0x79, 0xed, 0x10, 0xf2, 0x61, 0xe6, 0x62, 0x19, 0xe4,
-       0xc4, 0x89, 0x33, 0xc0, 0x2a, 0xe4, 0xc8, 0x89, 0xb7, 0xe0, 0x57, 0x90,
-       0x37, 0x27, 0xe6, 0x99, 0xbb, 0x2e, 0x22, 0x3f, 0x7e, 0x1a, 0xf9, 0xf1,
-       0x53, 0x95, 0x3e, 0xf0, 0x37, 0xa9, 0xb0, 0x73, 0xef, 0x71, 0xd1, 0xee,
-       0x52, 0xf5, 0x61, 0xda, 0x73, 0x14, 0x7e, 0xb4, 0x5a, 0x3d, 0x90, 0xea,
-       0x41, 0x4e, 0x1e, 0x97, 0x4f, 0x99, 0xcc, 0x63, 0x35, 0xb3, 0xbb, 0x7f,
-       0xc1, 0x08, 0xc6, 0xa4, 0xd9, 0x2b, 0xfa, 0x81, 0x95, 0xbc, 0xcf, 0x29,
-       0x5f, 0x70, 0xcc, 0xb8, 0x1c, 0xef, 0xef, 0xaa, 0xf1, 0xfe, 0xc2, 0x1a,
-       0x69, 0x19, 0x56, 0x35, 0x80, 0xee, 0xfe, 0x03, 0xc4, 0xab, 0x14, 0xfc,
-       0x3a, 0xfc, 0x6f, 0x55, 0xee, 0x48, 0x5d, 0xac, 0x9e, 0xb7, 0xd7, 0x49,
-       0xbe, 0xef, 0x8b, 0x1e, 0x66, 0x8f, 0x3d, 0x92, 0xb5, 0x8b, 0xb0, 0x0f,
-       0xb7, 0x16, 0x39, 0x3e, 0x1d, 0x46, 0x14, 0xca, 0xbf, 0x0e, 0x59, 0x18,
-       0xfc, 0x1b, 0xc8, 0x70, 0xcb, 0x69, 0x16, 0xb0, 0x74, 0xe0, 0xf0, 0x42,
-       0x34, 0xa2, 0xea, 0x33, 0xd7, 0xd9, 0xec, 0xb7, 0x20, 0xd3, 0x51, 0x59,
-       0x40, 0xfc, 0x50, 0x1a, 0x04, 0x8d, 0x7d, 0x9d, 0x18, 0x4f, 0xbb, 0x23,
-       0xcf, 0x47, 0xe1, 0x7b, 0xc9, 0xd3, 0x28, 0xc6, 0xef, 0xc2, 0x98, 0x0e,
-       0x5c, 0xbf, 0x68, 0x2c, 0x58, 0xcc, 0x9d, 0x7f, 0x0e, 0x6d, 0xce, 0x11,
-       0xf4, 0x9d, 0x9f, 0x0e, 0x89, 0x9a, 0x93, 0xef, 0x74, 0x2a, 0xfb, 0xaf,
-       0xaf, 0xc5, 0x75, 0xf8, 0xec, 0xbd, 0xea, 0x2d, 0xfd, 0x83, 0x81, 0xf5,
-       0xda, 0x02, 0xeb, 0x0d, 0x06, 0xd6, 0x23, 0x9d, 0x1d, 0x01, 0x3a, 0x3b,
-       0xf0, 0x7e, 0x0e, 0x6b, 0x0f, 0xab, 0x98, 0xa7, 0xbe, 0xe6, 0xfd, 0x81,
-       0x35, 0xfd, 0xfd, 0x75, 0x06, 0xde, 0x7b, 0x07, 0xeb, 0xb1, 0x2f, 0x1a,
-       0xe8, 0x23, 0x0d, 0xeb, 0xd1, 0xc7, 0x76, 0x47, 0x80, 0x2e, 0xd2, 0xba,
-       0x16, 0xfd, 0x2a, 0x7e, 0x02, 0x9f, 0x5b, 0xe0, 0xb7, 0x74, 0xf8, 0x0e,
-       0xd6, 0xa0, 0x1b, 0xf7, 0xfa, 0x65, 0xac, 0xeb, 0xcf, 0x17, 0xc5, 0x1c,
-       0x1c, 0xcf, 0xb1, 0x86, 0xf7, 0x3e, 0xfb, 0xf9, 0xfc, 0x1b, 0xd5, 0xaf,
-       0x2b, 0xbe, 0xad, 0x07, 0xed, 0xaa, 0xee, 0x22, 0xf3, 0x1d, 0x26, 0xe4,
-       0xc9, 0xfc, 0x58, 0x93, 0x9b, 0x6c, 0x5d, 0xeb, 0xe9, 0xa7, 0xec, 0xd7,
-       0x79, 0x58, 0xda, 0xa2, 0x65, 0x8f, 0xb3, 0x5e, 0xd0, 0xea, 0xe5, 0x7c,
-       0xc8, 0x3d, 0x94, 0x8f, 0x31, 0xbd, 0xe7, 0xf4, 0x31, 0x8c, 0x5b, 0xe8,
-       0x3f, 0x33, 0xde, 0x3d, 0xae, 0xd0, 0xe1, 0x7d, 0xa5, 0x0e, 0x39, 0xaf,
-       0x78, 0x6a, 0xc9, 0xb9, 0x1a, 0x4f, 0x43, 0xde, 0xb7, 0x90, 0x83, 0xde,
-       0x77, 0x06, 0x03, 0x71, 0x11, 0xee, 0xcb, 0x19, 0xd0, 0x10, 0x97, 0x9e,
-       0x7e, 0xe6, 0x6e, 0x45, 0x5c, 0x59, 0xa7, 0xd0, 0x70, 0x75, 0xeb, 0x17,
-       0x3d, 0xfd, 0xf0, 0x4b, 0xc0, 0xa1, 0x9e, 0xfe, 0xef, 0xa8, 0x7c, 0xae,
-       0x54, 0xb1, 0xb4, 0x3b, 0x1c, 0xb7, 0x46, 0x74, 0xce, 0xbe, 0x5c, 0x8d,
-       0x68, 0xa0, 0x99, 0x75, 0x0d, 0xbf, 0x46, 0x74, 0x4e, 0x54, 0x8d, 0xe8,
-       0xe4, 0x15, 0x6a, 0x44, 0x99, 0xab, 0xaf, 0x11, 0x71, 0x7e, 0x53, 0xee,
-       0x1e, 0x10, 0xed, 0x4b, 0x5e, 0x8d, 0xe8, 0x82, 0xb8, 0x35, 0xa2, 0xf3,
-       0xb2, 0x7a, 0x8d, 0xe8, 0x68, 0x43, 0x8d, 0x68, 0xbd, 0xaa, 0x11, 0x71,
-       0x1e, 0xb7, 0x46, 0xc4, 0x76, 0xbe, 0x7f, 0x30, 0x50, 0xeb, 0x00, 0xfe,
-       0x3a, 0xb7, 0x82, 0x6f, 0x96, 0x36, 0xea, 0xf8, 0x98, 0x46, 0xec, 0xbf,
-       0xbe, 0xe6, 0xbf, 0xea, 0xf8, 0xa6, 0x29, 0x9d, 0xbb, 0x12, 0xbe, 0x8d,
-       0xba, 0x71, 0xc9, 0x32, 0x6c, 0x9b, 0xaa, 0xc5, 0x2e, 0xbf, 0xdc, 0xcc,
-       0x1c, 0x7a, 0xb2, 0x5c, 0x9f, 0x77, 0x12, 0xf2, 0x1e, 0xab, 0xd5, 0x49,
-       0x2e, 0x15, 0x1f, 0x45, 0xe5, 0xe0, 0xaa, 0xdf, 0x9a, 0x62, 0x99, 0x95,
-       0xdf, 0x9a, 0x34, 0x89, 0x82, 0xce, 0x7c, 0x7f, 0x5e, 0xe5, 0x5d, 0x0b,
-       0xce, 0xcf, 0xcb, 0xd2, 0xbd, 0x16, 0xf0, 0xc7, 0xaf, 0x9f, 0x50, 0xbe,
-       0x75, 0x9f, 0x92, 0xd5, 0x3f, 0xba, 0x1a, 0xca, 0x3e, 0x55, 0x43, 0xf9,
-       0x5a, 0x73, 0xb0, 0x86, 0x72, 0x4e, 0x2e, 0x5f, 0x43, 0xd9, 0xb7, 0x4a,
-       0x0d, 0xe5, 0x15, 0xa9, 0xd7, 0x50, 0x5e, 0x11, 0xbf, 0x86, 0x62, 0xc8,
-       0xd2, 0x7a, 0xce, 0xb3, 0x1f, 0xef, 0x8c, 0xe0, 0x37, 0x8c, 0x9f, 0x5b,
-       0x53, 0x39, 0x57, 0xa3, 0x7f, 0xb5, 0x9a, 0xca, 0x37, 0x9b, 0xdf, 0x4f,
-       0x4d, 0xc5, 0xf5, 0x01, 0x7e, 0x4d, 0xa5, 0x05, 0xf1, 0x0e, 0x7c, 0x8e,
-       0x1e, 0xac, 0xa9, 0xfc, 0x2d, 0xed, 0x01, 0x7d, 0x2a, 0x46, 0x40, 0x3f,
-       0xec, 0x02, 0x7e, 0x29, 0xa3, 0x6a, 0x1c, 0x9f, 0xf6, 0x78, 0xb8, 0x1b,
-       0x7b, 0x8e, 0x43, 0x16, 0xe4, 0x63, 0x8f, 0x8a, 0x2d, 0x33, 0x66, 0x4c,
-       0xcb, 0xf6, 0xc2, 0x9b, 0x4d, 0xf3, 0x5b, 0x74, 0x4c, 0xc6, 0x2b, 0xd4,
-       0xf1, 0x2e, 0xc4, 0xe2, 0x26, 0xfa, 0x76, 0xa3, 0xed, 0xc7, 0x54, 0xfd,
-       0xb5, 0x39, 0x68, 0x9b, 0x0b, 0xc0, 0x59, 0xe0, 0xc4, 0x55, 0xf8, 0xa8,
-       0x6d, 0xa0, 0x39, 0xb8, 0x8f, 0x22, 0xfc, 0x13, 0xfa, 0x94, 0xcc, 0x19,
-       0x5b, 0xfa, 0xb4, 0xc4, 0x69, 0xe7, 0x57, 0x31, 0x1f, 0xfb, 0xb6, 0xa9,
-       0x7c, 0xac, 0x30, 0xc0, 0xbd, 0xd2, 0xd7, 0x2d, 0x82, 0x3e, 0xf4, 0x95,
-       0x98, 0x03, 0xd2, 0xef, 0xf9, 0x39, 0x5a, 0x44, 0xe5, 0x68, 0x9d, 0x8a,
-       0x1f, 0xe4, 0xf5, 0x8d, 0x61, 0x62, 0x65, 0xa7, 0xcd, 0x3d, 0x0c, 0x7b,
-       0x58, 0xc7, 0xb6, 0x9b, 0x0b, 0x66, 0x74, 0xde, 0x3f, 0x02, 0xb9, 0xb2,
-       0x4e, 0xe3, 0xcb, 0xef, 0x21, 0x6f, 0xdf, 0x83, 0x52, 0xec, 0x94, 0xf0,
-       0x7a, 0xd0, 0x93, 0x9f, 0x61, 0xdc, 0xfd, 0x09, 0x95, 0x83, 0x44, 0xed,
-       0x4b, 0xdb, 0xed, 0x5d, 0xd7, 0x60, 0xb7, 0x23, 0x97, 0xb5, 0xdb, 0xcf,
-       0x85, 0x83, 0x76, 0x7b, 0xd7, 0x35, 0xd8, 0xed, 0xfe, 0x6b, 0xb2, 0x5b,
-       0xee, 0x8d, 0x98, 0xe4, 0xd7, 0xc4, 0x56, 0xc6, 0x59, 0xfe, 0xba, 0x13,
-       0x58, 0x33, 0x73, 0x89, 0x35, 0xc7, 0x2e, 0x59, 0x5b, 0x6d, 0x8c, 0xb1,
-       0xae, 0x46, 0xde, 0xcc, 0xad, 0xe8, 0x6f, 0x23, 0x9e, 0x5f, 0xba, 0xdd,
-       0xcb, 0xe7, 0xfd, 0xbc, 0x3e, 0x68, 0x3f, 0xd4, 0x0b, 0xea, 0xc2, 0x63,
-       0xe0, 0x17, 0xf5, 0xc1, 0xb7, 0xb9, 0x9e, 0x06, 0x1d, 0x5c, 0x44, 0xbe,
-       0xdf, 0xe3, 0xe9, 0x20, 0x65, 0xdd, 0xab, 0xbe, 0x11, 0x95, 0x9c, 0x47,
-       0xdc, 0x3c, 0x1f, 0x3a, 0x90, 0x2f, 0xf9, 0xb6, 0x06, 0x9e, 0x44, 0xfd,
-       0x67, 0xe4, 0xa3, 0x8d, 0x98, 0x67, 0x0b, 0xe2, 0x35, 0xf0, 0x48, 0xf5,
-       0x2f, 0xaf, 0x09, 0x5f, 0x1e, 0xcf, 0xa4, 0x18, 0xc2, 0xd8, 0x53, 0x03,
-       0xb0, 0xf1, 0x01, 0x62, 0x54, 0x1a, 0x79, 0x0f, 0xf5, 0x90, 0xba, 0xb9,
-       0x29, 0xb9, 0x43, 0x67, 0x4c, 0xb5, 0x07, 0xb6, 0x47, 0x7d, 0x8d, 0xcb,
-       0x8e, 0xca, 0xa6, 0x33, 0xe7, 0x74, 0xae, 0x51, 0xad, 0xe6, 0x99, 0x2b,
-       0x5a, 0xa2, 0x77, 0xf7, 0xff, 0x45, 0x98, 0x7e, 0xe9, 0x7a, 0xdb, 0xf0,
-       0x74, 0x2d, 0x83, 0x7b, 0xea, 0xed, 0xeb, 0xf0, 0xf7, 0xfc, 0xc6, 0xfe,
-       0x03, 0xf4, 0xc7, 0x60, 0xf3, 0xf4, 0xef, 0xcc, 0x47, 0xb6, 0x7a, 0xe3,
-       0x7a, 0xd4, 0xf7, 0xcf, 0x6c, 0xea, 0x56, 0xef, 0xbb, 0x13, 0xfd, 0x4f,
-       0x82, 0x3e, 0x7b, 0x99, 0x9c, 0x79, 0x46, 0x21, 0xa7, 0xf2, 0x19, 0xbe,
-       0xaf, 0x74, 0x12, 0x39, 0x88, 0x19, 0xa8, 0xa5, 0x87, 0xbd, 0xdc, 0x8d,
-       0x36, 0x16, 0x81, 0x0c, 0xb7, 0x7b, 0xb9, 0x0a, 0xf3, 0xd7, 0xe5, 0x67,
-       0x13, 0x56, 0xd7, 0x81, 0x0d, 0xef, 0x43, 0x07, 0x1a, 0xe5, 0x17, 0x86,
-       0xed, 0xfb, 0xf2, 0xf3, 0xe3, 0x98, 0x79, 0x6f, 0xdf, 0x3d, 0xae, 0x0c,
-       0x7f, 0x2c, 0xf6, 0xa9, 0x05, 0xf6, 0xe9, 0xe3, 0xd1, 0x3e, 0x6f, 0x9f,
-       0x5b, 0x1b, 0xf0, 0x68, 0xa4, 0xc1, 0x66, 0x3f, 0x4a, 0x3c, 0x3a, 0xb4,
-       0xe6, 0xa3, 0xc7, 0x23, 0xee, 0x6b, 0xe3, 0xaa, 0x38, 0xe4, 0xee, 0xe3,
-       0x77, 0x45, 0x4f, 0x7f, 0x98, 0xf9, 0xde, 0xfb, 0x91, 0x4f, 0x10, 0x47,
-       0x28, 0x93, 0x36, 0x15, 0xc3, 0xba, 0xb6, 0x07, 0x5f, 0x5e, 0x0a, 0xc9,
-       0x1b, 0xf7, 0x84, 0xe5, 0x7f, 0x6f, 0xe3, 0xf7, 0x30, 0xd3, 0xab, 0x69,
-       0xb1, 0xfd, 0xc2, 0x1a, 0xd7, 0x0f, 0xbd, 0xd0, 0xee, 0xfa, 0x1d, 0xbe,
-       0xe3, 0xdb, 0xb3, 0x85, 0xe7, 0x7c, 0xb6, 0x91, 0x5f, 0x4c, 0xae, 0x21,
-       0x07, 0xdc, 0x64, 0x5d, 0xd0, 0x57, 0xcb, 0x01, 0x2f, 0x5f, 0x0f, 0xac,
-       0xe7, 0x80, 0xc4, 0xd9, 0x0e, 0xa5, 0x1b, 0xf9, 0x28, 0x73, 0x1f, 0xc3,
-       0xc3, 0x4e, 0xde, 0x23, 0xb7, 0x75, 0x90, 0xef, 0x42, 0xb6, 0xcf, 0x21,
-       0x5e, 0x7a, 0xd6, 0x41, 0x8e, 0xeb, 0x20, 0xb7, 0x75, 0x90, 0xdb, 0x3a,
-       0xc8, 0x6d, 0x9d, 0xa4, 0x97, 0x23, 0x8f, 0x78, 0x75, 0x7f, 0x7e, 0xe3,
-       0x66, 0x7d, 0xa1, 0x08, 0x5f, 0x32, 0xc5, 0x73, 0x13, 0x7a, 0x36, 0xb5,
-       0xc6, 0xdb, 0x9f, 0x5f, 0x13, 0xef, 0xf2, 0x6a, 0x36, 0xdf, 0x54, 0x75,
-       0x43, 0xd1, 0x1f, 0x68, 0x71, 0xbf, 0x83, 0xf3, 0x7c, 0xc7, 0xaf, 0x21,
-       0x2e, 0x51, 0x67, 0x88, 0x68, 0xa3, 0x55, 0x3d, 0xcd, 0x9a, 0x8c, 0xe8,
-       0x7a, 0xfa, 0x16, 0xbc, 0xb3, 0xc5, 0xcd, 0x09, 0xa2, 0x62, 0xe8, 0xe9,
-       0x56, 0xf2, 0x54, 0xd3, 0xd3, 0x6b, 0xbd, 0xb9, 0xf6, 0xb7, 0xb8, 0xb1,
-       0x55, 0x2f, 0xdb, 0xa6, 0xce, 0x38, 0x41, 0xc5, 0xda, 0x7e, 0xff, 0xc5,
-       0xf6, 0xe5, 0x6b, 0x85, 0x14, 0xbe, 0x67, 0x53, 0xf7, 0x62, 0x3e, 0xb6,
-       0xeb, 0xfc, 0xd6, 0x2f, 0xc9, 0xef, 0x90, 0xc7, 0x6f, 0x97, 0xc7, 0x06,
-       0xc7, 0xa9, 0xba, 0x30, 0x79, 0xed, 0xcf, 0xa7, 0xea, 0x7a, 0x58, 0x47,
-       0x9d, 0xcd, 0xc0, 0xf5, 0x07, 0xa6, 0xb4, 0x8d, 0xee, 0x0e, 0xd9, 0xc1,
-       0x75, 0xfd, 0x6f, 0xe2, 0x57, 0xb3, 0x66, 0x8f, 0xfa, 0x8e, 0xe6, 0xfa,
-       0x8c, 0x90, 0xd2, 0x41, 0x33, 0xcd, 0x7d, 0xfd, 0x50, 0x9d, 0xa9, 0xa1,
-       0xfe, 0xe5, 0x90, 0xc7, 0x4c, 0x0d, 0x6c, 0x8a, 0x9b, 0xfa, 0x48, 0x0b,
-       0xeb, 0xaf, 0x43, 0x15, 0x1f, 0xf7, 0xb8, 0x5e, 0xa3, 0x1f, 0x67, 0x5d,
-       0xcd, 0xc7, 0x33, 0xd9, 0xe0, 0xd6, 0xdb, 0x3e, 0x88, 0x2d, 0xb5, 0x34,
-       0xd8, 0x92, 0xbf, 0x4f, 0xee, 0x9f, 0xd7, 0xd5, 0xcf, 0x43, 0x2c, 0x56,
-       0x02, 0xdf, 0x47, 0x6a, 0xba, 0xc1, 0xb3, 0x2a, 0x9f, 0x85, 0x0e, 0xf2,
-       0xdb, 0xc0, 0x4e, 0xd8, 0x51, 0xb5, 0x3a, 0xc4, 0x1a, 0x73, 0xdf, 0x67,
-       0x54, 0x7e, 0xa9, 0xa7, 0xe7, 0x55, 0xfd, 0xc1, 0x5c, 0x51, 0x7f, 0x18,
-       0x82, 0xae, 0x20, 0x06, 0x70, 0xda, 0x54, 0x4c, 0xa7, 0xe2, 0x85, 0x4a,
-       0xe3, 0xf7, 0x97, 0xfb, 0x5b, 0x5d, 0x3e, 0xfc, 0x5d, 0x8b, 0xfb, 0x0d,
-       0xe2, 0x8f, 0xa2, 0xcb, 0xdb, 0x7c, 0xff, 0xaf, 0x5b, 0xfc, 0xb3, 0x3b,
-       0x85, 0x13, 0x43, 0xd0, 0x45, 0xe4, 0xe4, 0x6a, 0x3e, 0xc4, 0xbb, 0x4f,
-       0xcc, 0x76, 0x2c, 0x1f, 0x8f, 0xbe, 0x13, 0xfe, 0xf8, 0x8e, 0x86, 0xf1,
-       0x1d, 0x18, 0xff, 0x7b, 0x0d, 0xe3, 0x3b, 0x02, 0xe3, 0xa3, 0x0d, 0xe3,
-       0xa3, 0x18, 0xff, 0x7c, 0xc3, 0xf8, 0x68, 0x60, 0x7c, 0x67, 0xc3, 0xf8,
-       0x4e, 0x8c, 0x7f, 0xa1, 0x61, 0x3c, 0xfa, 0x4e, 0x34, 0x79, 0xdf, 0xc5,
-       0x88, 0xb1, 0xfb, 0xbd, 0x5c, 0x1c, 0xd7, 0x72, 0xe3, 0xb7, 0x16, 0xea,
-       0x5d, 0x17, 0x64, 0xe0, 0x9f, 0xa7, 0xa3, 0xbd, 0x66, 0x60, 0xaf, 0xf5,
-       0x58, 0xc6, 0xd5, 0xc7, 0xa0, 0x2e, 0x12, 0x1f, 0x8a, 0x62, 0xd8, 0xd0,
-       0x9d, 0x12, 0x74, 0xa8, 0xe4, 0xfb, 0x24, 0x9e, 0x83, 0xe2, 0x19, 0x53,
-       0xd7, 0xf7, 0x86, 0xec, 0x45, 0x2f, 0x07, 0x7b, 0x9b, 0xb4, 0x03, 0x2f,
-       0x7d, 0xcc, 0x94, 0x63, 0xae, 0xdd, 0x50, 0x7f, 0x39, 0xbf, 0x67, 0x3f,
-       0xd4, 0x55, 0x6f, 0x9d, 0xa1, 0x15, 0xb8, 0x16, 0x5f, 0x51, 0xdb, 0x32,
-       0xae, 0x02, 0xd7, 0x46, 0x6a, 0xb8, 0xf6, 0x59, 0x99, 0xaf, 0xe5, 0xdb,
-       0xc3, 0x72, 0xc0, 0xd9, 0xc5, 0x33, 0x36, 0xc7, 0x32, 0xf2, 0xe1, 0xe4,
-       0xdb, 0xbb, 0x6a, 0x7e, 0x92, 0x67, 0x3a, 0x96, 0x0e, 0x31, 0x87, 0xf2,
-       0x6b, 0xb3, 0x53, 0xce, 0xcf, 0xb6, 0x42, 0x2e, 0xb0, 0x8d, 0x6b, 0xcd,
-       0xb7, 0x39, 0x5f, 0x54, 0x0e, 0xb8, 0xe7, 0x1d, 0x6a, 0xf3, 0x16, 0x6b,
-       0xf3, 0xc6, 0x3c, 0x7b, 0xa3, 0x0f, 0xae, 0xfb, 0xcb, 0x1c, 0xfc, 0xe5,
-       0x18, 0x72, 0xee, 0x45, 0x67, 0xb5, 0xfa, 0xe8, 0xb5, 0xfa, 0xcb, 0xc6,
-       0x3a, 0x73, 0xa3, 0xbf, 0xe4, 0x3a, 0x8d, 0xb5, 0xe5, 0x78, 0x03, 0xfe,
-       0x53, 0x9f, 0x0e, 0x7b, 0x31, 0x35, 0xae, 0xa5, 0xc3, 0xb0, 0x47, 0x5d,
-       0xc6, 0x94, 0xfe, 0xb2, 0xed, 0xe7, 0x96, 0xbb, 0x6b, 0xb9, 0x65, 0x3d,
-       0x1f, 0x44, 0xec, 0x9a, 0xfc, 0xa4, 0x87, 0x8f, 0x8c, 0x91, 0xa7, 0xd0,
-       0x7f, 0x0c, 0x3a, 0xc0, 0x67, 0xac, 0x97, 0xde, 0x2c, 0x9f, 0x32, 0x5d,
-       0xff, 0xe4, 0xd6, 0xa6, 0x76, 0xab, 0xf8, 0x9f, 0xdf, 0x0b, 0x0a, 0xa9,
-       0x76, 0x2f, 0xde, 0xbb, 0x12, 0xae, 0x2e, 0xcf, 0x4d, 0x75, 0xfd, 0x51,
-       0xbc, 0xcb, 0xdc, 0xd4, 0x8c, 0x10, 0x43, 0xb3, 0x95, 0xcb, 0xbe, 0x5f,
-       0xa4, 0x7f, 0x29, 0xa8, 0xef, 0x82, 0x2a, 0x0f, 0xc5, 0xb8, 0x45, 0xef,
-       0x7d, 0x37, 0x0f, 0xcd, 0x56, 0xbe, 0xdd, 0xea, 0xe2, 0xe0, 0xe5, 0x72,
-       0x96, 0x9f, 0x88, 0xb0, 0xae, 0xb7, 0xe8, 0x5c, 0x89, 0xd6, 0x95, 0x79,
-       0xaf, 0xb1, 0x22, 0xef, 0x1d, 0xf5, 0xf2, 0xda, 0xcf, 0xa9, 0xbc, 0xd7,
-       0xe5, 0x31, 0xf7, 0x12, 0xcc, 0xa3, 0x6c, 0x60, 0x21, 0xbf, 0xa9, 0x10,
-       0x1f, 0x26, 0x94, 0xdf, 0xca, 0x4f, 0xdf, 0x09, 0x3e, 0x47, 0x57, 0xd1,
-       0x9b, 0x8f, 0xda, 0x4f, 0xf8, 0x7b, 0x3f, 0x2c, 0x6e, 0xbd, 0x6e, 0x27,
-       0x68, 0x61, 0x6e, 0x15, 0xf2, 0xf4, 0xe1, 0xbb, 0xde, 0x39, 0x53, 0x7f,
-       0x9c, 0x9f, 0xc7, 0xd7, 0xbe, 0xbb, 0x16, 0x33, 0xcb, 0xea, 0x27, 0x1b,
-       0x09, 0xc3, 0x90, 0x7b, 0xe6, 0x1a, 0xbe, 0x5b, 0x7c, 0x90, 0xf3, 0x11,
-       0x8d, 0x7e, 0x8d, 0xdf, 0x4d, 0xf9, 0xad, 0x54, 0xb4, 0xbb, 0x7b, 0x6d,
-       0xd8, 0x00, 0xcf, 0x2c, 0x07, 0xf1, 0x35, 0x2c, 0xf9, 0x39, 0x09, 0x47,
-       0xd3, 0xfc, 0x06, 0x40, 0xff, 0xff, 0xba, 0xb7, 0xcf, 0x98, 0xec, 0x9f,
-       0x71, 0x6b, 0x9e, 0xfa, 0x65, 0xcf, 0xc5, 0x1d, 0x00, 0x1f, 0x12, 0x47,
-       0xfd, 0x9a, 0xa7, 0xee, 0x9e, 0x8b, 0x3b, 0xfa, 0xe1, 0x9d, 0x8b, 0xe3,
-       0xfc, 0xa6, 0xec, 0x5a, 0xe5, 0x5c, 0x9c, 0x71, 0x95, 0xe7, 0xe2, 0xda,
-       0x55, 0xcd, 0x93, 0xf3, 0xb8, 0x35, 0x4f, 0xb6, 0xbb, 0xfb, 0x59, 0x2b,
-       0xe1, 0xd9, 0xb7, 0x01, 0x75, 0x06, 0xb9, 0xbb, 0xff, 0x47, 0x91, 0xa3,
-       0x7c, 0x3d, 0xf2, 0xd1, 0xe7, 0x28, 0xdc, 0xcb, 0xaf, 0xb8, 0xdf, 0x77,
-       0xe5, 0x5a, 0xea, 0x00, 0x1f, 0xac, 0xae, 0xb9, 0x5f, 0xd5, 0x35, 0xbf,
-       0x13, 0x09, 0xd6, 0x35, 0xf5, 0x2b, 0x9c, 0x0d, 0xdb, 0xbf, 0x4a, 0x5d,
-       0x33, 0x14, 0x38, 0x1b, 0x16, 0xf2, 0xce, 0x86, 0xb5, 0xdb, 0xc8, 0x25,
-       0xbd, 0x3a, 0xa6, 0x7e, 0xd9, 0xb3, 0x61, 0xff, 0x19, 0xf9, 0xe0, 0x75,
-       0xcc, 0x15, 0x67, 0xc3, 0xe0, 0xeb, 0x36, 0x48, 0xfc, 0x9a, 0xf2, 0x9e,
-       0x0f, 0x92, 0xf3, 0xf0, 0xbc, 0x7e, 0x13, 0xf6, 0x1c, 0x92, 0x5d, 0x51,
-       0xea, 0x27, 0xcf, 0x36, 0xf6, 0xc2, 0x16, 0x70, 0xad, 0xb0, 0x9d, 0xa4,
-       0x8c, 0xb4, 0x91, 0xde, 0xe5, 0xe7, 0x10, 0xea, 0xe7, 0x71, 0xc3, 0xb5,
-       0xf3, 0xb8, 0x47, 0xa0, 0x37, 0xfa, 0x4c, 0x58, 0x16, 0x02, 0x3a, 0x35,
-       0x85, 0x78, 0x4f, 0x9f, 0xb3, 0xbc, 0xe7, 0xfc, 0x9f, 0x8a, 0x28, 0x30,
-       0x8f, 0x67, 0x78, 0xdb, 0xc4, 0x98, 0x73, 0xbf, 0x59, 0xba, 0xff, 0x57,
-       0x12, 0xc3, 0x18, 0x9e, 0xf1, 0x0c, 0xc9, 0x01, 0x55, 0xb3, 0xf0, 0x75,
-       0x79, 0xc7, 0x5a, 0x69, 0x59, 0x9f, 0xa9, 0xb7, 0xa3, 0xab, 0xf8, 0x7d,
-       0xc4, 0x91, 0x33, 0xd4, 0xe7, 0x5b, 0x25, 0xe7, 0xd5, 0x83, 0x0a, 0x95,
-       0x6d, 0x5e, 0x7e, 0xa1, 0xbe, 0xed, 0x80, 0x97, 0xdd, 0x9e, 0x0f, 0xc6,
-       0xb5, 0xd4, 0x4d, 0x9f, 0x87, 0x35, 0x4e, 0xca, 0xd0, 0xf4, 0x96, 0xd8,
-       0x38, 0xf0, 0x6e, 0x4c, 0xad, 0x79, 0x2d, 0x3c, 0xd7, 0x2e, 0xf1, 0xbd,
-       0xf1, 0x6a, 0xf9, 0xee, 0xc7, 0xc7, 0x8f, 0x62, 0x7f, 0xdd, 0xd0, 0x8f,
-       0x87, 0x25, 0x77, 0xe2, 0x66, 0x19, 0x9a, 0x4d, 0x80, 0x9e, 0x1f, 0x56,
-       0x0b, 0x29, 0xc4, 0xd2, 0x4f, 0xf0, 0xdc, 0x18, 0x30, 0x14, 0x7c, 0x7b,
-       0x66, 0xc5, 0x77, 0xec, 0xe0, 0x59, 0xb3, 0x64, 0xed, 0xec, 0xd0, 0x53,
-       0x15, 0x09, 0x77, 0x90, 0xe6, 0x99, 0xfa, 0xd9, 0xef, 0xc5, 0xca, 0x0e,
-       0xe5, 0xdb, 0x9e, 0xac, 0x2c, 0xab, 0xfd, 0x28, 0x19, 0x4e, 0x94, 0x9f,
-       0x04, 0x2f, 0x5e, 0x51, 0xfe, 0xed, 0x88, 0x23, 0x37, 0x19, 0x42, 0x79,
-       0x88, 0x06, 0x1e, 0xa8, 0x33, 0x1c, 0xee, 0xf7, 0xfd, 0x2e, 0x25, 0x57,
-       0x17, 0x2b, 0x76, 0x06, 0xce, 0x60, 0xd4, 0x65, 0xeb, 0x9e, 0xcd, 0x70,
-       0x65, 0xe1, 0x9e, 0x1f, 0x21, 0x3f, 0x97, 0x0e, 0xed, 0xb2, 0xdd, 0xf3,
-       0x23, 0x3d, 0x73, 0xec, 0xeb, 0x6c, 0xf0, 0x7d, 0x61, 0xe8, 0x00, 0xcf,
-       0x1d, 0xf1, 0xcc, 0x37, 0x69, 0x56, 0xb5, 0x8e, 0x55, 0xbf, 0x6d, 0x5f,
-       0x5b, 0xcd, 0xd5, 0x5d, 0xb3, 0x5b, 0xad, 0x79, 0x9d, 0x87, 0x59, 0xfe,
-       0x59, 0xef, 0x94, 0xf6, 0xff, 0xd4, 0x5d, 0x7b, 0x6c, 0x1b, 0xf7, 0x7d,
-       0xff, 0xf2, 0x48, 0x3d, 0xac, 0xe7, 0x49, 0xa6, 0x64, 0x5a, 0x52, 0x94,
-       0x3b, 0xe9, 0x64, 0x29, 0xb1, 0x12, 0x70, 0x9e, 0xba, 0x0a, 0x88, 0x9a,
-       0xb0, 0x24, 0xfd, 0x58, 0x10, 0x0c, 0xb4, 0xad, 0x64, 0xee, 0x92, 0xad,
-       0x0e, 0x25, 0xa7, 0x1d, 0x30, 0x60, 0x6e, 0xd6, 0x02, 0x69, 0x07, 0xc7,
-       0x0c, 0x65, 0x27, 0xc6, 0xaa, 0x88, 0x4c, 0xcc, 0x6a, 0x1d, 0xb0, 0x62,
-       0x1c, 0xa5, 0x38, 0x69, 0xa7, 0x80, 0x69, 0xda, 0x04, 0xc5, 0xfe, 0xb1,
-       0x26, 0x3b, 0x7b, 0x61, 0x7f, 0x04, 0xdb, 0x80, 0x1a, 0x5b, 0x81, 0xba,
-       0x76, 0x8a, 0x65, 0x1b, 0xe0, 0x34, 0xdb, 0xb0, 0x75, 0x58, 0x0b, 0xee,
-       0xfb, 0xf9, 0x3d, 0xc8, 0x23, 0x79, 0xd4, 0xc3, 0x71, 0x06, 0x4c, 0x80,
-       0x40, 0xde, 0xf1, 0x77, 0x77, 0xbf, 0xdf, 0xf7, 0xf7, 0x7d, 0xbf, 0x6e,
-       0x2e, 0x33, 0x1e, 0xf2, 0x33, 0x7e, 0xcf, 0x15, 0x61, 0x5f, 0x37, 0xd2,
-       0xe1, 0x36, 0x83, 0x67, 0xa4, 0x0e, 0x9e, 0xd5, 0x34, 0xc1, 0xf6, 0x78,
-       0x99, 0x77, 0x4b, 0xd8, 0xc9, 0xf3, 0xc8, 0x63, 0xd7, 0x39, 0x0e, 0x12,
-       0x76, 0x65, 0x1a, 0x5a, 0x72, 0xe7, 0x37, 0x54, 0x60, 0x77, 0xb2, 0x0c,
-       0xbb, 0x3d, 0xff, 0x8f, 0x60, 0x77, 0x4d, 0xe8, 0xbf, 0xdf, 0x2e, 0x22,
-       0x6f, 0x4d, 0xeb, 0x00, 0xba, 0x6e, 0x09, 0x70, 0x04, 0x3f, 0xb5, 0xf3,
-       0xeb, 0x04, 0x9e, 0x8a, 0xbc, 0xe2, 0x52, 0xe9, 0x3b, 0xe1, 0xb2, 0x9f,
-       0x92, 0xed, 0x12, 0xd8, 0x27, 0xf0, 0xe7, 0x35, 0x96, 0x91, 0x47, 0x6f,
-       0x4b, 0x46, 0x42, 0x57, 0xaa, 0xb5, 0x4f, 0x7e, 0xbb, 0xcb, 0x6d, 0x9f,
-       0x1c, 0xdd, 0xa1, 0x7d, 0x72, 0x5a, 0xda, 0x27, 0xa9, 0xed, 0xdb, 0x27,
-       0x03, 0x75, 0x79, 0x5d, 0x95, 0xf5, 0xec, 0xdc, 0x3e, 0x31, 0x36, 0xb5,
-       0x4f, 0x46, 0x5d, 0xbe, 0x18, 0xcc, 0xf7, 0x57, 0x29, 0x75, 0x0c, 0x3c,
-       0x4e, 0xc3, 0x19, 0x30, 0x3e, 0x56, 0xe3, 0x17, 0xfe, 0x38, 0x61, 0xfd,
-       0xd7, 0xff, 0xc7, 0xb0, 0x1e, 0xac, 0xf3, 0x79, 0x57, 0xd6, 0x03, 0x21,
-       0xfe, 0x51, 0x60, 0x3d, 0xd8, 0xd0, 0x77, 0xda, 0x38, 0x67, 0xb1, 0xda,
-       0x77, 0x3a, 0x62, 0x34, 0xe2, 0xed, 0x7f, 0xe4, 0xf2, 0xa9, 0xba, 0xf9,
-       0x3b, 0x68, 0x8a, 0x7c, 0x47, 0xc7, 0xf5, 0xb3, 0x40, 0x4b, 0x76, 0x2a,
-       0x45, 0xb0, 0x99, 0xf0, 0xbc, 0x90, 0xa0, 0xb5, 0x1a, 0x7d, 0x8b, 0x9f,
-       0xc7, 0xeb, 0x7b, 0xf5, 0x09, 0x21, 0xa7, 0xa4, 0xff, 0x01, 0xe3, 0x27,
-       0x7c, 0xf3, 0x62, 0xac, 0xcc, 0x6f, 0x52, 0xfe, 0x08, 0xa5, 0xfb, 0x37,
-       0xf2, 0x43, 0xd4, 0xcb, 0xbc, 0x9d, 0xd9, 0x0a, 0x9a, 0xc6, 0xef, 0xe6,
-       0x7d, 0x09, 0x55, 0xd9, 0x5a, 0xe0, 0x9f, 0xa7, 0x59, 0x2f, 0x18, 0x29,
-       0xeb, 0x04, 0xd5, 0x7b, 0x73, 0x4e, 0xd8, 0x74, 0x9a, 0x77, 0x26, 0x64,
-       0xee, 0xa9, 0x38, 0x0f, 0x3d, 0x4d, 0xf3, 0xce, 0x5a, 0x3d, 0xf8, 0x6e,
-       0x0f, 0xbc, 0xf0, 0xca, 0x69, 0x2a, 0xef, 0x9d, 0x85, 0x9c, 0xf3, 0xb8,
-       0xe7, 0xde, 0x95, 0x6b, 0xc2, 0x52, 0x95, 0xb1, 0xf2, 0xfa, 0xb8, 0x58,
-       0xd7, 0x0f, 0x8e, 0x44, 0x51, 0xfb, 0x56, 0xae, 0x17, 0xab, 0xad, 0x77,
-       0x82, 0x1c, 0xd0, 0x74, 0xa8, 0x6b, 0xa2, 0x01, 0x8b, 0x61, 0x8f, 0x7a,
-       0x27, 0xb7, 0x2c, 0xc1, 0x75, 0xb5, 0xb0, 0xa8, 0xc8, 0x91, 0xf3, 0x4a,
-       0x8e, 0x14, 0x5c, 0x7c, 0xbc, 0x5e, 0x6f, 0xef, 0xf5, 0xd0, 0xdb, 0xbd,
-       0x6a, 0x9e, 0x30, 0xa7, 0x67, 0x58, 0x0f, 0xb9, 0x1f, 0x7a, 0x88, 0x89,
-       0xba, 0x25, 0xa9, 0x8b, 0xe0, 0x77, 0x96, 0x35, 0xaf, 0x86, 0x18, 0x57,
-       0x8e, 0xd0, 0x53, 0xac, 0x6b, 0x5f, 0xa2, 0x7b, 0x94, 0x7d, 0x16, 0x71,
-       0xe5, 0x99, 0x22, 0x8f, 0xdf, 0x47, 0xa9, 0x27, 0xec, 0x89, 0x08, 0x1d,
-       0xa1, 0x53, 0x22, 0x67, 0x06, 0xf1, 0x3d, 0xe4, 0x1c, 0xdc, 0x2b, 0x9e,
-       0x2f, 0x7d, 0x19, 0x77, 0x22, 0xa7, 0x6e, 0xfb, 0xf9, 0xfb, 0xba, 0x56,
-       0x2f, 0x2a, 0x9e, 0xb9, 0xaa, 0x68, 0x4a, 0x9c, 0xe3, 0xeb, 0x9f, 0x31,
-       0xea, 0xaf, 0x8f, 0x18, 0xf1, 0x62, 0xdc, 0x88, 0xae, 0x60, 0xdc, 0x33,
-       0x46, 0xac, 0x08, 0x1b, 0x52, 0xe3, 0x88, 0x1d, 0x06, 0xbd, 0x6d, 0xd0,
-       0xd6, 0xb1, 0x88, 0x02, 0xd5, 0xd4, 0x49, 0x6c, 0x63, 0xde, 0x87, 0xaa,
-       0xe6, 0xad, 0xe1, 0x8b, 0xef, 0xf0, 0xf7, 0x44, 0x18, 0xa6, 0x5a, 0xaf,
-       0x6d, 0x83, 0x7f, 0x7d, 0x22, 0x45, 0x9b, 0xe9, 0xb5, 0x76, 0x9d, 0x5e,
-       0x5b, 0xd8, 0x72, 0xde, 0x1f, 0x95, 0xc6, 0x65, 0x3d, 0xa2, 0xdf, 0x11,
-       0xfa, 0x2b, 0xcf, 0xbb, 0x4a, 0xb7, 0xad, 0xc1, 0x29, 0x8c, 0xd1, 0x7e,
-       0x70, 0xed, 0x07, 0xeb, 0x52, 0xf9, 0xc0, 0x3a, 0x3f, 0xa1, 0x0d, 0xf5,
-       0x5e, 0xa6, 0xcc, 0x6b, 0x85, 0x8d, 0xb5, 0xce, 0xf3, 0x83, 0xbd, 0xf5,
-       0xa0, 0x98, 0x23, 0xdb, 0x5b, 0x56, 0x8c, 0xa4, 0xaf, 0x7b, 0xbe, 0x58,
-       0x55, 0xff, 0xe9, 0x51, 0x07, 0x39, 0xe2, 0x51, 0x07, 0xe9, 0xa6, 0xb5,
-       0x80, 0x8b, 0xd6, 0x42, 0x2e, 0xbd, 0x6d, 0x88, 0xed, 0x96, 0x0e, 0xe6,
-       0x21, 0xb0, 0x5b, 0xda, 0xc8, 0xff, 0xb2, 0xdb, 0x6e, 0xa9, 0xad, 0x45,
-       0x07, 0xdd, 0x41, 0x37, 0x93, 0x36, 0x4c, 0x3c, 0x57, 0xae, 0x63, 0xe7,
-       0x75, 0x57, 0x6a, 0x0e, 0x57, 0xea, 0xea, 0x23, 0xbd, 0xe6, 0x3b, 0x5c,
-       0x37, 0x5f, 0xc8, 0xaf, 0x48, 0x43, 0x9d, 0xce, 0xcb, 0xae, 0xba, 0x53,
-       0xf3, 0xab, 0xe5, 0x67, 0x78, 0xd6, 0x88, 0xf0, 0x79, 0xa7, 0xca, 0xbc,
-       0x6c, 0x5a, 0xce, 0x37, 0x53, 0x6d, 0x67, 0xf8, 0x97, 0x48, 0xc1, 0xce,
-       0x9b, 0xb7, 0xef, 0xcc, 0x7f, 0xd6, 0x5e, 0x23, 0x77, 0xdf, 0x33, 0xa5,
-       0x5f, 0xac, 0x49, 0xe5, 0x61, 0xf7, 0x29, 0x7b, 0x6f, 0x2b, 0x7c, 0xc7,
-       0xb9, 0x26, 0xe5, 0x4b, 0xb4, 0xad, 0x3c, 0x01, 0xcf, 0x8f, 0x9d, 0x68,
-       0x72, 0x4c, 0x15, 0xcb, 0x42, 0xbc, 0x0a, 0x78, 0xaf, 0xef, 0x0f, 0x9e,
-       0xbd, 0x9d, 0x3d, 0xb3, 0xea, 0xf6, 0x4c, 0xe2, 0x15, 0x6c, 0x2d, 0xe4,
-       0x17, 0x4f, 0xd6, 0xe4, 0x78, 0x7f, 0x14, 0x58, 0x74, 0x79, 0xe4, 0x3d,
-       0x23, 0x6f, 0xb9, 0xd1, 0x3c, 0xaf, 0xbb, 0xf4, 0x72, 0xcc, 0xb7, 0x54,
-       0x7a, 0x23, 0x3c, 0x20, 0x65, 0x71, 0xd1, 0x5b, 0x47, 0x32, 0xb7, 0x3d,
-       0xbf, 0x5a, 0xd9, 0xbb, 0x77, 0x9b, 0xb2, 0x57, 0xf4, 0xf4, 0xf0, 0x1d,
-       0x14, 0x3c, 0xa0, 0x83, 0x56, 0x72, 0xc8, 0xbf, 0xfe, 0x05, 0xd0, 0x3c,
-       0xf3, 0x59, 0x57, 0x4d, 0x9a, 0xf7, 0x3e, 0x96, 0x63, 0x2a, 0x81, 0x19,
-       0xc4, 0xfe, 0x90, 0x5b, 0xd2, 0xcb, 0xbc, 0x07, 0xe3, 0xc7, 0xac, 0xab,
-       0xf0, 0xf7, 0x2a, 0xff, 0x53, 0x5c, 0xc9, 0x97, 0x83, 0xdb, 0x88, 0xad,
-       0xec, 0x8c, 0x4f, 0xdb, 0xd6, 0x3a, 0x21, 0xee, 0x83, 0x7c, 0xe1, 0xfb,
-       0xba, 0xa8, 0xeb, 0x33, 0x2d, 0x2d, 0xce, 0x97, 0x7a, 0x64, 0x2c, 0x0a,
-       0xbf, 0x75, 0xd0, 0x2b, 0x39, 0xe4, 0x72, 0xe3, 0xb7, 0xdf, 0xe0, 0xdf,
-       0xbc, 0x78, 0x94, 0xce, 0x45, 0x87, 0x2e, 0x27, 0xf7, 0x27, 0x4f, 0xb0,
-       0x95, 0x4a, 0xf4, 0xb7, 0xe1, 0x5f, 0x94, 0xf1, 0x8c, 0xe2, 0x9d, 0x8e,
-       0xd5, 0x78, 0xf9, 0x0b, 0xdf, 0xec, 0xb9, 0xdd, 0xdc, 0xc8, 0x2f, 0x6c,
-       0xcb, 0x5f, 0x88, 0x38, 0xff, 0x76, 0x62, 0x26, 0x3a, 0x36, 0x3c, 0x25,
-       0x6a, 0x4e, 0xdd, 0x78, 0x70, 0x67, 0xe2, 0xc3, 0xc0, 0x87, 0xe1, 0x3a,
-       0x5e, 0xf5, 0xd1, 0xfd, 0xfd, 0xb5, 0x70, 0x6d, 0xf3, 0xf4, 0x55, 0x79,
-       0xc7, 0x81, 0x11, 0xf3, 0x87, 0x9f, 0xfa, 0x21, 0x9a, 0xbf, 0x08, 0x1c,
-       0x36, 0x18, 0xdb, 0x46, 0x69, 0x21, 0x88, 0xba, 0x22, 0x51, 0x9b, 0xa3,
-       0xe2, 0x86, 0xb2, 0x56, 0x68, 0x5e, 0xd4, 0x40, 0x8e, 0x85, 0x6e, 0xf2,
-       0xbc, 0xe7, 0x8b, 0x29, 0x3a, 0xc5, 0x32, 0xf6, 0xd4, 0x4a, 0x45, 0x77,
-       0xaf, 0xaf, 0x83, 0xac, 0xc6, 0xf1, 0x9b, 0x02, 0xc7, 0x87, 0x36, 0xc5,
-       0xf1, 0xc3, 0x65, 0x1c, 0xff, 0x44, 0xaf, 0xc4, 0xe7, 0x67, 0xf9, 0x5e,
-       0x5d, 0x74, 0x50, 0xdc, 0x37, 0xc5, 0xdf, 0xdb, 0xe9, 0xa0, 0xec, 0x61,
-       0xc1, 0xcf, 0x66, 0x1e, 0x9f, 0x49, 0xd1, 0x53, 0x17, 0x53, 0xbe, 0xb8,
-       0xa8, 0x5f, 0x70, 0xf7, 0xe8, 0xd0, 0xd7, 0x63, 0x5c, 0x23, 0xfc, 0xd7,
-       0x7c, 0x49, 0xd6, 0x5c, 0xe5, 0x25, 0x7f, 0xa2, 0x77, 0xc3, 0x83, 0x35,
-       0xf8, 0x5f, 0x6d, 0x3b, 0x9e, 0x56, 0x32, 0xf0, 0xd8, 0x26, 0x7e, 0x8d,
-       0x7a, 0xbc, 0xec, 0xf1, 0xd0, 0x87, 0x7f, 0xbd, 0x57, 0xc6, 0xa9, 0x36,
-       0xf3, 0x6b, 0xb8, 0x71, 0xb4, 0x2a, 0x6e, 0xcf, 0x7c, 0xff, 0xbf, 0x55,
-       0x1c, 0xfd, 0xa5, 0x5e, 0x29, 0x2f, 0x50, 0x1f, 0x98, 0x60, 0x38, 0x9c,
-       0x64, 0x5d, 0x65, 0x90, 0x9a, 0x5f, 0xd6, 0x6b, 0x1d, 0x14, 0xfc, 0xd6,
-       0xed, 0xa7, 0x39, 0xa7, 0x6a, 0xbb, 0xd3, 0xae, 0x35, 0x9d, 0x13, 0x36,
-       0x4e, 0x63, 0x7a, 0x6b, 0x9c, 0x73, 0x35, 0x54, 0x23, 0x13, 0x6a, 0xf1,
-       0x0d, 0xbd, 0x4f, 0xb0, 0xbf, 0x64, 0x48, 0x3d, 0x78, 0x9a, 0xf5, 0xdb,
-       0x9d, 0xc6, 0x8b, 0x3e, 0xaa, 0x8e, 0x58, 0xdb, 0x53, 0xa3, 0xf6, 0x3b,
-       0xf6, 0x41, 0xda, 0x1c, 0xc9, 0x57, 0x1f, 0x12, 0xbc, 0xe0, 0xdc, 0x64,
-       0x89, 0x62, 0xe1, 0x4e, 0x4a, 0x4e, 0xf2, 0xb3, 0xa7, 0x1d, 0xb6, 0xbd,
-       0xfc, 0x94, 0x62, 0xfa, 0x4d, 0x4e, 0xee, 0x52, 0xfa, 0xa2, 0xf6, 0xa7,
-       0xb7, 0xa8, 0x3c, 0x87, 0x67, 0x45, 0x5c, 0x52, 0xf6, 0xc6, 0xe0, 0xef,
-       0x2b, 0xfa, 0xde, 0xcf, 0x8a, 0xf8, 0x68, 0xf2, 0x62, 0xb3, 0x1a, 0xd7,
-       0xee, 0x1a, 0x87, 0x31, 0xed, 0x6a, 0x2c, 0xee, 0xa9, 0x75, 0x8a, 0x56,
-       0xc5, 0x6f, 0x1f, 0x11, 0x75, 0x60, 0xb2, 0x56, 0x0f, 0xbf, 0x9f, 0xa6,
-       0xb9, 0xf2, 0x5a, 0xda, 0x79, 0xec, 0xcf, 0x4a, 0x11, 0x61, 0xcb, 0xb5,
-       0xb3, 0xce, 0x8b, 0x79, 0xd7, 0xcf, 0x09, 0x6b, 0xf1, 0x8b, 0xf8, 0x10,
-       0x7f, 0x57, 0xcf, 0x39, 0x59, 0x9e, 0x13, 0x72, 0x34, 0xec, 0x90, 0xbc,
-       0x97, 0x1e, 0xd7, 0xee, 0x1a, 0xa7, 0x79, 0x85, 0x8e, 0x3f, 0xfc, 0x80,
-       0xe7, 0xf1, 0x37, 0x2a, 0x87, 0xd7, 0x14, 0xf1, 0x53, 0x99, 0xa3, 0xa1,
-       0xbf, 0xc3, 0xbf, 0x8c, 0x9c, 0x0a, 0xe4, 0x49, 0xb8, 0xf9, 0x8d, 0x5c,
-       0x6f, 0x00, 0xb2, 0xa8, 0x88, 0xb8, 0x29, 0xe2, 0x15, 0x8d, 0x74, 0xe7,
-       0xbd, 0xc8, 0xcd, 0xdf, 0x81, 0x0e, 0xba, 0x1d, 0xfa, 0xb3, 0x3c, 0xe8,
-       0xcf, 0xfd, 0x7c, 0xd4, 0xc1, 0xa1, 0x1e, 0x2e, 0x35, 0x61, 0x50, 0x89,
-       0x6d, 0x05, 0x83, 0xf2, 0xa6, 0x8f, 0x9e, 0x72, 0xec, 0xf0, 0x0a, 0xc9,
-       0x9a, 0xc9, 0xd8, 0xa2, 0x3d, 0xb1, 0x4e, 0xfb, 0x45, 0xcd, 0x38, 0x7a,
-       0x1f, 0xe4, 0x59, 0x06, 0x9f, 0xa4, 0x09, 0xb6, 0x8f, 0xd8, 0xfe, 0x9c,
-       0x45, 0xbc, 0x45, 0xef, 0x0b, 0x6a, 0xe0, 0xf1, 0x39, 0xc1, 0x70, 0x7a,
-       0x6c, 0x37, 0xb5, 0x45, 0xf8, 0x9e, 0x13, 0xe0, 0x4f, 0xe8, 0xe7, 0x45,
-       0x51, 0xb6, 0x93, 0x60, 0xb3, 0x9e, 0x9c, 0xb5, 0xcd, 0x3c, 0x19, 0x3c,
-       0x16, 0xb6, 0x2b, 0xee, 0x83, 0xeb, 0x23, 0x66, 0x13, 0xd5, 0xd6, 0xe4,
-       0x3e, 0x2b, 0xea, 0x14, 0xdf, 0x0d, 0xdf, 0x47, 0x46, 0x3f, 0xf8, 0x15,
-       0xf6, 0xed, 0x5e, 0x15, 0x27, 0x3a, 0xcb, 0xdf, 0xc7, 0xd5, 0xf7, 0xaf,
-       0x88, 0xfd, 0x94, 0xdf, 0x35, 0x7e, 0xe3, 0xef, 0x5f, 0x5a, 0xc8, 0xf9,
-       0xa1, 0xca, 0x59, 0xa9, 0xca, 0x05, 0x09, 0x8d, 0x1a, 0x5f, 0xa1, 0xd3,
-       0x2b, 0x9b, 0xf9, 0x5f, 0xbc, 0x6a, 0x5d, 0xbb, 0xb7, 0x59, 0xeb, 0xfa,
-       0x07, 0xbb, 0x65, 0x6d, 0x99, 0x7b, 0x2e, 0xff, 0xc9, 0x73, 0xf1, 0xd2,
-       0xc9, 0xea, 0xf4, 0x44, 0x5e, 0x6f, 0x89, 0xfe, 0x29, 0xfc, 0x49, 0xba,
-       0x1e, 0x0c, 0xa9, 0x9c, 0x25, 0xe4, 0x28, 0xdd, 0xa7, 0xf0, 0x5a, 0xf3,
-       0x7e, 0xf2, 0xe0, 0xfd, 0x8f, 0x89, 0x5c, 0x4d, 0x29, 0x3b, 0x06, 0x15,
-       0x3c, 0x00, 0xb3, 0x90, 0x0b, 0x66, 0x7d, 0x2e, 0x98, 0x19, 0xea, 0x7b,
-       0xa7, 0x38, 0x3e, 0xbd, 0xf2, 0x99, 0x6e, 0x59, 0x2f, 0x8e, 0x58, 0xe2,
-       0xbc, 0xfa, 0xbe, 0xd5, 0x7a, 0x7f, 0xce, 0x6b, 0x15, 0xfe, 0x26, 0xd7,
-       0x5a, 0x5f, 0x27, 0x72, 0x5a, 0x82, 0xf5, 0x30, 0xf8, 0x8e, 0xeb, 0x3c,
-       0xe6, 0x38, 0xe6, 0x9a, 0xe3, 0x88, 0x6b, 0x8e, 0x77, 0x37, 0x98, 0x23,
-       0xf3, 0xf8, 0xe2, 0x69, 0xfe, 0xbf, 0xdd, 0xb9, 0xca, 0x79, 0xce, 0x0b,
-       0x78, 0xb6, 0x53, 0x3a, 0x18, 0x52, 0xb2, 0xe3, 0xfb, 0xaa, 0x16, 0xdd,
-       0x6b, 0xce, 0xff, 0x40, 0x8d, 0xf7, 0xcd, 0x8d, 0xab, 0xee, 0xfa, 0xe3,
-       0x97, 0x28, 0x26, 0xeb, 0xc8, 0x15, 0x6d, 0x7f, 0xb5, 0x81, 0x1f, 0xfa,
-       0x41, 0xa1, 0xff, 0xcc, 0xcb, 0x78, 0xd0, 0x80, 0xec, 0xbf, 0x16, 0xa0,
-       0xd5, 0x72, 0x2d, 0xaf, 0x5f, 0xd5, 0xee, 0xdc, 0x1f, 0xbc, 0xb3, 0x75,
-       0xbc, 0x38, 0xff, 0x88, 0xf0, 0xe5, 0xc9, 0xf8, 0x51, 0x42, 0xd5, 0x23,
-       0xdb, 0x16, 0x72, 0x03, 0x0a, 0x6b, 0xf0, 0xbf, 0x36, 0xaa, 0xdd, 0xc5,
-       0xb5, 0xf0, 0x03, 0x6a, 0x3b, 0xfe, 0x84, 0xe0, 0x89, 0xd2, 0x3f, 0x26,
-       0xeb, 0x6f, 0x0b, 0x6b, 0x27, 0x45, 0xcd, 0x6b, 0x54, 0xd5, 0xf1, 0x26,
-       0xa9, 0x43, 0xe8, 0xb9, 0xb7, 0x5f, 0x7f, 0xfb, 0x5c, 0x70, 0xe7, 0xf5,
-       0xb7, 0xee, 0x6b, 0x76, 0x56, 0x7f, 0x6b, 0xf2, 0xda, 0x8d, 0x65, 0x59,
-       0x7f, 0x5b, 0x1d, 0x93, 0x91, 0xfe, 0xc0, 0xa4, 0x4b, 0x7f, 0x90, 0xfa,
-       0xfa, 0x6f, 0xb9, 0xf2, 0xb7, 0x65, 0x6d, 0x6d, 0xa1, 0xac, 0xb3, 0xca,
-       0xda, 0x5a, 0x99, 0xef, 0xed, 0xee, 0x03, 0x23, 0x63, 0x3f, 0xf2, 0x39,
-       0x9d, 0x35, 0xb1, 0x1f, 0x59, 0x53, 0x6b, 0x19, 0x8d, 0x6c, 0x38, 0xd1,
-       0xe7, 0xa2, 0x8f, 0xba, 0x22, 0x8c, 0xbb, 0xed, 0x0d, 0xfa, 0x21, 0x44,
-       0x1a, 0xf4, 0x43, 0x70, 0xf3, 0x7e, 0xb7, 0x8e, 0x05, 0x9d, 0x18, 0xb2,
-       0x11, 0xba, 0x30, 0xfa, 0x19, 0x84, 0xe9, 0x74, 0x59, 0xf7, 0xbc, 0x8f,
-       0x12, 0x4a, 0xf7, 0x3c, 0xbd, 0xa2, 0xf9, 0xd1, 0x48, 0x0d, 0x3f, 0xf2,
-       0xd2, 0x45, 0x6d, 0x95, 0xe7, 0xa3, 0xe9, 0x35, 0xe5, 0xa2, 0xd7, 0x94,
-       0x07, 0xbd, 0x8a, 0x67, 0x34, 0x98, 0xf7, 0xf7, 0xd5, 0x35, 0xf8, 0x4f,
-       0x84, 0xd0, 0xb3, 0x85, 0x79, 0x6a, 0x50, 0xe9, 0x7f, 0x2e, 0x7a, 0x3d,
-       0xc5, 0xf4, 0xaa, 0xcf, 0x63, 0xbe, 0x0d, 0x73, 0x41, 0x95, 0xce, 0x38,
-       0xe8, 0x3b, 0x74, 0xf1, 0x1b, 0x22, 0x4f, 0xaa, 0xda, 0x5e, 0xd4, 0xfa,
-       0xc4, 0x3e, 0x41, 0x4b, 0xd7, 0xfd, 0xc8, 0x5b, 0xd1, 0xe7, 0x4c, 0xe5,
-       0x27, 0xd3, 0xb0, 0x68, 0xae, 0xd2, 0x39, 0x2a, 0xfa, 0x86, 0xc8, 0xf1,
-       0x75, 0xcd, 0xed, 0x43, 0x9e, 0x9b, 0x3e, 0xaf, 0x65, 0xe6, 0xb5, 0x2a,
-       0x7f, 0xc6, 0xe5, 0xaa, 0x9e, 0x83, 0xf0, 0x1d, 0x75, 0x26, 0x0c, 0x27,
-       0x2e, 0x72, 0x4c, 0x7b, 0x1c, 0xf8, 0xc9, 0xa2, 0x4c, 0xfb, 0x3d, 0x09,
-       0xe4, 0x33, 0xf7, 0x2c, 0x59, 0x74, 0x3c, 0x73, 0xff, 0x5d, 0x12, 0x57,
-       0xce, 0x8a, 0x3e, 0x92, 0xe8, 0x67, 0x16, 0x63, 0xf9, 0x1c, 0xf5, 0x4f,
-       0xd3, 0xf9, 0x62, 0x0b, 0x15, 0x58, 0xbb, 0xf7, 0x3b, 0x79, 0xe1, 0xeb,
-       0x63, 0x9e, 0x94, 0x45, 0x2f, 0x51, 0x63, 0xb9, 0x99, 0xef, 0xdb, 0x4f,
-       0xab, 0xb9, 0x31, 0xd1, 0x13, 0x4a, 0xf6, 0x17, 0xc1, 0x58, 0x1f, 0xf5,
-       0x3a, 0x07, 0xfb, 0xa8, 0xed, 0xb3, 0x22, 0xc7, 0xb2, 0x90, 0x3d, 0x2b,
-       0x3f, 0xf3, 0x0f, 0xa8, 0x67, 0xf0, 0xf3, 0x8a, 0x7f, 0x4a, 0x91, 0x5e,
-       0xcb, 0x65, 0xcb, 0xb9, 0xff, 0xbc, 0xf5, 0x95, 0xa3, 0x3b, 0xd2, 0x57,
-       0x52, 0x89, 0x8a, 0xbe, 0xe2, 0xbe, 0x77, 0x39, 0x07, 0xa6, 0x5f, 0xf6,
-       0x7b, 0x00, 0x0c, 0xda, 0xa1, 0x8b, 0x25, 0x00, 0x4b, 0x63, 0xc6, 0x0e,
-       0x45, 0xfd, 0x53, 0xb4, 0x50, 0x1c, 0x32, 0x92, 0x59, 0xe8, 0xcc, 0xfc,
-       0x99, 0x8f, 0xee, 0x91, 0x3e, 0x1a, 0x7d, 0x0d, 0xf8, 0xca, 0x6e, 0x1e,
-       0xff, 0x7a, 0xbf, 0xcc, 0xcb, 0x76, 0x9f, 0xef, 0xe2, 0xf3, 0x7b, 0x42,
-       0xd5, 0xe7, 0x77, 0xf1, 0xf9, 0xde, 0x04, 0xf6, 0xd0, 0x58, 0x82, 0x5f,
-       0xd2, 0xa1, 0x34, 0xef, 0xcd, 0x42, 0x91, 0x65, 0xeb, 0xcb, 0xcc, 0x47,
-       0x57, 0xf4, 0xb8, 0x3e, 0xd4, 0xec, 0x88, 0x3d, 0x31, 0x78, 0xcc, 0xb9,
-       0xcc, 0x04, 0x8f, 0x1b, 0x24, 0xff, 0xcb, 0x6c, 0x8b, 0xae, 0x68, 0x5c,
-       0xd5, 0xf9, 0xf6, 0xdf, 0xe8, 0x93, 0x39, 0x55, 0xdf, 0xdd, 0x23, 0xe1,
-       0xe7, 0x08, 0x9e, 0x72, 0x9e, 0xe1, 0xf2, 0xbc, 0xc0, 0x43, 0x7b, 0xda,
-       0x2a, 0x3f, 0xbf, 0x13, 0x78, 0xd5, 0x8a, 0xbc, 0xd9, 0xc0, 0x12, 0xf3,
-       0xc5, 0x19, 0xc7, 0x4c, 0x97, 0x73, 0xd5, 0x1e, 0x1f, 0x90, 0xd7, 0xbf,
-       0xd9, 0x27, 0xfb, 0x83, 0x7e, 0x6b, 0x40, 0xf7, 0x48, 0x94, 0x32, 0x07,
-       0xf9, 0xcb, 0x3e, 0x01, 0x1b, 0xff, 0x32, 0xf8, 0xa5, 0xc1, 0xdf, 0x79,
-       0x3d, 0x09, 0xcc, 0xf1, 0x4a, 0x9f, 0xee, 0x17, 0x23, 0xd7, 0x15, 0xe7,
-       0xf9, 0x46, 0x78, 0x5d, 0xfa, 0xfc, 0x0c, 0x1f, 0x7b, 0xed, 0x2f, 0xee,
-       0xd5, 0x96, 0x90, 0xfd, 0xc5, 0xda, 0x12, 0xc9, 0x09, 0xb9, 0xcf, 0x15,
-       0x9f, 0x6e, 0xa8, 0xec, 0xd3, 0x3d, 0x9f, 0xb9, 0xd5, 0x07, 0xff, 0x86,
-       0xb1, 0xc4, 0xfb, 0x1d, 0x7c, 0x9e, 0xc7, 0xa2, 0x56, 0x21, 0xcd, 0x9f,
-       0x1d, 0x2a, 0xaf, 0xa7, 0x1e, 0x57, 0x64, 0x9e, 0x84, 0x96, 0x5b, 0xb8,
-       0xf6, 0x43, 0xbe, 0x87, 0x94, 0x5d, 0x8d, 0x9f, 0x43, 0x75, 0x79, 0x30,
-       0xf5, 0x38, 0xb6, 0x99, 0x1f, 0x56, 0xc4, 0x13, 0x3d, 0xf0, 0x6c, 0xb3,
-       0x7e, 0x06, 0xd7, 0x84, 0x1f, 0x2d, 0x56, 0x47, 0xaf, 0xa0, 0xe3, 0x00,
-       0xfd, 0xce, 0x62, 0x8a, 0x76, 0xf1, 0x5e, 0xfd, 0xa6, 0xf1, 0x00, 0xe2,
-       0xed, 0x24, 0x73, 0x9e, 0x18, 0xc6, 0x19, 0x67, 0xe2, 0x94, 0x11, 0x01,
-       0xbf, 0x2c, 0x05, 0x9c, 0x0e, 0x6a, 0x66, 0x5a, 0xfd, 0x65, 0x1a, 0x65,
-       0xfb, 0x0f, 0x34, 0xeb, 0x84, 0xe2, 0x04, 0x7a, 0xb3, 0xcd, 0x43, 0xac,
-       0x13, 0xc7, 0x8a, 0xc0, 0x67, 0x83, 0x3e, 0x9f, 0x23, 0xfa, 0x5c, 0x6e,
-       0xd4, 0xfc, 0x26, 0x39, 0x56, 0xe5, 0x77, 0xdb, 0x8c, 0xf2, 0x3c, 0xe2,
-       0xc5, 0x2f, 0xd3, 0xfb, 0xa2, 0xcf, 0x09, 0xe0, 0xa8, 0xf7, 0xfd, 0x4b,
-       0x74, 0x32, 0x81, 0x79, 0x6f, 0x9f, 0x3e, 0x8f, 0xef, 0x88, 0x3e, 0xdb,
-       0x3c, 0xe8, 0xf3, 0xc5, 0x7e, 0x89, 0x37, 0x25, 0xc6, 0xd1, 0x36, 0x9a,
-       0xcb, 0x22, 0x07, 0xec, 0xd3, 0xe8, 0x3b, 0x95, 0x4d, 0x32, 0x5f, 0x4a,
-       0x56, 0xf8, 0xd2, 0x85, 0x28, 0x1b, 0xc3, 0x4c, 0xe3, 0xe8, 0xcb, 0xa6,
-       0xf2, 0x7e, 0xb0, 0x8e, 0x01, 0x1a, 0x5d, 0x6e, 0xe7, 0x6b, 0x69, 0x3d,
-       0x3a, 0x15, 0x51, 0xb5, 0xfe, 0xb6, 0x15, 0x63, 0xfe, 0x78, 0x9e, 0x69,
-       0x39, 0x9d, 0xbd, 0x97, 0x0a, 0xc1, 0x21, 0x1a, 0x59, 0xd6, 0xfd, 0x4d,
-       0x44, 0xce, 0xc6, 0xa0, 0xe4, 0x49, 0x7a, 0xdd, 0x9f, 0x10, 0xbe, 0x0b,
-       0xeb, 0xd2, 0xc7, 0xb5, 0xee, 0xf6, 0x2d, 0xf8, 0xd2, 0x25, 0x45, 0xb3,
-       0xa5, 0xcb, 0xd1, 0x30, 0xa5, 0xa2, 0x53, 0xaf, 0xf4, 0x03, 0xff, 0x47,
-       0x2e, 0xc1, 0x0f, 0x07, 0x1e, 0x6d, 0x51, 0x22, 0x53, 0x0b, 0x8b, 0x21,
-       0x5e, 0x37, 0x7e, 0x2f, 0x7d, 0x30, 0x17, 0x7e, 0x40, 0xc8, 0xfe, 0xd1,
-       0x4b, 0x3c, 0x4e, 0xca, 0x26, 0xc5, 0x37, 0xbc, 0xf0, 0x50, 0xf7, 0xc5,
-       0xd4, 0xb8, 0x28, 0x73, 0x3d, 0x59, 0x7f, 0x33, 0x13, 0xfe, 0x5a, 0x9c,
-       0xbc, 0xe6, 0x3b, 0xba, 0x68, 0xd1, 0xb1, 0x8c, 0xfd, 0xf5, 0x14, 0x4d,
-       0x31, 0x5d, 0xbb, 0xe5, 0x05, 0x8f, 0x27, 0xe0, 0xd9, 0x34, 0xd3, 0x3e,
-       0xdb, 0xcd, 0x59, 0x4b, 0xe6, 0xdd, 0x89, 0xde, 0x73, 0x38, 0x46, 0xdd,
-       0xf1, 0x5f, 0xf5, 0x6b, 0x79, 0x90, 0xcc, 0xa2, 0x8e, 0x90, 0x3f, 0xf3,
-       0x3c, 0x1e, 0xb9, 0xff, 0x39, 0xdc, 0x07, 0xf2, 0x0e, 0x73, 0xe7, 0xe3,
-       0x55, 0xb9, 0xaf, 0x23, 0x7c, 0x6f, 0xd4, 0xdd, 0x1f, 0x2b, 0x4e, 0xf2,
-       0xfe, 0x76, 0x09, 0xde, 0x2c, 0xf7, 0x73, 0x9a, 0xce, 0x79, 0xf2, 0x15,
-       0xb9, 0x2f, 0x49, 0x17, 0x7d, 0x27, 0x05, 0x7d, 0x4f, 0x8b, 0xfd, 0x48,
-       0xe6, 0x0c, 0xd6, 0xd7, 0xb4, 0xef, 0x81, 0xed, 0xec, 0x5c, 0x40, 0xe7,
-       0x06, 0xf2, 0xf7, 0x0f, 0xfb, 0x45, 0x5e, 0x22, 0xec, 0xef, 0x1c, 0x3e,
-       0xa7, 0xe9, 0x79, 0x96, 0xeb, 0x2f, 0x64, 0x5a, 0xe8, 0x6a, 0xb6, 0x85,
-       0xde, 0xc9, 0x0e, 0xd1, 0x95, 0xc5, 0x6e, 0x3a, 0xc7, 0x3a, 0xf3, 0x39,
-       0x27, 0x60, 0xa5, 0xa9, 0x1b, 0xf1, 0x45, 0xe4, 0x0c, 0x31, 0xdd, 0x61,
-       0x3c, 0xf4, 0xbf, 0xe8, 0x5e, 0xc6, 0x39, 0xd6, 0xbd, 0x5b, 0xe9, 0x3d,
-       0x7e, 0x66, 0x3a, 0xa3, 0x73, 0x1d, 0xe0, 0x93, 0x1f, 0x2b, 0xeb, 0xaf,
-       0x5b, 0xe3, 0x88, 0xb9, 0x05, 0x8e, 0x4c, 0x8b, 0xf8, 0xd6, 0xc2, 0x22,
-       0xff, 0xbe, 0x08, 0xff, 0x39, 0xc3, 0x9b, 0xf9, 0xf3, 0x93, 0x01, 0x8c,
-       0xc7, 0x39, 0x47, 0xe6, 0x4a, 0x8a, 0xb5, 0x85, 0xf8, 0xd8, 0x27, 0x6a,
-       0xa4, 0x25, 0x1c, 0x5a, 0x79, 0x7d, 0x3e, 0x31, 0x3e, 0xb9, 0xda, 0x4a,
-       0xf3, 0x39, 0xd6, 0x41, 0x72, 0x7e, 0xb6, 0x61, 0x30, 0xf6, 0xef, 0x54,
-       0x6f, 0x61, 0xdc, 0xbf, 0x8b, 0xd2, 0x62, 0x1c, 0x7f, 0xae, 0x76, 0xd1,
-       0x42, 0xae, 0x43, 0x1d, 0xdf, 0x2b, 0x72, 0xdc, 0x65, 0x1f, 0x23, 0xfc,
-       0xb6, 0x19, 0x7f, 0x7b, 0x97, 0x71, 0x0a, 0x32, 0x55, 0xda, 0xa5, 0xe0,
-       0x35, 0x97, 0xeb, 0x7a, 0x22, 0x03, 0xe7, 0xa6, 0xe8, 0x25, 0x96, 0xb7,
-       0x23, 0x2f, 0xc3, 0x7f, 0xfc, 0x38, 0xf0, 0x26, 0x9f, 0xa2, 0x41, 0x3e,
-       0x46, 0x5f, 0x24, 0xbf, 0xa8, 0x73, 0x8a, 0x05, 0x27, 0x44, 0x6d, 0x88,
-       0xa4, 0xd1, 0x59, 0xd1, 0x8b, 0xee, 0x2d, 0xc1, 0x9b, 0xec, 0x94, 0x65,
-       0x40, 0x1f, 0x81, 0x0f, 0x46, 0xe6, 0x60, 0x1d, 0x77, 0x7a, 0xde, 0xed,
-       0x9b, 0x19, 0xa7, 0x48, 0x3f, 0xf0, 0x5e, 0xd2, 0xac, 0xea, 0x2f, 0x20,
-       0xf8, 0xbd, 0xb9, 0x4f, 0xd7, 0x4b, 0xea, 0x63, 0x2d, 0x2b, 0xf4, 0x71,
-       0x47, 0xcd, 0xef, 0x66, 0xcd, 0xef, 0xe5, 0x7c, 0x39, 0x96, 0x79, 0x2c,
-       0xe7, 0x49, 0xf6, 0x28, 0x4a, 0x2e, 0x4b, 0xfc, 0x33, 0xf7, 0x8d, 0x99,
-       0x8f, 0x2a, 0x1d, 0x3c, 0xb9, 0x36, 0x1a, 0xea, 0x31, 0x26, 0x8c, 0xe4,
-       0xe4, 0x3f, 0x96, 0x22, 0x09, 0xe8, 0x45, 0x4f, 0xee, 0x51, 0xf9, 0xa7,
-       0x3c, 0xaf, 0x54, 0x18, 0xaa, 0xdb, 0xec, 0x5a, 0x07, 0xad, 0x8b, 0x9e,
-       0x5c, 0x42, 0xc7, 0xe0, 0xeb, 0x71, 0x9f, 0x94, 0xd9, 0x44, 0xe8, 0x73,
-       0x0e, 0x1a, 0xdf, 0x1f, 0xba, 0xc4, 0xfb, 0x19, 0x5f, 0xfb, 0x69, 0xe9,
-       0xa4, 0xe8, 0x71, 0x83, 0xb1, 0x5d, 0x34, 0x27, 0x74, 0x7e, 0xd6, 0x5f,
-       0xaa, 0xec, 0xaa, 0x29, 0xcc, 0x33, 0x85, 0xd8, 0x8a, 0xe1, 0xfc, 0xbe,
-       0x2f, 0x99, 0x97, 0xb1, 0xf2, 0x78, 0x4d, 0xac, 0x7c, 0x56, 0xc4, 0xca,
-       0x11, 0x27, 0x07, 0x5c, 0x01, 0x4b, 0xaf, 0x9c, 0x16, 0xec, 0x63, 0x98,
-       0x90, 0x1b, 0x7e, 0xee, 0xa2, 0xe0, 0x37, 0xe1, 0x98, 0x5f, 0xe6, 0x57,
-       0xc7, 0x79, 0xc6, 0x06, 0x5d, 0x60, 0x7c, 0xb0, 0x27, 0x36, 0x58, 0x97,
-       0x58, 0xc9, 0x7e, 0x99, 0xae, 0xe4, 0x9b, 0x58, 0xd7, 0x5b, 0xa0, 0x8d,
-       0x3c, 0xb1, 0x4e, 0xd8, 0x4d, 0x0b, 0x61, 0xc6, 0xb1, 0x89, 0x36, 0xde,
-       0x4f, 0xd6, 0x6b, 0x27, 0x98, 0xee, 0x78, 0xee, 0x2b, 0xb9, 0xd2, 0x8f,
-       0xd2, 0xe1, 0x88, 0x15, 0x9d, 0xea, 0x60, 0xbb, 0xc5, 0xe4, 0x7f, 0x87,
-       0xff, 0x77, 0x85, 0x00, 0x93, 0xc2, 0x2a, 0x7e, 0x67, 0x9d, 0x27, 0x53,
-       0xfa, 0xd1, 0x1c, 0x8f, 0x99, 0x9b, 0x82, 0xfd, 0x03, 0x3b, 0xcf, 0xe1,
-       0x7f, 0x39, 0x66, 0x65, 0x95, 0xf1, 0xfb, 0x62, 0x2a, 0x64, 0x08, 0xde,
-       0xbe, 0xce, 0x3c, 0xfe, 0x02, 0xcd, 0xf1, 0x1c, 0xae, 0x10, 0xae, 0xb5,
-       0x28, 0x19, 0xde, 0xc7, 0x78, 0xdf, 0xcd, 0x9f, 0xa8, 0xbf, 0x6a, 0xa7,
-       0x85, 0xc9, 0x31, 0x55, 0x7f, 0xf5, 0xbd, 0x06, 0xf5, 0x57, 0xb8, 0x8e,
-       0xe5, 0xfe, 0x62, 0xe9, 0xe6, 0x5c, 0xd8, 0xfd, 0x3c, 0x32, 0x92, 0xe1,
-       0x4e, 0xa1, 0x23, 0xad, 0xac, 0xfa, 0xf8, 0xd9, 0x11, 0x2b, 0x39, 0xc5,
-       0x73, 0xcc, 0xb9, 0xe7, 0x5d, 0xba, 0x19, 0x0b, 0x63, 0x9c, 0xbf, 0x66,
-       0x1c, 0xdb, 0xca, 0x53, 0x72, 0x3d, 0x85, 0x5c, 0xe9, 0xe7, 0xd1, 0xb0,
-       0x5e, 0x9f, 0xfb, 0x5a, 0xac, 0x03, 0xf4, 0xc4, 0x9f, 0x2b, 0x5d, 0xbe,
-       0x2b, 0x59, 0xd8, 0xdf, 0x06, 0xe3, 0x39, 0x66, 0x34, 0x44, 0xa9, 0x15,
-       0xa6, 0xef, 0x8b, 0x1d, 0xbe, 0x8d, 0xec, 0x95, 0x52, 0xb2, 0x2a, 0x97,
-       0xa5, 0xda, 0xef, 0x2e, 0x6d, 0xae, 0x21, 0x72, 0x96, 0x20, 0x33, 0x21,
-       0x2f, 0x53, 0x25, 0xbf, 0x03, 0xfd, 0x0e, 0xb6, 0xd0, 0x59, 0xe6, 0x57,
-       0x32, 0x1f, 0x89, 0x79, 0x27, 0xf3, 0x2c, 0x49, 0x2f, 0xf1, 0xaa, 0xd7,
-       0x0d, 0x48, 0x9c, 0x1d, 0xa9, 0xe4, 0x41, 0xba, 0xe2, 0xe9, 0x01, 0x57,
-       0x3c, 0xdd, 0x74, 0xe5, 0x41, 0x06, 0x85, 0x3e, 0x56, 0xd1, 0xa1, 0x82,
-       0x4a, 0x87, 0x82, 0xae, 0x25, 0x79, 0x59, 0xa1, 0xcc, 0xcb, 0x76, 0x6f,
-       0xc1, 0xcb, 0xbc, 0x6c, 0xd3, 0x75, 0xc5, 0x37, 0xec, 0x30, 0xe4, 0xfc,
-       0xe5, 0xe2, 0x34, 0xbd, 0xcd, 0x3c, 0xe2, 0xad, 0x62, 0x98, 0xf9, 0xc6,
-       0x24, 0xf3, 0x8d, 0x09, 0xe6, 0x1b, 0x0e, 0xc3, 0xc0, 0xe2, 0xb5, 0x5f,
-       0xf3, 0x5d, 0x59, 0x84, 0xbc, 0x98, 0xa2, 0xe7, 0x8b, 0xe0, 0xc1, 0x93,
-       0xac, 0xf3, 0x5c, 0xf3, 0x6d, 0x2c, 0x76, 0x31, 0xbe, 0x4a, 0x3d, 0xa7,
-       0xda, 0x8e, 0x41, 0xaf, 0x15, 0xf8, 0x87, 0xaf, 0x82, 0xcf, 0xbc, 0x91,
-       0xa2, 0x4e, 0x86, 0x3d, 0xe0, 0xbc, 0x8e, 0xde, 0x14, 0xaf, 0x81, 0x96,
-       0xd1, 0x13, 0xf8, 0xbb, 0xe3, 0x53, 0x3c, 0xf7, 0x4e, 0xdf, 0x02, 0xef,
-       0xcb, 0xd3, 0xe1, 0x94, 0xd9, 0xcb, 0x38, 0x7f, 0xac, 0x82, 0xf3, 0xa9,
-       0x34, 0xaf, 0xa0, 0x67, 0xb9, 0x9b, 0xc6, 0x0e, 0x44, 0xf7, 0xf6, 0x30,
-       0x9d, 0x22, 0x37, 0xa2, 0xd2, 0xa7, 0xc7, 0x4f, 0x27, 0x83, 0x6d, 0xaa,
-       0xbf, 0x8f, 0xc5, 0xf2, 0xf1, 0x03, 0xbe, 0xcf, 0x2d, 0x5f, 0x3a, 0xfb,
-       0x2a, 0x3f, 0x03, 0xc7, 0x5f, 0x85, 0xff, 0x93, 0xed, 0x83, 0x56, 0xe1,
-       0x3f, 0x2a, 0x88, 0xb1, 0x38, 0xb6, 0x27, 0x98, 0x97, 0x85, 0xd7, 0x0d,
-       0x7b, 0x3a, 0x62, 0x30, 0xd1, 0x75, 0x99, 0xbc, 0xde, 0xd2, 0xa0, 0x8c,
-       0xc1, 0xed, 0xdd, 0x2b, 0xf9, 0x06, 0xe3, 0x66, 0x30, 0x22, 0x6c, 0xb4,
-       0xa6, 0x25, 0x29, 0x27, 0x0b, 0xbc, 0xcf, 0x2b, 0xe1, 0x09, 0xde, 0xe7,
-       0x0e, 0x25, 0x23, 0x53, 0xfc, 0xbb, 0x90, 0xbf, 0x2c, 0x2b, 0x87, 0xd0,
-       0xb3, 0xda, 0x14, 0xfd, 0x20, 0x66, 0xd1, 0x6f, 0xa7, 0x83, 0xef, 0x6b,
-       0x33, 0xd6, 0x82, 0x4f, 0x7c, 0xe0, 0x4b, 0x66, 0xf1, 0x5c, 0xe0, 0x21,
-       0x7f, 0xcf, 0x4f, 0xd1, 0x85, 0x8c, 0x9e, 0xc3, 0x80, 0x61, 0xbc, 0x84,
-       0x79, 0xf8, 0x68, 0xb7, 0xf3, 0x43, 0x86, 0x17, 0x1f, 0xff, 0x71, 0xed,
-       0x9c, 0x86, 0xd5, 0x9c, 0xd0, 0xd3, 0xb2, 0x05, 0x3d, 0x7c, 0x08, 0xbd,
-       0x8f, 0x0a, 0xa2, 0xe7, 0x64, 0xb3, 0xb0, 0x4d, 0x0b, 0xc2, 0xc6, 0x28,
-       0x85, 0x2a, 0x7d, 0x30, 0xef, 0xa9, 0x39, 0xf7, 0x13, 0x5f, 0x7a, 0xf1,
-       0xa0, 0xd0, 0xc5, 0x46, 0x0e, 0xec, 0x55, 0xf5, 0xa7, 0x5d, 0xe2, 0xbe,
-       0xc6, 0x32, 0x7e, 0x7b, 0x50, 0xfd, 0xf6, 0x49, 0xa1, 0x03, 0x23, 0x2f,
-       0x2e, 0xb0, 0x24, 0xf0, 0x9c, 0xf7, 0xd7, 0x99, 0x60, 0x3c, 0x0f, 0xad,
-       0xc0, 0x77, 0x2f, 0xe0, 0xa9, 0xe1, 0x01, 0x58, 0x00, 0xf7, 0x3b, 0x14,
-       0xde, 0xdb, 0x56, 0xdc, 0xaf, 0xd7, 0xdd, 0x08, 0xce, 0xac, 0xd3, 0x64,
-       0xb0, 0x56, 0xac, 0x69, 0x8f, 0x2f, 0x92, 0xb7, 0x8c, 0xf4, 0x22, 0x6c,
-       0x1a, 0xd4, 0xb5, 0xdc, 0x85, 0xbc, 0x29, 0x9e, 0xc3, 0x1e, 0x8a, 0x24,
-       0x30, 0x2f, 0x8c, 0xd3, 0x30, 0xf8, 0xb7, 0x1a, 0x58, 0xb8, 0xaf, 0xeb,
-       0x56, 0xd7, 0xb5, 0x8a, 0xbd, 0x20, 0x03, 0xcf, 0xd1, 0xcf, 0xc6, 0x73,
-       0xf1, 0x7c, 0x5c, 0x87, 0xfb, 0xc9, 0xfb, 0xf6, 0x31, 0x7f, 0x8e, 0x4e,
-       0xc9, 0x7b, 0x19, 0x97, 0xe4, 0x6f, 0x7d, 0x8e, 0xf7, 0x7c, 0xe5, 0xfe,
-       0xf9, 0x54, 0xbf, 0x1e, 0xec, 0x5f, 0x37, 0xe5, 0x85, 0x8f, 0x13, 0xbf,
-       0x75, 0x8a, 0xdf, 0xa2, 0x4e, 0xa7, 0xd8, 0xd7, 0xf3, 0x7c, 0x3c, 0x9f,
-       0xed, 0xf2, 0xc1, 0x36, 0x4f, 0x27, 0x3a, 0x7d, 0xf9, 0x3c, 0xd6, 0xdb,
-       0xe9, 0x8b, 0x33, 0xee, 0xc7, 0xb2, 0xf1, 0xd2, 0x82, 0xe0, 0x31, 0xac,
-       0xd3, 0xf6, 0xda, 0xe6, 0x49, 0xe3, 0x4f, 0x86, 0x64, 0x6f, 0x5b, 0x7c,
-       0x67, 0xfa, 0xcb, 0x30, 0xfd, 0x65, 0x98, 0xfe, 0x32, 0x4c, 0x7f, 0x19,
-       0xa6, 0x3f, 0xb6, 0x4b, 0xdf, 0x64, 0x99, 0xf1, 0x6d, 0x96, 0x19, 0x92,
-       0x66, 0x23, 0xca, 0x8f, 0xa9, 0x69, 0xb6, 0xb6, 0x3e, 0x53, 0xd3, 0x28,
-       0xe4, 0x34, 0xf9, 0x0e, 0x8f, 0x57, 0xd3, 0xea, 0x55, 0xa6, 0xd5, 0xa6,
-       0x99, 0x7e, 0xba, 0x91, 0xc3, 0x9e, 0xd9, 0xd6, 0x79, 0xe6, 0xd1, 0x71,
-       0x3f, 0x74, 0xaa, 0x00, 0xd3, 0x13, 0x74, 0x4a, 0x9b, 0xe1, 0xde, 0x4f,
-       0x37, 0x99, 0x4f, 0xdf, 0xc8, 0x81, 0x76, 0xef, 0x52, 0xc7, 0x19, 0xa6,
-       0x5d, 0xc8, 0xb9, 0x25, 0xdf, 0xd5, 0xac, 0xc1, 0xba, 0x57, 0xc0, 0x4c,
-       0x12, 0xf8, 0xa8, 0xd0, 0xc7, 0x78, 0xdf, 0xd7, 0x99, 0xdf, 0xc3, 0x57,
-       0x87, 0xbe, 0x5f, 0x79, 0x1f, 0xcb, 0x89, 0xd0, 0x15, 0xe6, 0xa3, 0xa7,
-       0x73, 0x4b, 0x4c, 0xef, 0xbd, 0xf4, 0x85, 0x1c, 0xe4, 0x31, 0x60, 0xc4,
-       0xc7, 0x79, 0x12, 0x3e, 0x30, 0x63, 0x06, 0x6b, 0x1f, 0x4b, 0x19, 0x02,
-       0x4f, 0x9e, 0x01, 0x1c, 0x18, 0xf6, 0x67, 0xf6, 0xa2, 0x67, 0x7d, 0xc4,
-       0x68, 0x56, 0x3e, 0x45, 0x7c, 0xc7, 0x78, 0x8c, 0x05, 0xdc, 0x70, 0xdc,
-       0x28, 0xfe, 0x88, 0xf7, 0x42, 0x84, 0x19, 0x1e, 0xb5, 0x7c, 0xeb, 0x02,
-       0x7a, 0x91, 0x02, 0x5e, 0xd3, 0x51, 0x3f, 0x6a, 0xc5, 0xe9, 0x39, 0xbc,
-       0xff, 0xe0, 0x85, 0x22, 0xe6, 0xbd, 0x48, 0x0b, 0x41, 0xf0, 0x21, 0x3b,
-       0x7c, 0x9d, 0x24, 0xec, 0x5a, 0x59, 0xbf, 0xfc, 0xbc, 0x37, 0x6f, 0xb3,
-       0xa2, 0x42, 0x1f, 0x6e, 0x61, 0xfb, 0x06, 0xb0, 0x79, 0x8b, 0x71, 0x2d,
-       0x0c, 0x9b, 0x5f, 0xf1, 0xb5, 0x37, 0x99, 0xe7, 0x60, 0xcf, 0x3a, 0x85,
-       0x8c, 0xf1, 0xe2, 0x65, 0x1b, 0x8a, 0x97, 0x39, 0x2e, 0x5e, 0x96, 0x2e,
-       0xf3, 0x32, 0xc6, 0x09, 0xc1, 0xc3, 0xc0, 0xa3, 0x66, 0x59, 0x4f, 0x94,
-       0xdf, 0xa1, 0xff, 0xed, 0x16, 0x3c, 0x8b, 0x79, 0x3d, 0xdb, 0x0d, 0x85,
-       0x62, 0xca, 0x77, 0x48, 0xf0, 0x0e, 0x8d, 0xd7, 0xff, 0xa3, 0xe8, 0xa1,
-       0x55, 0xf0, 0x81, 0xf4, 0x2c, 0xf8, 0x95, 0xd7, 0xf8, 0xff, 0x02, 0x6c,
-       0x79, 0xbc, 0x13, 0x7a, 0x8d, 0xf9, 0x58, 0x21, 0x0c, 0x9b, 0xb5, 0x43,
-       0xd9, 0x36, 0xe8, 0xbb, 0xb5, 0x07, 0xb9, 0x96, 0x56, 0xb4, 0xcc, 0xc7,
-       0x76, 0x2b, 0xbf, 0x05, 0xfc, 0x8c, 0xd8, 0xeb, 0x3a, 0x5d, 0xc0, 0x82,
-       0x2e, 0xc0, 0x63, 0x03, 0x0c, 0x1f, 0xd1, 0x1b, 0x9c, 0xe8, 0x16, 0xc3,
-       0x01, 0xfb, 0x7c, 0x0b, 0xfb, 0xcc, 0xba, 0x2c, 0x05, 0xe6, 0xa6, 0x02,
-       0x03, 0x98, 0xdf, 0xc2, 0x6a, 0x85, 0x1f, 0x9e, 0xcf, 0x0c, 0x18, 0x85,
-       0xac, 0x9c, 0xe3, 0xca, 0xb8, 0xe4, 0x79, 0x85, 0x3c, 0x7a, 0x7b, 0x89,
-       0xb9, 0xf2, 0x1c, 0xf5, 0xfa, 0x04, 0xff, 0x52, 0x74, 0xbf, 0x1d, 0x5a,
-       0x4b, 0x30, 0x5d, 0x61, 0x4f, 0x52, 0x2e, 0x9c, 0x79, 0x94, 0x9f, 0x8f,
-       0x73, 0x8d, 0xd7, 0x71, 0xb3, 0xbc, 0x8e, 0x08, 0xaf, 0x03, 0x63, 0x6f,
-       0xf9, 0x6e, 0xa8, 0x75, 0xdc, 0x28, 0xaf, 0x63, 0x56, 0xad, 0x83, 0xd2,
-       0xc6, 0xcc, 0x6e, 0xa5, 0xc7, 0x6f, 0x79, 0xcf, 0xd6, 0x28, 0xeb, 0x27,
-       0xe9, 0x55, 0xc0, 0xf3, 0x1e, 0x85, 0x2f, 0x6e, 0x7f, 0xa8, 0x7b, 0x6e,
-       0xf6, 0xc4, 0x75, 0xfa, 0x5d, 0xba, 0x29, 0xf4, 0x93, 0x61, 0xd6, 0x4f,
-       0x70, 0x9e, 0x16, 0xc0, 0x87, 0xd3, 0x41, 0xf4, 0x9b, 0x1d, 0x64, 0x98,
-       0xb1, 0x5d, 0x35, 0xc5, 0x9f, 0xc2, 0x4f, 0x86, 0xfb, 0xe8, 0xeb, 0xbf,
-       0x48, 0x37, 0x17, 0xc1, 0xab, 0xa1, 0x8f, 0xca, 0x9e, 0xb4, 0x37, 0xd7,
-       0xa4, 0x9f, 0x36, 0xee, 0xe9, 0xa7, 0x85, 0x8f, 0x36, 0x0c, 0x7d, 0xdd,
-       0x84, 0x3f, 0x37, 0x26, 0xde, 0x67, 0xc1, 0xc7, 0x45, 0xdc, 0xcb, 0x8b,
-       0xef, 0x4c, 0xbb, 0x72, 0xdc, 0x90, 0x73, 0x92, 0x62, 0x3e, 0xe2, 0x98,
-       0x4d, 0x86, 0xac, 0x9d, 0xb9, 0x5c, 0xd4, 0x3a, 0x51, 0x9c, 0xf7, 0xc8,
-       0x09, 0x1b, 0x46, 0x44, 0xf8, 0x0c, 0x5a, 0x9d, 0x0e, 0x6a, 0x61, 0x39,
-       0x79, 0x8a, 0xd0, 0x13, 0xcd, 0xb6, 0xe0, 0xcb, 0xbf, 0xc0, 0xb8, 0xb7,
-       0x10, 0xb6, 0x43, 0x9f, 0x13, 0xf6, 0x25, 0xe4, 0x07, 0xde, 0xa7, 0x02,
-       0x18, 0x63, 0x0e, 0xfc, 0x7d, 0x15, 0xfd, 0x30, 0xc3, 0xbc, 0x7e, 0xf8,
-       0x81, 0x47, 0xad, 0x77, 0x58, 0xee, 0x5c, 0x10, 0xfe, 0x95, 0xb3, 0x94,
-       0x66, 0x3a, 0x3c, 0x2c, 0xe8, 0xd0, 0x18, 0x66, 0x6a, 0x61, 0xfa, 0x41,
-       0x8e, 0xc1, 0x98, 0xe8, 0xbf, 0x23, 0x6d, 0x16, 0x5e, 0xe5, 0x9a, 0xea,
-       0x6b, 0x90, 0x00, 0x6f, 0xd8, 0xbe, 0x6f, 0x21, 0xf1, 0x91, 0x7d, 0x2a,
-       0x6e, 0x5d, 0xab, 0xd6, 0x87, 0x0d, 0xfb, 0xcc, 0x12, 0x7d, 0x1f, 0x01,
-       0x3b, 0xe1, 0x17, 0x34, 0x26, 0x19, 0x6e, 0xfa, 0xdd, 0x35, 0x6e, 0xfb,
-       0xff, 0x29, 0x51, 0x9f, 0xff, 0x46, 0x51, 0xca, 0xd8, 0x34, 0xdb, 0xe6,
-       0x0b, 0x07, 0xdc, 0x3a, 0x87, 0x9d, 0x8d, 0x09, 0x9f, 0xcc, 0x00, 0x45,
-       0x97, 0x27, 0xe9, 0xb1, 0x0c, 0x78, 0x14, 0x5d, 0x8f, 0x3a, 0x78, 0xc3,
-       0x06, 0x68, 0x79, 0x92, 0xe2, 0x45, 0xc0, 0xc8, 0x47, 0x0b, 0x2c, 0x05,
-       0xd2, 0x59, 0xc4, 0xee, 0xf9, 0x7b, 0x1e, 0xef, 0x57, 0xf9, 0x15, 0xe5,
-       0xf7, 0x1e, 0xa2, 0xd8, 0x32, 0xa5, 0x92, 0xe1, 0x87, 0x45, 0xcf, 0xea,
-       0x64, 0x78, 0x5c, 0xf9, 0x68, 0x42, 0x7c, 0x1e, 0x7e, 0x2f, 0x8b, 0x1e,
-       0xcd, 0xd8, 0xa9, 0x24, 0x49, 0xdf, 0x03, 0xf1, 0x1c, 0x0c, 0x96, 0xad,
-       0xbb, 0x99, 0x57, 0x1c, 0x17, 0xfe, 0x07, 0xd6, 0x44, 0x16, 0x31, 0x1e,
-       0xbe, 0x83, 0x5e, 0x82, 0xbd, 0x95, 0xcc, 0x3e, 0xa0, 0xc6, 0x96, 0xc8,
-       0x64, 0x5c, 0x30, 0x7f, 0xc9, 0x49, 0x85, 0x8d, 0xca, 0xf5, 0xf0, 0x5d,
-       0x1c, 0x17, 0xfa, 0xe1, 0x30, 0xdb, 0x30, 0x62, 0x5c, 0x69, 0x4e, 0xf8,
-       0x21, 0xf8, 0x38, 0xff, 0xd3, 0x01, 0xfd, 0x6e, 0x03, 0x9c, 0x97, 0xfe,
-       0x09, 0xbe, 0x67, 0x9e, 0xe7, 0x51, 0x95, 0x17, 0x3f, 0x44, 0x91, 0x1d,
-       0xf8, 0x8b, 0x66, 0xef, 0xa8, 0xbf, 0x88, 0x61, 0xcd, 0xb2, 0xe5, 0x32,
-       0xd3, 0xc6, 0xdb, 0x5b, 0xda, 0x71, 0xef, 0x6b, 0x19, 0xcd, 0xb0, 0x32,
-       0xc5, 0xfb, 0x2f, 0xd0, 0xeb, 0x73, 0xa1, 0xf8, 0x29, 0xbc, 0x47, 0xc6,
-       0x97, 0x10, 0x3a, 0x6f, 0x88, 0x75, 0x17, 0xe8, 0x30, 0xa3, 0x22, 0xbe,
-       0x15, 0x79, 0xc2, 0x32, 0x16, 0xd6, 0xfa, 0xc9, 0x0f, 0xbf, 0x9a, 0xa3,
-       0x73, 0x22, 0x5a, 0x45, 0xfe, 0xba, 0x8c, 0x2b, 0x42, 0xfe, 0x82, 0x07,
-       0xfe, 0xc4, 0x97, 0x5c, 0xf3, 0xf7, 0xe9, 0x7c, 0xb7, 0x48, 0xb0, 0x9c,
-       0x4f, 0xa3, 0x78, 0x8a, 0xc6, 0x3d, 0x1d, 0xb3, 0x70, 0xbf, 0xd7, 0x0a,
-       0xb4, 0xeb, 0xd6, 0x19, 0xe0, 0x67, 0x12, 0x7b, 0x74, 0x01, 0x71, 0x5c,
-       0xa3, 0x2a, 0x1e, 0xd1, 0xc2, 0xfb, 0x04, 0x3b, 0x0f, 0xfe, 0xbb, 0xcf,
-       0xf2, 0x27, 0xe2, 0x0a, 0x27, 0x07, 0xa1, 0x27, 0xf5, 0x38, 0x8c, 0x33,
-       0x53, 0x38, 0xee, 0x67, 0xbb, 0x4b, 0xeb, 0xb5, 0xd2, 0xa7, 0xc4, 0xb6,
-       0x98, 0xda, 0x2f, 0xf8, 0x93, 0x46, 0x54, 0xbf, 0x01, 0x9b, 0xac, 0x5e,
-       0xc0, 0xe9, 0xe3, 0xa2, 0xc7, 0xad, 0x62, 0x10, 0xdb, 0xc9, 0x59, 0xc2,
-       0x3b, 0xb7, 0xd0, 0x77, 0xf3, 0x6e, 0xc0, 0x9e, 0xf7, 0xc8, 0x1d, 0xa3,
-       0xf8, 0x94, 0x7a, 0xff, 0xcf, 0x9d, 0xda, 0xb7, 0x5d, 0x1e, 0xfb, 0xf6,
-       0xbd, 0x41, 0x19, 0x03, 0xbb, 0x4b, 0x8d, 0xf1, 0xca, 0x53, 0xfd, 0xfb,
-       0xa7, 0xe1, 0x4f, 0xaa, 0xd4, 0x51, 0x5c, 0x13, 0x7c, 0xa5, 0xde, 0xa7,
-       0x1d, 0x62, 0x7e, 0x2a, 0xe9, 0xf8, 0xb8, 0x07, 0x1d, 0xf7, 0xce, 0x40,
-       0x2f, 0xb9, 0x7d, 0x3a, 0x3e, 0xd6, 0x90, 0x8e, 0xff, 0x75, 0x50, 0xfa,
-       0x54, 0xeb, 0xe9, 0x18, 0xb5, 0x3c, 0xc7, 0x8b, 0x8d, 0xfc, 0x57, 0xd8,
-       0x07, 0xd4, 0xa4, 0xc3, 0xe7, 0x01, 0x58, 0x69, 0xbf, 0x07, 0xe2, 0x7e,
-       0xc0, 0x47, 0xc4, 0x4e, 0xfe, 0x90, 0xe2, 0x8b, 0xb5, 0xb1, 0xd0, 0xcd,
-       0xae, 0xf9, 0x96, 0xc7, 0x35, 0xd0, 0xc5, 0x41, 0x0b, 0x76, 0x48, 0xda,
-       0xf4, 0x1a, 0x5e, 0xef, 0xf9, 0x0e, 0xe5, 0xec, 0x54, 0x9e, 0xe0, 0xa3,
-       0x0e, 0xd2, 0x53, 0x88, 0x2b, 0x2b, 0x1f, 0xf0, 0xd1, 0x8c, 0x5c, 0xb7,
-       0x79, 0x40, 0xe0, 0x03, 0xf4, 0xd5, 0x50, 0xc2, 0x9f, 0xe0, 0x3d, 0x95,
-       0xfe, 0xdf, 0xe4, 0x6a, 0x48, 0xed, 0x13, 0x8f, 0xc5, 0xfd, 0x3c, 0xeb,
-       0xfc, 0xb0, 0x3f, 0xf6, 0xd7, 0xd7, 0xcb, 0x79, 0xc5, 0x90, 0x05, 0x25,
-       0xfa, 0x0f, 0x96, 0x73, 0xfe, 0x03, 0xa6, 0xe8, 0xb9, 0x70, 0xb9, 0x78,
-       0x80, 0xf5, 0x47, 0xec, 0x21, 0x7c, 0x87, 0xda, 0xb7, 0xfb, 0xf6, 0x30,
-       0x75, 0xed, 0x67, 0xa9, 0x6f, 0x90, 0xc3, 0x7a, 0xa3, 0x71, 0x00, 0xf9,
-       0xe1, 0x16, 0x5f, 0x83, 0x5e, 0x51, 0x63, 0x56, 0x9c, 0x3a, 0xe0, 0x4f,
-       0x40, 0x0f, 0x68, 0x2b, 0x5d, 0x45, 0x53, 0xb3, 0x82, 0xa6, 0xe2, 0x6b,
-       0xb3, 0x8a, 0xa6, 0x66, 0x95, 0xff, 0x7c, 0x56, 0xd1, 0xd4, 0xac, 0xa2,
-       0xa9, 0x59, 0x45, 0x53, 0xb3, 0x8c, 0xd7, 0xa3, 0xac, 0xaf, 0x42, 0xf7,
-       0xd0, 0xfe, 0xcb, 0x2e, 0x4a, 0xe6, 0x70, 0x1e, 0xf2, 0xb8, 0x96, 0xae,
-       0x7e, 0x6d, 0x58, 0xfb, 0x47, 0x0b, 0x32, 0xcf, 0x8e, 0x9f, 0x85, 0x3d,
-       0x78, 0x98, 0xe1, 0x77, 0xcd, 0x37, 0xbf, 0x88, 0xb9, 0xfa, 0x28, 0x26,
-       0x7a, 0xc0, 0x36, 0x51, 0xd4, 0xad, 0xe3, 0x9a, 0xa8, 0xeb, 0x92, 0xb6,
-       0x5c, 0xaa, 0x61, 0x8d, 0x97, 0xc6, 0x8b, 0x69, 0xb5, 0x5f, 0xb5, 0x76,
-       0x4e, 0x0b, 0x25, 0xb2, 0x80, 0x2b, 0x72, 0x21, 0x2d, 0xde, 0x1b, 0x01,
-       0xa7, 0x94, 0xe9, 0x01, 0x83, 0xa3, 0x0a, 0x06, 0x4f, 0x8b, 0x35, 0x22,
-       0x97, 0x10, 0x3e, 0xc8, 0xc6, 0x70, 0x48, 0x67, 0x46, 0xf9, 0x3e, 0x8c,
-       0xfb, 0x07, 0x42, 0xcc, 0x83, 0xb6, 0x0b, 0x07, 0xf7, 0xda, 0x1b, 0xf1,
-       0x9a, 0xed, 0xd6, 0xd3, 0x5c, 0x77, 0xc9, 0x8e, 0x90, 0x92, 0x1b, 0x52,
-       0xef, 0xdd, 0xe5, 0xd8, 0x89, 0x14, 0xcf, 0xed, 0x2f, 0xc2, 0x7f, 0x39,
-       0x44, 0x6d, 0x25, 0x3a, 0x12, 0x06, 0x3e, 0x77, 0xb1, 0x5d, 0xc9, 0x73,
-       0x18, 0x2b, 0xd1, 0x85, 0xf0, 0x3e, 0xb6, 0x5d, 0xf6, 0xb3, 0x0e, 0x3a,
-       0xca, 0xff, 0x4e, 0xc4, 0xef, 0xc3, 0xbc, 0x3a, 0xf8, 0xda, 0x7e, 0x32,
-       0x7a, 0x52, 0x66, 0x2b, 0xeb, 0x07, 0x47, 0x2a, 0xf6, 0x88, 0x05, 0xff,
-       0x1c, 0xeb, 0xb6, 0xc6, 0x5c, 0xb8, 0x5b, 0xd5, 0x9c, 0xc1, 0x87, 0x8d,
-       0xf8, 0xd6, 0x3f, 0x97, 0x64, 0xaf, 0x80, 0x21, 0x75, 0xfc, 0xe3, 0x52,
-       0x64, 0x08, 0xc7, 0x78, 0xe7, 0x90, 0x3d, 0x11, 0xf1, 0xfd, 0x58, 0xea,
-       0xf2, 0x3e, 0xfb, 0x88, 0x7c, 0x3f, 0x80, 0x6d, 0x5a, 0x3e, 0x2f, 0xbc,
-       0x97, 0x3a, 0x4f, 0x25, 0x5f, 0x15, 0x74, 0x50, 0xa2, 0x7f, 0x67, 0x9a,
-       0x35, 0x09, 0xb1, 0x8c, 0x29, 0x51, 0x0b, 0x8d, 0x7c, 0xe5, 0xf9, 0x45,
-       0x3d, 0x2f, 0x47, 0xed, 0xf5, 0xfd, 0xc8, 0x37, 0xcb, 0x16, 0x68, 0x73,
-       0x99, 0x01, 0x3f, 0xda, 0xe8, 0xf2, 0x46, 0x4f, 0x50, 0xd4, 0x66, 0x77,
-       0xb3, 0x8e, 0xa3, 0xf3, 0x92, 0xc7, 0xf8, 0xfe, 0x01, 0xf1, 0xbe, 0xb9,
-       0xd8, 0x12, 0xc6, 0x35, 0xd3, 0xc8, 0x72, 0xe9, 0x21, 0xfe, 0x5d, 0xc4,
-       0x11, 0x93, 0xd4, 0xaa, 0x62, 0x04, 0x1d, 0x2a, 0xae, 0x14, 0x62, 0x5a,
-       0xaa, 0xd4, 0x1c, 0x8f, 0x94, 0x7d, 0x6d, 0xc0, 0xf1, 0x5a, 0x5f, 0xdb,
-       0x73, 0x5b, 0xc8, 0x9b, 0xad, 0xf0, 0x1a, 0x39, 0xa5, 0x2d, 0xa4, 0x7c,
-       0x88, 0xd6, 0x02, 0x6d, 0xb7, 0xb6, 0x6e, 0xc7, 0xd7, 0xb4, 0x36, 0xcf,
-       0xac, 0x9f, 0x79, 0xc7, 0x69, 0x53, 0xf8, 0xd4, 0x4c, 0xf3, 0xb9, 0x36,
-       0x96, 0xd9, 0xa8, 0x97, 0x02, 0xbc, 0xfc, 0x43, 0xa8, 0x37, 0x79, 0x32,
-       0xd0, 0x4c, 0xab, 0xab, 0xc8, 0x79, 0x78, 0xfc, 0x2e, 0x99, 0xe7, 0xfb,
-       0x08, 0xc3, 0x65, 0x3f, 0xcb, 0x37, 0x43, 0xc5, 0x70, 0x70, 0x0e, 0xbc,
-       0x41, 0xf4, 0xfd, 0x0c, 0x3c, 0x3c, 0xde, 0xc6, 0x7a, 0xbd, 0x8c, 0x01,
-       0x1c, 0xe4, 0x7b, 0x7f, 0x33, 0xf7, 0x08, 0xfc, 0x59, 0xe6, 0x61, 0xbe,
-       0x7f, 0x8c, 0xf5, 0x81, 0x08, 0x35, 0xd3, 0xca, 0x6a, 0x33, 0xeb, 0xf5,
-       0xcd, 0xac, 0x0f, 0x8c, 0x9a, 0x23, 0x3e, 0xf1, 0x2c, 0x51, 0xdb, 0xf2,
-       0xe9, 0xc0, 0x7e, 0xc6, 0x41, 0x3c, 0xeb, 0x8b, 0xea, 0x59, 0xb5, 0xcf,
-       0xb8, 0x55, 0xc2, 0xf1, 0x61, 0xff, 0xfa, 0x99, 0xab, 0x78, 0x2f, 0xd4,
-       0xe2, 0x34, 0xeb, 0xbe, 0x41, 0xf1, 0x6e, 0x46, 0x63, 0x66, 0x86, 0xed,
-       0x80, 0x30, 0x1f, 0x1f, 0xa1, 0x54, 0x31, 0x41, 0xbf, 0x57, 0x74, 0xfb,
-       0x6a, 0x8f, 0xf0, 0x9c, 0x65, 0x6d, 0x7d, 0x0b, 0xcf, 0xeb, 0x7d, 0xa7,
-       0x96, 0x67, 0xb4, 0x91, 0xff, 0x6b, 0x41, 0x6a, 0x7e, 0x11, 0xbe, 0x91,
-       0x12, 0x65, 0xc3, 0xf6, 0x85, 0xeb, 0xe2, 0xbd, 0x1b, 0x16, 0xbd, 0x22,
-       0xf2, 0x5b, 0xf9, 0x7a, 0xbe, 0xe7, 0x79, 0x8c, 0x7b, 0xc5, 0xa2, 0x2b,
-       0x8e, 0x84, 0xf7, 0x9f, 0x05, 0x82, 0xe4, 0x7f, 0x1d, 0x39, 0x48, 0xd0,
-       0xb5, 0xd6, 0xcf, 0x38, 0xfb, 0x98, 0x5f, 0xbf, 0x88, 0xeb, 0xf8, 0xf3,
-       0x75, 0x1c, 0xb7, 0xf1, 0x3a, 0x21, 0x6f, 0x91, 0x77, 0x02, 0x3e, 0xb7,
-       0x3f, 0x64, 0x0a, 0xfc, 0x3b, 0xc2, 0x38, 0xd5, 0x24, 0x7c, 0x81, 0xbd,
-       0x18, 0xeb, 0x0c, 0xb2, 0x6e, 0xb0, 0x7e, 0x66, 0x7c, 0x1f, 0x8e, 0x23,
-       0x3d, 0x7e, 0x86, 0x91, 0xc4, 0xa1, 0xb0, 0x78, 0xff, 0xa1, 0xeb, 0x2f,
-       0x70, 0x70, 0x9c, 0x78, 0x3f, 0xa1, 0x3f, 0xf0, 0x7e, 0x9a, 0xe8, 0xb3,
-       0xd4, 0x46, 0x71, 0x7e, 0x46, 0x2c, 0x27, 0xd7, 0x7d, 0xbe, 0xe8, 0x27,
-       0xe9, 0x47, 0x6a, 0x1e, 0xd6, 0xef, 0x29, 0xa4, 0x7e, 0xdc, 0x5b, 0xd3,
-       0x0a, 0xbe, 0x77, 0xd1, 0x8d, 0x5c, 0x07, 0xdd, 0x54, 0xb1, 0xa5, 0x1b,
-       0xc2, 0xae, 0x62, 0x9e, 0x9c, 0xe8, 0xa2, 0xeb, 0xab, 0x4d, 0x44, 0xbd,
-       0x6d, 0x22, 0xf6, 0x7b, 0x23, 0x97, 0xc7, 0xf3, 0x87, 0xa5, 0xdf, 0xa5,
-       0x82, 0x23, 0x37, 0x3c, 0x70, 0xe4, 0x3d, 0x81, 0x23, 0xef, 0x6d, 0x81,
-       0x23, 0x7b, 0x95, 0x2d, 0xd1, 0x46, 0xcd, 0x0a, 0x3f, 0x5e, 0x63, 0xfc,
-       0x78, 0x81, 0xf1, 0xe3, 0x50, 0x03, 0xfc, 0x30, 0x6a, 0xf0, 0xe3, 0xb0,
-       0xc0, 0x8f, 0x9f, 0x6d, 0x8a, 0x1f, 0x87, 0xfc, 0x9b, 0xf9, 0x82, 0x34,
-       0x6e, 0x0e, 0xd0, 0x4a, 0xce, 0xa1, 0xd5, 0x45, 0x9b, 0x2d, 0x7b, 0xd8,
-       0xe6, 0x88, 0x19, 0xce, 0x88, 0x7a, 0x97, 0x82, 0xc0, 0x2b, 0x96, 0xe3,
-       0x33, 0xa8, 0x69, 0xaa, 0xdb, 0x03, 0x12, 0xef, 0xa5, 0x14, 0xf0, 0x97,
-       0x7b, 0x12, 0xcb, 0xac, 0x9f, 0xf9, 0x73, 0xde, 0xc7, 0x2b, 0x6b, 0x81,
-       0x00, 0x7e, 0xf3, 0xcf, 0x04, 0x69, 0x63, 0x8d, 0xed, 0x54, 0xc6, 0xb1,
-       0xab, 0xb9, 0x21, 0xba, 0x92, 0x1b, 0xa0, 0x8d, 0xdc, 0x30, 0xbd, 0x93,
-       0xc3, 0x33, 0x00, 0x73, 0x3e, 0x16, 0x30, 0x37, 0xe8, 0x60, 0x90, 0xc7,
-       0xac, 0x0e, 0xd0, 0xfa, 0xaa, 0xc6, 0x57, 0xe0, 0x2a, 0xf6, 0x3f, 0xd2,
-       0x23, 0xeb, 0xd0, 0xea, 0x71, 0x20, 0x56, 0x85, 0x03, 0xf2, 0x1a, 0xec,
-       0xfd, 0x42, 0x7d, 0x0d, 0x6d, 0xab, 0x39, 0x83, 0x1c, 0xb8, 0x36, 0xb6,
-       0xc9, 0x6d, 0xe1, 0x73, 0x3d, 0xe8, 0x87, 0x4e, 0x6b, 0xdc, 0x4d, 0x5d,
-       0xbc, 0x07, 0x0e, 0xf2, 0x87, 0x86, 0x59, 0x3f, 0xed, 0x16, 0xfa, 0x68,
-       0xd4, 0x09, 0x84, 0x62, 0x54, 0x3a, 0x6b, 0x38, 0xe8, 0x93, 0xf8, 0x08,
-       0xdf, 0xcf, 0x50, 0x7e, 0x9e, 0x4e, 0x17, 0x3e, 0xd5, 0xea, 0x9e, 0x88,
-       0xd1, 0x9e, 0xe0, 0x39, 0x43, 0x4e, 0x56, 0xe2, 0x22, 0x54, 0x8e, 0x8b,
-       0xb4, 0xf2, 0xba, 0x25, 0x2d, 0xcd, 0x39, 0x3c, 0xae, 0xc8, 0xe3, 0x8a,
-       0x88, 0xa9, 0xf1, 0xf9, 0x55, 0xc4, 0x73, 0x87, 0x68, 0x63, 0x11, 0x34,
-       0x07, 0xff, 0x44, 0x25, 0x86, 0xba, 0xb1, 0x86, 0xf3, 0xf0, 0x51, 0x54,
-       0x62, 0xa8, 0x1b, 0x2a, 0x86, 0xba, 0xb1, 0x36, 0x2d, 0xf8, 0xf0, 0x42,
-       0x8e, 0x79, 0x40, 0xce, 0xaf, 0xf2, 0x07, 0xf7, 0xa9, 0x77, 0xf6, 0x9c,
-       0x10, 0x3e, 0xe4, 0x1e, 0x67, 0x73, 0x18, 0x1e, 0xac, 0x83, 0xe1, 0xb4,
-       0xd0, 0x83, 0xe2, 0x7c, 0xcf, 0x58, 0xee, 0x04, 0xc3, 0x73, 0x96, 0x69,
-       0x69, 0xb7, 0xa2, 0x25, 0x1d, 0x93, 0xed, 0x26, 0xf5, 0xfe, 0x1f, 0xa1,
-       0xeb, 0x4b, 0xfe, 0x33, 0x54, 0xc3, 0x7f, 0x28, 0x10, 0x1d, 0x97, 0xd7,
-       0xa7, 0x8b, 0xaf, 0x0c, 0x6b, 0xff, 0x5b, 0x9a, 0xef, 0xbb, 0x90, 0xdb,
-       0x49, 0x4c, 0x97, 0xe5, 0xa6, 0x67, 0xce, 0xe0, 0x76, 0x9f, 0xad, 0x71,
-       0xe1, 0xc4, 0x6d, 0xe0, 0x93, 0xbc, 0x47, 0x05, 0x9f, 0xfe, 0x77, 0x16,
-       0xc0, 0xb2, 0x93, 0x05, 0x98, 0x57, 0x84, 0x80, 0xf5, 0x03, 0x03, 0xb4,
-       0x8e, 0x39, 0x00, 0x1e, 0x53, 0x68, 0x02, 0xe6, 0x19, 0xa7, 0xf5, 0x40,
-       0xfb, 0xfb, 0x95, 0xc1, 0xeb, 0x5d, 0x1b, 0xa0, 0x67, 0x4f, 0x2d, 0xea,
-       0x79, 0x2c, 0x07, 0xca, 0xa3, 0x4e, 0x2a, 0x0c, 0x24, 0xe6, 0x27, 0x90,
-       0xff, 0x80, 0xfe, 0x00, 0xf9, 0x11, 0x98, 0x9f, 0x9c, 0x81, 0x72, 0xa0,
-       0x35, 0x53, 0xcd, 0x6b, 0x40, 0xfa, 0x40, 0x61, 0x08, 0x2a, 0x53, 0x41,
-       0x63, 0x1d, 0x40, 0xf6, 0x12, 0x21, 0x68, 0xd8, 0x01, 0x69, 0x20, 0xbb,
-       0x79, 0x8a, 0x08, 0x98, 0x9f, 0x14, 0x20, 0xc4, 0xd0, 0x00, 0xcf, 0x4f,
-       0xec, 0x40, 0x97, 0xc2, 0xdc, 0xf4, 0xff, 0xff, 0x31, 0x15, 0x16, 0x60,
-       0xda, 0x03, 0xad, 0xf9, 0xfc, 0xfd, 0xff, 0x80, 0x08, 0x0b, 0x43, 0x0b,
-       0x7c, 0xed, 0x9e, 0xb0, 0x3c, 0xa8, 0x9c, 0x5b, 0x00, 0x64, 0xb5, 0xc1,
-       0xeb, 0x6d, 0x16, 0xf0, 0x7d, 0xc4, 0x0b, 0x18, 0x7e, 0x01, 0xcb, 0x95,
-       0xff, 0xff, 0x97, 0xc2, 0xd5, 0x82, 0x00, 0x00, 0xd4, 0xc2, 0xcb, 0x42,
-       0x60, 0x7c, 0x00, 0x00, 0x00 };
-static u32 bnx2_COM_b09FwData[(0x0/4) + 1] = { 0x0 };
-static u32 bnx2_COM_b09FwRodata[(0x88/4) + 1] = {
-       0x08001ad8, 0x08001b14, 0x08001b14, 0x08001b14, 0x08001b14, 0x08001b14,
-       0x08001a24, 0x08001b14, 0x08001a98, 0x08001b14, 0x080019ac, 0x08001b14,
-       0x08001b14, 0x08001b14, 0x080019b8, 0x0, 0x08002a2c, 0x08002a7c,
-       0x08002aac, 0x08002adc, 0x08002b0c, 0x0, 0x08005fac, 0x08005fac,
-       0x08005fac, 0x08005fac, 0x08005fac, 0x08005fd8, 0x08005fd8, 0x08006018,
-       0x08006024, 0x08006024, 0x08005fac, 0x0, 0x0 };
-static u32 bnx2_COM_b09FwBss[(0x88/4) + 1] = { 0x0 };
-static u32 bnx2_COM_b09FwSbss[(0x5c/4) + 1] = { 0x0 };
+       0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xdc, 0x5b,
+       0x6d, 0x70, 0x5c, 0xd5, 0x79, 0x7e, 0xef, 0xd9, 0xbb, 0xf2, 0x5a, 0x92,
+       0xe5, 0x6b, 0x79, 0x23, 0x16, 0x4b, 0xc0, 0xae, 0x75, 0x6d, 0x69, 0xb0,
+       0x43, 0x16, 0xa1, 0x80, 0x9a, 0xd9, 0xc0, 0xb2, 0x2b, 0x33, 0x9e, 0x0c,
+       0x69, 0x64, 0x50, 0x80, 0xb6, 0x4c, 0x46, 0xec, 0x1a, 0x9a, 0x4e, 0x87,
+       0xd6, 0xa6, 0x6e, 0x9b, 0xc9, 0x34, 0x78, 0x47, 0x1f, 0x8d, 0xa7, 0x15,
+       0xba, 0x06, 0x1b, 0xd9, 0xd3, 0xd0, 0xa0, 0x6a, 0x71, 0xf1, 0x8f, 0x8d,
+       0xaf, 0xf9, 0x48, 0xaa, 0x4c, 0x4d, 0xa5, 0x18, 0x48, 0x69, 0xa7, 0x4d,
+       0xfb, 0xa3, 0x9e, 0xa1, 0x5f, 0x84, 0x32, 0xfd, 0xc1, 0x74, 0xda, 0x4e,
+       0x3a, 0x24, 0x53, 0x08, 0x84, 0xed, 0xf3, 0x9c, 0x7b, 0xee, 0xea, 0x6a,
+       0x25, 0x7f, 0xf1, 0x91, 0x1f, 0xd5, 0xcc, 0xfa, 0xde, 0xf3, 0xfd, 0x9e,
+       0xf7, 0xbc, 0xef, 0xf3, 0x7e, 0xdc, 0xe3, 0x4f, 0x8a, 0xb4, 0x8a, 0xf9,
+       0xdb, 0x80, 0x5f, 0xfa, 0xc1, 0xdf, 0x2c, 0x5f, 0x37, 0x78, 0xdd, 0x0d,
+       0x78, 0xbd, 0x41, 0xc5, 0xec, 0x18, 0xeb, 0xf9, 0x4f, 0x12, 0xbf, 0x01,
+       0xf3, 0xbe, 0xd6, 0x9f, 0x83, 0xdf, 0x9b, 0x68, 0x1c, 0xfb, 0x0f, 0x11,
+       0xeb, 0x3c, 0x7d, 0xa2, 0x7f, 0xf5, 0xfa, 0x85, 0xdb, 0x15, 0x69, 0xb9,
+       0x40, 0x7b, 0x2c, 0x58, 0x52, 0xd3, 0xcc, 0x9f, 0x24, 0x54, 0x6e, 0xec,
+       0xe1, 0x82, 0x2b, 0x89, 0x58, 0x6e, 0xf7, 0xc1, 0xb2, 0x2b, 0x92, 0xaf,
+       0xed, 0x48, 0x17, 0xe5, 0x67, 0xf5, 0x4a, 0xd2, 0x16, 0xd6, 0x5f, 0x95,
+       0x7b, 0xef, 0xc9, 0x17, 0x6e, 0xca, 0xfc, 0x68, 0x2e, 0x26, 0x09, 0x27,
+       0xf7, 0xbc, 0x38, 0xdb, 0x25, 0xd1, 0x83, 0x31, 0x4f, 0xf4, 0xe5, 0x2d,
+       0xe9, 0x08, 0xe7, 0x7a, 0xb3, 0xfe, 0x42, 0x9f, 0x54, 0xb6, 0xe4, 0x12,
+       0xa2, 0x72, 0xdb, 0x5e, 0x2d, 0xc4, 0x9c, 0xb1, 0x58, 0xce, 0x91, 0x45,
+       0x5f, 0x46, 0xee, 0x9f, 0x96, 0x44, 0x22, 0xf7, 0xe5, 0xc4, 0xba, 0x6d,
+       0x92, 0xb0, 0x73, 0x4b, 0x0f, 0xff, 0xbe, 0x7b, 0xb0, 0xae, 0x5c, 0xb7,
+       0x7f, 0x5e, 0xda, 0x87, 0x4e, 0x0c, 0xa2, 0xbd, 0x96, 0xe9, 0x17, 0xb9,
+       0x49, 0x94, 0x5b, 0x69, 0x8f, 0xb9, 0x09, 0x29, 0xf8, 0xae, 0x14, 0x7d,
+       0x91, 0xbf, 0xac, 0x59, 0x72, 0xc2, 0xed, 0x92, 0xf9, 0x9d, 0xef, 0xd5,
+       0xf3, 0xa0, 0xe5, 0xfb, 0xee, 0xd2, 0xc3, 0x93, 0x2e, 0xe9, 0x3d, 0x90,
+       0x08, 0xe8, 0xdd, 0xbb, 0xae, 0xec, 0xda, 0x32, 0x5e, 0x63, 0xdd, 0xa8,
+       0x62, 0x5d, 0x3c, 0x97, 0x68, 0x3d, 0xe1, 0xb6, 0x9b, 0xba, 0x57, 0x6f,
+       0x29, 0x60, 0xbe, 0x89, 0x1a, 0xfb, 0xe6, 0xaf, 0x2f, 0xbb, 0x49, 0x53,
+       0xbf, 0x70, 0x63, 0xc1, 0x4d, 0xa1, 0xbe, 0xc7, 0xb4, 0x8d, 0x3d, 0x58,
+       0x76, 0x5d, 0xd3, 0xf6, 0x76, 0xac, 0xe0, 0xf6, 0x9b, 0xfa, 0xf7, 0x6e,
+       0x2e, 0xbb, 0x3b, 0x4d, 0x7d, 0x0f, 0xe6, 0xca, 0x9a, 0xfa, 0x85, 0x7b,
+       0xca, 0xee, 0xa0, 0xa9, 0xdf, 0x7d, 0x73, 0xc1, 0x1d, 0x32, 0xf5, 0x89,
+       0xa1, 0xb2, 0x9b, 0x43, 0xfd, 0x97, 0x13, 0x6a, 0x9b, 0x23, 0x53, 0xb5,
+       0x34, 0x7e, 0x79, 0xb4, 0x0d, 0xa3, 0x6e, 0x37, 0x7e, 0xb7, 0xe3, 0xf7,
+       0xc8, 0x46, 0xe9, 0x18, 0xc1, 0xf3, 0xbf, 0xba, 0x03, 0xde, 0x81, 0x47,
+       0x5e, 0x42, 0x5e, 0x8f, 0xa5, 0xe4, 0x85, 0xbe, 0xd7, 0xc1, 0x43, 0x47,
+       0x4e, 0xfb, 0x62, 0x8d, 0xf4, 0xa5, 0xc0, 0xbb, 0xa4, 0x3c, 0xe3, 0xb7,
+       0x49, 0xec, 0xb1, 0x18, 0x78, 0xf3, 0xcb, 0x52, 0x4a, 0x26, 0x64, 0xd3,
+       0xac, 0x25, 0x5b, 0x07, 0x12, 0x92, 0x77, 0xb8, 0x36, 0x4e, 0x7b, 0x26,
+       0x29, 0xb1, 0xd9, 0xfc, 0x66, 0x25, 0xdb, 0x9c, 0xa2, 0x54, 0xc0, 0xbb,
+       0x57, 0x29, 0x97, 0x68, 0x4b, 0x4b, 0x71, 0xfa, 0x5a, 0x19, 0x73, 0x48,
+       0xd7, 0x1f, 0x5c, 0x15, 0xac, 0x95, 0xb0, 0x0a, 0xc7, 0x46, 0x65, 0xca,
+       0x6b, 0xb7, 0x8a, 0xc7, 0x6e, 0x96, 0x42, 0x56, 0x92, 0x18, 0x97, 0x2a,
+       0xa1, 0xa5, 0x5a, 0x1b, 0x95, 0x49, 0x4f, 0xac, 0x82, 0x47, 0x7e, 0x76,
+       0xa1, 0xbd, 0x43, 0xf7, 0x45, 0x5d, 0x4f, 0x4c, 0xcf, 0x9d, 0x40, 0xbd,
+       0x83, 0xfa, 0x4e, 0x6b, 0x58, 0xcf, 0xa1, 0xeb, 0xd3, 0x13, 0xd2, 0x2e,
+       0x4f, 0xd5, 0x92, 0xa6, 0x6f, 0xbd, 0x5e, 0xc8, 0x3a, 0xe8, 0x37, 0x2a,
+       0x13, 0x5e, 0x52, 0xc6, 0xf0, 0x1c, 0xf7, 0xb8, 0x7e, 0x0a, 0x32, 0x75,
+       0xdd, 0xc1, 0xd2, 0x51, 0x3d, 0x5f, 0x3a, 0x96, 0xe3, 0x7c, 0x3d, 0xe8,
+       0xf7, 0x12, 0xe8, 0xb2, 0xc4, 0xd6, 0x67, 0x99, 0x97, 0xd2, 0xb4, 0x05,
+       0x79, 0xc3, 0x53, 0xf3, 0x75, 0x18, 0xf4, 0xdb, 0xe2, 0x0e, 0x58, 0x52,
+       0xc6, 0x59, 0x55, 0x1c, 0x94, 0x6b, 0x0b, 0xaa, 0xe0, 0xad, 0x93, 0xa2,
+       0x9d, 0x96, 0xd8, 0x0c, 0x65, 0x69, 0x4c, 0x26, 0x30, 0x46, 0xb9, 0xec,
+       0xf3, 0x0e, 0xf6, 0x3d, 0xa6, 0xcf, 0xa1, 0x25, 0x57, 0x51, 0x45, 0xbf,
+       0x4b, 0xd4, 0xec, 0xbd, 0xf2, 0xd2, 0xb4, 0x38, 0x38, 0xc7, 0x7a, 0xc1,
+       0x9d, 0x54, 0x85, 0xa7, 0x6d, 0x89, 0xcf, 0x58, 0x32, 0xe9, 0x66, 0xa0,
+       0x01, 0x87, 0xd4, 0x2e, 0x7f, 0x01, 0xfd, 0x38, 0x0e, 0xfd, 0x6a, 0x0a,
+       0x7c, 0xe5, 0xfb, 0x0e, 0x47, 0x69, 0x79, 0x66, 0x1f, 0x9c, 0x01, 0xf6,
+       0xf1, 0x8c, 0x87, 0x33, 0xd1, 0x67, 0x94, 0xc6, 0x19, 0x89, 0x35, 0xdc,
+       0x07, 0x99, 0x3a, 0x6a, 0x4b, 0x29, 0x8b, 0x7d, 0xa1, 0x77, 0x29, 0xbb,
+       0x4c, 0xd7, 0xc4, 0x74, 0x33, 0x5d, 0x1c, 0x47, 0xba, 0x02, 0x9a, 0xc6,
+       0x8f, 0x92, 0xbe, 0x65, 0x7a, 0xa6, 0xa6, 0x43, 0x1a, 0xb9, 0x1e, 0x69,
+       0x0b, 0xe9, 0xe2, 0x38, 0xd2, 0xb5, 0x99, 0x67, 0xcd, 0x3f, 0x6b, 0x18,
+       0x74, 0x4c, 0x78, 0x36, 0xce, 0xa8, 0x5d, 0x4a, 0x4e, 0xc5, 0x9a, 0x18,
+       0xda, 0x91, 0x82, 0x36, 0x5b, 0xe3, 0x43, 0xa4, 0xd9, 0xc5, 0x39, 0xb6,
+       0xe8, 0xf3, 0x56, 0xb9, 0x49, 0xf2, 0x0e, 0xfd, 0xb9, 0x3e, 0xde, 0x6b,
+       0x8e, 0x4c, 0xea, 0xf9, 0x48, 0xd3, 0x47, 0x31, 0x0f, 0x69, 0x7d, 0x05,
+       0xb2, 0x3a, 0x08, 0x19, 0xcd, 0xca, 0x5f, 0xf8, 0x3b, 0xe5, 0xcf, 0xfc,
+       0x7e, 0xf9, 0x0e, 0xf4, 0xf6, 0xdb, 0x7e, 0x5a, 0x9e, 0xf7, 0x7b, 0xe4,
+       0x39, 0x3f, 0x25, 0xcf, 0x6a, 0xf9, 0x1d, 0x16, 0xe9, 0xa0, 0x4c, 0xa7,
+       0xa5, 0x13, 0xfa, 0xb3, 0x09, 0xba, 0xf9, 0x38, 0xf8, 0x77, 0xb4, 0x4f,
+       0xf2, 0x9b, 0x73, 0x92, 0xb8, 0x1a, 0xbf, 0x2b, 0xf0, 0xeb, 0xca, 0xd9,
+       0x5a, 0x56, 0xec, 0x1c, 0x79, 0x68, 0x4b, 0x51, 0xef, 0xd9, 0x96, 0x09,
+       0xff, 0x91, 0xab, 0x03, 0xd9, 0x15, 0x19, 0x01, 0x8f, 0xd5, 0xc0, 0x4f,
+       0xea, 0x79, 0x07, 0xfb, 0x18, 0xd8, 0xa1, 0x79, 0xaf, 0x06, 0x28, 0xb3,
+       0x69, 0xc8, 0xbd, 0x6d, 0x15, 0xbd, 0x93, 0xc0, 0x8d, 0x36, 0xab, 0x70,
+       0xa4, 0x22, 0xe5, 0x23, 0x75, 0x29, 0x67, 0xe3, 0xf2, 0x90, 0x53, 0x97,
+       0xe1, 0x6c, 0x8b, 0xec, 0x77, 0xc0, 0xfb, 0x9d, 0xbf, 0x6d, 0x85, 0x98,
+       0xfd, 0xb8, 0xff, 0x3b, 0x78, 0x67, 0x9d, 0xc8, 0x51, 0xfd, 0x1e, 0xd4,
+       0x57, 0xfc, 0xb8, 0xe4, 0x93, 0x95, 0x94, 0x2d, 0x5b, 0x54, 0xb0, 0xee,
+       0x78, 0xd8, 0x06, 0x7e, 0x2c, 0x01, 0x27, 0x33, 0x5a, 0x5f, 0x4a, 0xd3,
+       0xeb, 0xdf, 0xce, 0xeb, 0x6a, 0xf4, 0x77, 0x06, 0xe5, 0xac, 0xe6, 0x67,
+       0x7a, 0xcc, 0xca, 0x25, 0x65, 0x6b, 0x8d, 0xe5, 0x21, 0xeb, 0x4e, 0x9f,
+       0xf2, 0x8c, 0x77, 0x9f, 0x74, 0x5e, 0x89, 0x7e, 0x36, 0x9e, 0x79, 0x43,
+       0x6f, 0x94, 0x46, 0xce, 0x43, 0x1a, 0xf9, 0xfc, 0x66, 0x84, 0xc6, 0x27,
+       0x1b, 0xef, 0x47, 0x23, 0xef, 0x15, 0xff, 0x8f, 0x5a, 0x03, 0xda, 0x86,
+       0xe4, 0x8d, 0x99, 0xaf, 0x98, 0x75, 0xf0, 0x7e, 0x8a, 0xf3, 0x7f, 0xab,
+       0x1e, 0xc8, 0x4b, 0xe5, 0x22, 0xeb, 0x2c, 0x44, 0xd6, 0xf9, 0x6e, 0x64,
+       0x9d, 0xef, 0x46, 0xd6, 0xa9, 0x80, 0xa7, 0xb2, 0x51, 0x41, 0x86, 0x4b,
+       0x34, 0x63, 0x72, 0x08, 0x73, 0xbe, 0x2e, 0xb1, 0x1c, 0xf5, 0x3c, 0xc4,
+       0x9b, 0x73, 0xe8, 0x9f, 0x93, 0xb3, 0x33, 0x15, 0x29, 0x1d, 0x89, 0xcb,
+       0x1d, 0xba, 0xdf, 0x26, 0x43, 0x5f, 0xb4, 0x2d, 0x21, 0x7b, 0x92, 0x7c,
+       0x0f, 0xdb, 0x6c, 0xf0, 0x99, 0xe5, 0x6f, 0x5d, 0x19, 0x94, 0xf9, 0xbe,
+       0x60, 0xf6, 0x32, 0x1a, 0x8c, 0x3b, 0xf5, 0xa6, 0xc6, 0xc3, 0x45, 0x9f,
+       0xb8, 0x25, 0xd9, 0x98, 0x2b, 0xfb, 0x86, 0xb3, 0x5d, 0x32, 0xe1, 0x58,
+       0xd9, 0xf1, 0xfe, 0x75, 0xd4, 0x8b, 0xbc, 0x72, 0xdb, 0x80, 0x0d, 0x92,
+       0x56, 0xc4, 0x7c, 0xbd, 0x2f, 0x4b, 0x05, 0xf4, 0x3b, 0x2c, 0x8f, 0x28,
+       0xb7, 0xb3, 0xa9, 0x9e, 0xba, 0x1d, 0xc3, 0x3b, 0x65, 0x78, 0x97, 0x39,
+       0x63, 0x1b, 0x65, 0xe2, 0xf0, 0x35, 0xa6, 0x1c, 0xb6, 0x6f, 0xb6, 0x57,
+       0x96, 0xcf, 0x76, 0xaf, 0x2c, 0x87, 0x38, 0x11, 0xc5, 0x70, 0xee, 0x15,
+       0xf8, 0xe4, 0x52, 0xee, 0xe2, 0xa0, 0x35, 0x0b, 0x9d, 0x5b, 0x67, 0x68,
+       0xb8, 0xc2, 0xd0, 0x00, 0x5a, 0xfb, 0x20, 0x59, 0x5a, 0x97, 0xb4, 0x68,
+       0x35, 0x95, 0xc9, 0xfb, 0xf0, 0x7d, 0x83, 0x6e, 0x0f, 0x74, 0x2e, 0x7c,
+       0x86, 0xf8, 0xfe, 0x66, 0xc4, 0x5e, 0xf4, 0x40, 0x67, 0x93, 0xe0, 0x55,
+       0x88, 0xf5, 0xc4, 0xe0, 0x14, 0xec, 0x03, 0x64, 0x55, 0x63, 0x7b, 0x3b,
+       0xf0, 0xd0, 0x36, 0xd8, 0x9c, 0x30, 0xd8, 0xdc, 0x0e, 0x5c, 0x66, 0xd9,
+       0x31, 0xe5, 0xa4, 0x29, 0xa7, 0x50, 0x86, 0x1d, 0x9f, 0x25, 0x2e, 0x5f,
+       0x77, 0x70, 0xef, 0x51, 0x8d, 0xf7, 0xb4, 0x15, 0x40, 0x61, 0xe2, 0x35,
+       0x71, 0xbb, 0x47, 0xe6, 0x6b, 0x58, 0xaf, 0x81, 0x8d, 0xdc, 0x7b, 0x94,
+       0x1e, 0xd2, 0xb2, 0x5e, 0x14, 0x6c, 0x57, 0x3e, 0x49, 0x7a, 0x1f, 0xc4,
+       0xde, 0x89, 0x3f, 0xa4, 0xfb, 0x2a, 0xd0, 0xca, 0x7d, 0xfc, 0x3c, 0x69,
+       0xe5, 0x7a, 0xcd, 0xf4, 0x7e, 0x58, 0x1c, 0x24, 0xed, 0x27, 0xb1, 0xe7,
+       0x3c, 0x30, 0x4f, 0xac, 0xd1, 0xbe, 0x51, 0xec, 0x79, 0x04, 0x78, 0x78,
+       0x3b, 0xf0, 0x70, 0x37, 0xf0, 0x70, 0x18, 0x78, 0x98, 0x03, 0x16, 0x0e,
+       0x01, 0x0b, 0x07, 0x81, 0x85, 0x59, 0xf0, 0x26, 0x29, 0x73, 0xc0, 0xc6,
+       0x39, 0x60, 0xe4, 0x1c, 0xe6, 0x18, 0x9f, 0x15, 0xeb, 0x4b, 0xd8, 0xc3,
+       0x63, 0x33, 0x99, 0x93, 0x90, 0xa5, 0x54, 0x45, 0x41, 0xfe, 0xb3, 0x43,
+       0x90, 0xed, 0x7e, 0xa9, 0xfa, 0xb6, 0x94, 0x69, 0x53, 0xb7, 0xf7, 0x42,
+       0xd7, 0x20, 0xef, 0x29, 0x31, 0x7f, 0x1b, 0xcc, 0xf3, 0x1f, 0x45, 0xdc,
+       0xbf, 0xa3, 0x2c, 0xa6, 0x45, 0xce, 0x48, 0xc9, 0xeb, 0x75, 0x0a, 0xaa,
+       0x1f, 0xfd, 0x58, 0xce, 0xaa, 0xfb, 0x8f, 0x5c, 0xaf, 0xf6, 0x1e, 0x21,
+       0x5f, 0xa6, 0x81, 0x57, 0x75, 0x99, 0xcc, 0x52, 0xb7, 0xea, 0x72, 0x22,
+       0x9b, 0x19, 0xaa, 0x48, 0x9b, 0x4c, 0x25, 0xa7, 0xb5, 0xad, 0xb5, 0x73,
+       0x87, 0xb5, 0xbd, 0x2a, 0xbb, 0x78, 0xd6, 0x06, 0x54, 0xe9, 0x08, 0xf7,
+       0xdf, 0x8b, 0x5f, 0x1c, 0xb4, 0x70, 0x7e, 0x5b, 0x86, 0x07, 0x1d, 0xf5,
+       0x40, 0x5f, 0x05, 0x08, 0x96, 0x71, 0xce, 0x62, 0xe5, 0xe2, 0x74, 0x6f,
+       0xaa, 0xa8, 0x6c, 0x19, 0xb3, 0x2d, 0x19, 0x87, 0x7c, 0x0f, 0x67, 0xdf,
+       0xa9, 0x4f, 0x25, 0xd9, 0xbe, 0x4e, 0xbe, 0xae, 0x7d, 0x0e, 0xac, 0x5d,
+       0x3d, 0x8a, 0x75, 0xe3, 0x38, 0x03, 0xae, 0xcb, 0x79, 0x50, 0xae, 0xd9,
+       0x28, 0x67, 0x4e, 0x56, 0xc4, 0x87, 0x9e, 0x6c, 0x94, 0xc2, 0xce, 0x16,
+       0xc9, 0x8f, 0xa4, 0x65, 0x7c, 0xc6, 0x07, 0x4e, 0xe1, 0x1c, 0xdd, 0x56,
+       0x29, 0x8d, 0xa6, 0xe5, 0xd1, 0x19, 0xd6, 0x9d, 0xc6, 0xfe, 0x33, 0x87,
+       0xf2, 0xc2, 0xfd, 0xc7, 0xf5, 0xbe, 0xd2, 0xea, 0xb4, 0xec, 0xf7, 0xde,
+       0x30, 0x7a, 0x14, 0x94, 0xef, 0xc7, 0x99, 0x9e, 0xf0, 0x17, 0xb0, 0x7f,
+       0x57, 0xe6, 0x81, 0xff, 0xc5, 0x23, 0xc0, 0x41, 0xb7, 0x03, 0x98, 0x95,
+       0x59, 0xa0, 0x4d, 0x8d, 0xc1, 0xef, 0xab, 0x6a, 0x5e, 0xf7, 0xc8, 0x91,
+       0x19, 0x25, 0xdf, 0xbe, 0x31, 0x8d, 0x32, 0xb0, 0x31, 0x9b, 0x39, 0x3d,
+       0xa6, 0x7a, 0xe4, 0x86, 0xce, 0x14, 0xc6, 0xe5, 0x54, 0xc9, 0xdb, 0x18,
+       0x03, 0x2f, 0x8f, 0xa7, 0x15, 0xfb, 0x2a, 0x29, 0x66, 0x63, 0x38, 0xff,
+       0x0a, 0xfa, 0xbf, 0x8f, 0xf5, 0x7a, 0x64, 0x16, 0xbe, 0xd6, 0xec, 0x4c,
+       0x1e, 0xe3, 0x88, 0x5d, 0x99, 0xe3, 0x4b, 0x0a, 0x18, 0x33, 0x0b, 0xf9,
+       0x1e, 0x85, 0x2f, 0x33, 0x03, 0xd1, 0x69, 0x4d, 0xe3, 0x4c, 0x7b, 0x9d,
+       0x71, 0xe0, 0x41, 0xbe, 0x87, 0xef, 0x9c, 0xd3, 0x95, 0x13, 0x1e, 0xe5,
+       0x30, 0x2d, 0x4f, 0xf9, 0x1c, 0xd7, 0xbb, 0xf0, 0x1c, 0x7c, 0x9f, 0xdf,
+       0xf5, 0xae, 0x44, 0xff, 0x77, 0xe1, 0x07, 0x3b, 0x52, 0xc5, 0xb9, 0x95,
+       0xc1, 0xcb, 0x7c, 0x2a, 0x28, 0x8f, 0xcf, 0x66, 0x16, 0xde, 0x50, 0x7c,
+       0x77, 0x2b, 0xf3, 0xea, 0x5a, 0x91, 0x4e, 0xf2, 0x33, 0x0b, 0x5e, 0xba,
+       0x8e, 0x52, 0xdb, 0x8d, 0xef, 0x47, 0x3d, 0x72, 0x41, 0x9f, 0x2d, 0xf3,
+       0x03, 0x51, 0x3d, 0xa2, 0x3d, 0x0c, 0xf5, 0x28, 0x93, 0x5a, 0x52, 0x0a,
+       0xed, 0xb6, 0x1c, 0xd6, 0x65, 0x0b, 0xb4, 0x66, 0x52, 0xdc, 0xdf, 0x44,
+       0xad, 0x5f, 0x9e, 0xf2, 0xd8, 0x1f, 0x7c, 0x9e, 0x6e, 0x37, 0xfd, 0x4f,
+       0x83, 0x87, 0xf4, 0xdf, 0xfa, 0x41, 0x73, 0xa0, 0x5b, 0xf3, 0xd3, 0x49,
+       0xdd, 0x36, 0xe5, 0x05, 0x7e, 0x9a, 0x82, 0x2f, 0x37, 0x07, 0x5f, 0xae,
+       0xa8, 0xf5, 0xcc, 0xc9, 0xc3, 0xd7, 0x87, 0x9e, 0x04, 0x3a, 0x56, 0xad,
+       0x91, 0x96, 0xbb, 0x40, 0x5f, 0xa6, 0x02, 0x62, 0x0e, 0xab, 0x1c, 0xce,
+       0x7d, 0x50, 0x2a, 0xf4, 0xf7, 0xce, 0xc6, 0x9e, 0x92, 0xb1, 0x2a, 0xed,
+       0x11, 0x7e, 0x9e, 0xeb, 0x30, 0xbe, 0xc8, 0x6b, 0x5b, 0xd1, 0x0d, 0x39,
+       0x80, 0x1d, 0xc9, 0x6e, 0x32, 0x7e, 0xce, 0x13, 0x38, 0xcf, 0x33, 0x38,
+       0xf7, 0x9a, 0xec, 0x3d, 0xf6, 0x0a, 0x65, 0xba, 0xbf, 0x2a, 0x99, 0xfe,
+       0x29, 0xd9, 0xe1, 0xcc, 0x43, 0x1f, 0xf3, 0xa3, 0xf5, 0x5b, 0x54, 0x8e,
+       0x63, 0x0e, 0x62, 0x0c, 0x9e, 0xd5, 0x57, 0xe4, 0x21, 0x9f, 0x75, 0x0f,
+       0x81, 0x9f, 0xd0, 0x95, 0xc1, 0x27, 0x8c, 0x1e, 0x60, 0x3e, 0x3b, 0x9c,
+       0xef, 0x15, 0x33, 0x1f, 0xfb, 0xb1, 0x0f, 0xc7, 0x2c, 0xcf, 0xbb, 0x8b,
+       0xb6, 0x08, 0x78, 0xb4, 0x4b, 0xd5, 0x6f, 0x89, 0xa3, 0xfd, 0xc4, 0x20,
+       0xdf, 0x31, 0x0f, 0x6c, 0x91, 0xe3, 0x9e, 0x41, 0x5f, 0xf8, 0x7a, 0xde,
+       0x7a, 0x29, 0x74, 0x85, 0xf4, 0x52, 0x06, 0xe8, 0x27, 0x68, 0x1b, 0xbc,
+       0x39, 0xe0, 0xfd, 0x1f, 0xc6, 0x02, 0x99, 0x3c, 0x80, 0x32, 0xf5, 0xef,
+       0x80, 0x14, 0xbd, 0x0c, 0xf6, 0x09, 0x1d, 0xf3, 0x3b, 0xac, 0x60, 0x8f,
+       0xe0, 0xff, 0xc8, 0x39, 0xf0, 0x41, 0x2a, 0x01, 0x6f, 0xc8, 0x17, 0xf2,
+       0xa4, 0x03, 0xb2, 0x0f, 0xb9, 0x87, 0xdc, 0x96, 0x34, 0x0f, 0xfe, 0xbd,
+       0x33, 0xf0, 0x8b, 0x33, 0x95, 0x3c, 0xe3, 0xb9, 0x4e, 0xe2, 0x26, 0x30,
+       0xcc, 0x87, 0x70, 0x60, 0xee, 0x25, 0xb5, 0x9e, 0xf4, 0xa6, 0x97, 0x62,
+       0x7d, 0x2c, 0xf7, 0x2f, 0x41, 0x86, 0xab, 0x38, 0x9f, 0xc2, 0xce, 0x5e,
+       0x83, 0x5b, 0xcf, 0xc6, 0x28, 0xaf, 0x55, 0x60, 0x4c, 0xc9, 0xdb, 0xe1,
+       0xdc, 0x4d, 0xbe, 0x39, 0x8e, 0x3c, 0xe7, 0x45, 0xb1, 0x03, 0xb6, 0xcf,
+       0xa5, 0x1c, 0x26, 0x21, 0x07, 0x36, 0x6c, 0x68, 0x0a, 0x67, 0xfe, 0x6f,
+       0x9d, 0xc1, 0x5e, 0xf8, 0x6e, 0xcb, 0x9c, 0x83, 0x35, 0xbd, 0xc5, 0x8d,
+       0x41, 0x1d, 0xdf, 0xb7, 0xf0, 0x8c, 0x0e, 0xaf, 0xa4, 0x9d, 0xe7, 0xdb,
+       0x7c, 0xa6, 0x27, 0xb0, 0x17, 0xd6, 0xe3, 0x59, 0x3d, 0x2e, 0x7b, 0x89,
+       0x9b, 0x83, 0xdb, 0x52, 0x2f, 0xa2, 0x7f, 0x11, 0x36, 0xa1, 0x62, 0xb3,
+       0xed, 0x6d, 0x6b, 0x79, 0x8c, 0xa2, 0x5f, 0x0a, 0x1f, 0x78, 0xc9, 0xfa,
+       0x92, 0xff, 0x92, 0x55, 0xa8, 0xbe, 0x6d, 0x15, 0x21, 0x27, 0x55, 0x8f,
+       0xf1, 0x0b, 0xf5, 0xc7, 0xc1, 0xda, 0x99, 0xd4, 0x5b, 0xaa, 0x37, 0x3d,
+       0x0f, 0x2c, 0xb8, 0x1f, 0x3a, 0x5d, 0xb4, 0x17, 0xa4, 0xec, 0xd7, 0xa4,
+       0x74, 0x6c, 0x07, 0xf4, 0x2d, 0x1d, 0xa1, 0x8b, 0x78, 0x56, 0xa1, 0x1f,
+       0x6e, 0xed, 0xf2, 0xa4, 0xd2, 0x92, 0x23, 0xae, 0x6d, 0x83, 0xec, 0xa0,
+       0xae, 0xb6, 0x2c, 0x7f, 0xb7, 0xad, 0xa2, 0x15, 0xb1, 0xee, 0xe0, 0x4a,
+       0x7a, 0xab, 0x72, 0x71, 0x7a, 0x77, 0x35, 0xe8, 0x25, 0x66, 0x00, 0xff,
+       0x3d, 0xe0, 0xbf, 0x07, 0xfc, 0xf7, 0x80, 0xff, 0x1e, 0xf0, 0xdf, 0x83,
+       0x6d, 0xf0, 0x60, 0x03, 0x3c, 0xd8, 0x00, 0x0f, 0x36, 0xc0, 0x83, 0x0d,
+       0xf0, 0x0a, 0x38, 0x27, 0xe2, 0x3c, 0x6d, 0xc8, 0x3d, 0x0d, 0xbb, 0x19,
+       0xf8, 0x39, 0x57, 0x1a, 0xdf, 0x01, 0xfa, 0xe7, 0x6c, 0x91, 0xf1, 0xfe,
+       0x2b, 0xb0, 0xb7, 0x56, 0x3c, 0xdb, 0xf0, 0xc4, 0x1a, 0xfd, 0x9f, 0x35,
+       0x7a, 0xf2, 0x55, 0xd0, 0xa5, 0x50, 0xfe, 0x05, 0xc8, 0x61, 0x0b, 0xe8,
+       0xf9, 0x94, 0xf1, 0x31, 0xbe, 0x61, 0x07, 0x72, 0xd8, 0x86, 0xba, 0xcf,
+       0xa0, 0xae, 0x0d, 0x7d, 0xf6, 0xa3, 0x0f, 0x7d, 0x94, 0x0e, 0x53, 0x17,
+       0xed, 0x47, 0x5f, 0xe5, 0x0b, 0x58, 0x2b, 0x83, 0x7e, 0x1d, 0x98, 0xbb,
+       0x07, 0x7d, 0x6e, 0x46, 0x9f, 0xab, 0x50, 0xa6, 0x6f, 0xdb, 0x8d, 0xf2,
+       0xa7, 0x9b, 0xc6, 0x5c, 0x83, 0xba, 0xcf, 0x36, 0xd5, 0x9d, 0x45, 0x1d,
+       0x62, 0x62, 0xe7, 0x45, 0x33, 0xae, 0x82, 0x72, 0x57, 0x53, 0x9f, 0x57,
+       0x50, 0x37, 0x84, 0xba, 0xbf, 0xc2, 0x13, 0xb1, 0xb0, 0x43, 0x9a, 0xc2,
+       0x36, 0xfa, 0xa9, 0x69, 0xd4, 0xc7, 0x8d, 0xaf, 0xf9, 0x24, 0x7d, 0x2f,
+       0xd8, 0xdc, 0x3f, 0xb6, 0x03, 0xdf, 0x0c, 0xde, 0xab, 0x96, 0xc3, 0xb0,
+       0xfc, 0xcd, 0xa6, 0x32, 0xfb, 0x7e, 0xbf, 0xa9, 0xae, 0x6d, 0xd3, 0xca,
+       0xf2, 0x4f, 0xe3, 0xab, 0xc7, 0xdc, 0xdb, 0xd4, 0xe7, 0xeb, 0x9d, 0x2b,
+       0xcb, 0xbb, 0x5b, 0x56, 0x8f, 0xd9, 0xbe, 0x71, 0x65, 0xdd, 0xad, 0x9b,
+       0x57, 0x96, 0xe9, 0x03, 0x26, 0x11, 0xc3, 0x84, 0xfd, 0x77, 0x7e, 0x22,
+       0x68, 0x27, 0x7f, 0x9b, 0x65, 0x49, 0x2b, 0x23, 0xca, 0x0a, 0xe7, 0xb0,
+       0x64, 0x41, 0x9f, 0x1c, 0x95, 0x7b, 0xc9, 0x2a, 0x42, 0xa6, 0x0a, 0x7e,
+       0x38, 0x1f, 0x75, 0xb6, 0x39, 0x4f, 0x10, 0xe6, 0x07, 0xe8, 0x6f, 0xb5,
+       0x43, 0x6e, 0xee, 0xa2, 0x4d, 0x3a, 0x54, 0x91, 0x65, 0xfd, 0xdc, 0xaa,
+       0xce, 0xa7, 0x9f, 0xf7, 0x19, 0x8c, 0x3a, 0x07, 0x3a, 0xeb, 0x32, 0x92,
+       0x5d, 0x47, 0x1b, 0x63, 0xb0, 0x8b, 0xb8, 0x53, 0xaf, 0xc7, 0xb6, 0xd7,
+       0x65, 0x5f, 0xf6, 0xdd, 0xba, 0x68, 0xcc, 0xbb, 0x57, 0xe3, 0x4e, 0x5a,
+       0x75, 0xe3, 0x8c, 0x1c, 0xc4, 0x12, 0x88, 0xed, 0x93, 0xb4, 0x49, 0xc7,
+       0xe9, 0x9f, 0x1c, 0x0c, 0x30, 0x95, 0xb8, 0x83, 0xb2, 0x3f, 0x85, 0x39,
+       0xb9, 0x3e, 0x9e, 0x55, 0xe2, 0xb8, 0xad, 0x6d, 0x4a, 0xc9, 0xe1, 0xbc,
+       0x6b, 0x61, 0xe3, 0xbf, 0xd8, 0xf4, 0x0b, 0x6d, 0xf7, 0x24, 0xec, 0x1b,
+       0xdb, 0xe8, 0x2b, 0x9c, 0xa4, 0x5f, 0x12, 0xc1, 0xaa, 0x9b, 0x62, 0xe2,
+       0x2e, 0x63, 0x66, 0xb0, 0xaf, 0x2d, 0xf4, 0xfb, 0x2f, 0x61, 0xaf, 0x6b,
+       0x63, 0x51, 0xaf, 0xba, 0xb8, 0x6e, 0xef, 0x69, 0xe8, 0x76, 0x28, 0x7b,
+       0x6b, 0xe5, 0x03, 0x5e, 0xd5, 0x67, 0xf1, 0xac, 0x9f, 0x39, 0x5c, 0x81,
+       0x2e, 0x2d, 0xea, 0xd8, 0x37, 0x3c, 0x17, 0xfa, 0x38, 0x99, 0xe3, 0x73,
+       0x90, 0xed, 0xbd, 0x3a, 0x26, 0x60, 0x3c, 0x50, 0x97, 0x5d, 0xd9, 0x4f,
+       0x25, 0xc9, 0x87, 0xbc, 0xfa, 0x71, 0x9c, 0x3e, 0xc3, 0xa2, 0x47, 0x9e,
+       0x65, 0xd1, 0x9e, 0x05, 0x26, 0xfc, 0xab, 0x14, 0x93, 0xac, 0x7b, 0xab,
+       0x3e, 0x0f, 0xbf, 0x4a, 0xfb, 0x47, 0xda, 0xde, 0xd3, 0xbf, 0x83, 0x5d,
+       0xf7, 0xc9, 0xd3, 0x25, 0xf0, 0x39, 0xf4, 0x01, 0x7e, 0x40, 0x1f, 0x55,
+       0x56, 0xfa, 0xd2, 0x22, 0x0f, 0xd5, 0xfe, 0x01, 0x36, 0x47, 0x05, 0xbe,
+       0x0a, 0xe3, 0x65, 0x97, 0xf5, 0x37, 0xc6, 0xe9, 0xcb, 0x05, 0xb6, 0x3e,
+       0x86, 0xf5, 0x10, 0x5f, 0xd7, 0xfe, 0xd3, 0x2a, 0x79, 0x3d, 0xf4, 0xb3,
+       0xb0, 0x7f, 0xf8, 0x50, 0x3e, 0xdb, 0x58, 0x97, 0x30, 0xfe, 0x77, 0xbb,
+       0xf1, 0xb7, 0x1d, 0xe3, 0x6f, 0x6b, 0x3a, 0x12, 0x4e, 0x2e, 0xf4, 0x0b,
+       0x78, 0x66, 0xe9, 0x83, 0x6a, 0x3b, 0xfd, 0x82, 0x0e, 0x59, 0xdb, 0x2f,
+       0x08, 0x69, 0x3a, 0x85, 0x7d, 0xd2, 0xcf, 0xd3, 0x79, 0xa0, 0xce, 0x20,
+       0xf7, 0x44, 0x1a, 0x42, 0xfb, 0xa8, 0xed, 0xf0, 0x21, 0x98, 0x3c, 0xe6,
+       0x24, 0x41, 0xeb, 0x6e, 0x29, 0x4c, 0x9f, 0x32, 0xf6, 0x96, 0x71, 0x04,
+       0x7d, 0xf8, 0x40, 0x66, 0x0b, 0xd9, 0x0e, 0xcb, 0xcc, 0xd3, 0x05, 0x0b,
+       0x19, 0xc9, 0x51, 0x71, 0x2d, 0xfa, 0x31, 0xa1, 0x4f, 0xb3, 0x60, 0x7c,
+       0x9a, 0x33, 0xb2, 0xcf, 0x0b, 0xe2, 0x86, 0x91, 0xda, 0x12, 0xea, 0x34,
+       0xed, 0x29, 0xfa, 0x96, 0x0a, 0x3e, 0x77, 0xfe, 0xde, 0x0c, 0x02, 0x90,
+       0x60, 0x2f, 0x5b, 0xb1, 0x97, 0x6a, 0x63, 0x2f, 0x6d, 0x4b, 0xcd, 0x3e,
+       0x0e, 0xc7, 0x4e, 0xae, 0x1a, 0x2b, 0xd8, 0xc7, 0xdc, 0x79, 0xda, 0xb8,
+       0x47, 0xfa, 0x0d, 0x8e, 0xd9, 0x63, 0x78, 0x4e, 0x8f, 0x63, 0x8f, 0x49,
+       0xab, 0xa4, 0x7d, 0x2d, 0xfa, 0x2d, 0x88, 0xb3, 0x6b, 0x2f, 0xe1, 0x49,
+       0xfd, 0xd0, 0xf3, 0x60, 0x4f, 0xed, 0x7a, 0x4f, 0x53, 0xde, 0x2b, 0x7a,
+       0x1f, 0xf3, 0xb5, 0xbf, 0x91, 0xf2, 0xb1, 0x1f, 0xc0, 0xee, 0x45, 0x73,
+       0x73, 0xcc, 0x6b, 0x92, 0x1f, 0x95, 0x08, 0x7e, 0x72, 0xaf, 0xcc, 0xbb,
+       0xbd, 0x1c, 0x0f, 0xe2, 0x83, 0x69, 0x9c, 0xb1, 0x15, 0xb4, 0xeb, 0xf5,
+       0x43, 0xbe, 0xb6, 0x44, 0xe8, 0xa9, 0xc3, 0xe7, 0x4c, 0x81, 0x86, 0xe8,
+       0x98, 0x03, 0x32, 0xec, 0xf1, 0x3c, 0x7a, 0x53, 0x7b, 0xc5, 0x75, 0x4a,
+       0x12, 0xfa, 0x19, 0x5c, 0x9f, 0x3a, 0x5f, 0x84, 0xe3, 0xcb, 0x5c, 0x6a,
+       0xc8, 0xbb, 0x90, 0x6f, 0xed, 0x4b, 0xcd, 0x32, 0x30, 0x89, 0x58, 0xab,
+       0xec, 0x91, 0x4f, 0xa1, 0x6c, 0x86, 0x6b, 0xbf, 0x6a, 0x71, 0x3f, 0x13,
+       0x3a, 0x7f, 0xf8, 0x4f, 0x0d, 0x19, 0x1d, 0x07, 0x76, 0x04, 0x32, 0xf7,
+       0xf7, 0x86, 0x37, 0xa1, 0x6c, 0xb6, 0x9b, 0x73, 0x66, 0x2c, 0x48, 0xdd,
+       0x09, 0xe5, 0x60, 0x9b, 0x73, 0xa7, 0xe6, 0x05, 0xdb, 0xb4, 0xcf, 0xad,
+       0xcf, 0x72, 0xac, 0x71, 0x96, 0x1b, 0x9a, 0xe4, 0xf2, 0xdd, 0x8d, 0x81,
+       0x1e, 0x52, 0xdf, 0xa0, 0xb7, 0xe0, 0xd7, 0xb3, 0x2b, 0xf4, 0xbb, 0xff,
+       0x3c, 0x39, 0xd9, 0x76, 0x89, 0xcd, 0x7e, 0x0f, 0xbc, 0xbc, 0x06, 0xb1,
+       0x8a, 0x88, 0x3d, 0x43, 0x1c, 0xa2, 0xbf, 0xb1, 0xec, 0xef, 0xce, 0xcb,
+       0x5a, 0xbe, 0xee, 0xc5, 0x7c, 0x8d, 0x4f, 0x5e, 0xa2, 0xaf, 0x31, 0xdc,
+       0x22, 0xad, 0xc4, 0xa2, 0x33, 0xf0, 0x6d, 0x2d, 0x69, 0x71, 0xbf, 0x01,
+       0x1b, 0x76, 0xda, 0x5e, 0xe7, 0x86, 0x98, 0xd0, 0x2e, 0x9b, 0x66, 0xb7,
+       0x68, 0x5c, 0x70, 0x66, 0x96, 0x71, 0x61, 0x1c, 0xbc, 0x1f, 0x09, 0xf2,
+       0xbc, 0xc9, 0x4d, 0x72, 0xa9, 0xf1, 0xf5, 0xb2, 0xdf, 0x3f, 0xd6, 0xf0,
+       0xfb, 0xaf, 0x6c, 0xe2, 0xe3, 0x5a, 0xb8, 0x78, 0x1a, 0x7c, 0xcb, 0x21,
+       0xfe, 0x65, 0x5c, 0x3b, 0x8c, 0x78, 0x98, 0xb1, 0x58, 0x1e, 0x31, 0x71,
+       0xe6, 0xb4, 0xc8, 0x6e, 0xc4, 0xc8, 0x99, 0x1f, 0x31, 0x7f, 0xf5, 0xbc,
+       0x9f, 0x99, 0x13, 0xb9, 0x1d, 0x7c, 0x1d, 0x04, 0x6e, 0x66, 0x81, 0xa3,
+       0x3b, 0xc1, 0xdf, 0x7e, 0x8d, 0x9d, 0xf7, 0x1f, 0x11, 0xeb, 0x0e, 0x9d,
+       0xab, 0xa6, 0x3e, 0x27, 0x61, 0x47, 0xeb, 0xf5, 0xfd, 0xd9, 0x5e, 0xc4,
+       0xf5, 0x69, 0xb9, 0xd5, 0x66, 0x1c, 0x6b, 0xd9, 0x5b, 0x07, 0xe6, 0x63,
+       0x51, 0x9f, 0xb4, 0x70, 0x51, 0x3b, 0xb0, 0x9a, 0xf7, 0x45, 0x6d, 0x0b,
+       0x0e, 0xc7, 0x2e, 0xc4, 0xfb, 0x3b, 0x1a, 0xbc, 0x6f, 0x69, 0x95, 0xd6,
+       0xdb, 0x75, 0x1e, 0x61, 0xeb, 0xc0, 0x7e, 0xe2, 0x55, 0x16, 0x76, 0x1d,
+       0xf6, 0xb7, 0x2e, 0xb7, 0x65, 0xdf, 0xae, 0xbf, 0xe8, 0x6e, 0x94, 0xd2,
+       0xce, 0xfb, 0x0c, 0x66, 0x2f, 0x7d, 0xad, 0xe0, 0x56, 0xa0, 0x1f, 0x41,
+       0xce, 0x70, 0xef, 0x74, 0x02, 0x96, 0x80, 0x7f, 0x9d, 0x32, 0x3f, 0xf4,
+       0x16, 0xce, 0x70, 0xc7, 0x49, 0x26, 0x9c, 0x14, 0x70, 0x78, 0x3e, 0xd9,
+       0xae, 0xf3, 0xc5, 0x9f, 0x70, 0x59, 0xef, 0xe0, 0x4c, 0x47, 0x65, 0x1e,
+       0xfe, 0x43, 0x75, 0x08, 0x34, 0xee, 0xec, 0x42, 0x7f, 0xea, 0x1d, 0x79,
+       0x3e, 0x0a, 0xdb, 0x4b, 0x9e, 0x26, 0xd1, 0x7f, 0x0f, 0xfa, 0x74, 0xe2,
+       0x79, 0x5f, 0x6c, 0xde, 0x61, 0xec, 0xfc, 0x79, 0x94, 0x39, 0x47, 0xd4,
+       0x76, 0x7e, 0x2e, 0x2e, 0x7a, 0x4e, 0x8e, 0xe9, 0xd2, 0xfa, 0xbf, 0xbc,
+       0x16, 0xd7, 0x61, 0xdb, 0xcf, 0xea, 0xd7, 0x0f, 0x0c, 0x45, 0xd6, 0xeb,
+       0x88, 0xac, 0x37, 0x14, 0x59, 0x8f, 0x74, 0x76, 0x46, 0xe8, 0xec, 0xc4,
+       0xf8, 0x22, 0xd6, 0x26, 0x3f, 0xa2, 0x6b, 0x3e, 0x18, 0x59, 0x33, 0xdc,
+       0x5f, 0x57, 0x64, 0xdc, 0xbb, 0x58, 0x8f, 0x75, 0xc9, 0x48, 0x1d, 0x69,
+       0xd8, 0x8c, 0x3a, 0x96, 0x3b, 0x23, 0x74, 0x91, 0xd6, 0x0d, 0xa8, 0xd7,
+       0xfe, 0x13, 0xf8, 0xdc, 0x0a, 0xbb, 0xa5, 0x60, 0x3b, 0x5a, 0xe0, 0x5f,
+       0x35, 0xef, 0xf5, 0x51, 0xac, 0x1b, 0xce, 0x97, 0xc4, 0x1c, 0xec, 0xcf,
+       0xbe, 0x31, 0x33, 0x9e, 0xf5, 0x6c, 0xff, 0xf3, 0xfa, 0x9f, 0x6a, 0xbe,
+       0x6d, 0x06, 0xed, 0x3a, 0xef, 0x22, 0x73, 0x9d, 0x36, 0xce, 0x93, 0xf1,
+       0xb1, 0x25, 0x57, 0xbb, 0xca, 0xea, 0x1d, 0xe0, 0xd9, 0x6f, 0x34, 0x58,
+       0xda, 0x6a, 0x15, 0x8e, 0x30, 0x5f, 0xd0, 0x66, 0x62, 0x3e, 0xc4, 0x1e,
+       0xda, 0xc6, 0xd8, 0xa6, 0x9d, 0x36, 0x86, 0x7e, 0x0b, 0xed, 0xe7, 0x69,
+       0xf3, 0x8e, 0x27, 0x64, 0xf8, 0x81, 0x6a, 0xa7, 0xbc, 0xa8, 0x79, 0xea,
+       0xc8, 0xd9, 0x06, 0x4f, 0xe3, 0xe6, 0xbb, 0xcc, 0x01, 0xf3, 0xcd, 0xa3,
+       0x0f, 0x7e, 0x11, 0xde, 0x6b, 0x79, 0xd0, 0x90, 0x96, 0xde, 0x01, 0xc6,
+       0x6e, 0x15, 0x3c, 0x99, 0xa7, 0xb0, 0xf0, 0x0c, 0xf2, 0x17, 0xbd, 0x03,
+       0xb0, 0x4b, 0xc0, 0xa1, 0xde, 0x81, 0x73, 0x3a, 0x9e, 0xab, 0xfa, 0x8e,
+       0x75, 0x9b, 0x17, 0xe4, 0x88, 0xce, 0xba, 0x17, 0xca, 0x11, 0xdd, 0xb3,
+       0x8e, 0x79, 0x8d, 0x30, 0x47, 0x74, 0x56, 0x74, 0x8e, 0xe8, 0xf8, 0x45,
+       0x72, 0x44, 0xf9, 0x4b, 0xcf, 0x11, 0x71, 0x7e, 0x5b, 0xee, 0x1c, 0x74,
+       0xd4, 0xaf, 0x9a, 0x1c, 0xd1, 0x1b, 0x12, 0xe4, 0x88, 0x5e, 0x94, 0xb5,
+       0x73, 0x44, 0x87, 0x9a, 0x72, 0x44, 0x9b, 0x75, 0x8e, 0x88, 0xf3, 0x04,
+       0x39, 0x22, 0x96, 0x4b, 0x03, 0x43, 0x91, 0x5c, 0x07, 0xf0, 0xd7, 0xbb,
+       0x01, 0x7c, 0x73, 0xac, 0x51, 0x2f, 0xc4, 0x34, 0x62, 0xff, 0x15, 0x0d,
+       0xfb, 0xb5, 0x8c, 0x6f, 0x96, 0x96, 0xb9, 0x8b, 0xe1, 0xdb, 0x68, 0xe0,
+       0x97, 0xac, 0xc0, 0xb6, 0xc9, 0x86, 0xef, 0xe2, 0xad, 0x63, 0x0c, 0x3d,
+       0x51, 0x5b, 0x9e, 0x77, 0x02, 0xbc, 0x1e, 0x6b, 0xe4, 0x49, 0xce, 0xe7,
+       0x1f, 0x25, 0xe5, 0xc0, 0x9a, 0xdf, 0xbd, 0x52, 0xf9, 0xd5, 0xdf, 0xbd,
+       0x2c, 0x49, 0x82, 0xce, 0xd2, 0x40, 0x49, 0xc7, 0x5d, 0xf3, 0xde, 0xaf,
+       0xc8, 0xd2, 0xdd, 0x0e, 0xf0, 0x27, 0xcc, 0x9f, 0xf0, 0x7c, 0x97, 0x6d,
+       0x4a, 0x41, 0x7d, 0x7c, 0x39, 0x94, 0x07, 0x74, 0x0e, 0xe5, 0xc5, 0x75,
+       0xd1, 0x1c, 0xca, 0x59, 0xb9, 0x70, 0x0e, 0xe5, 0x81, 0x35, 0x72, 0x28,
+       0x2f, 0xcb, 0x72, 0x0e, 0xe5, 0x65, 0x09, 0x73, 0x28, 0x31, 0x59, 0xda,
+       0x1c, 0x48, 0xe3, 0x03, 0xfe, 0x12, 0x7e, 0x67, 0xf0, 0x0b, 0x72, 0x2a,
+       0x67, 0x1b, 0xf4, 0xaf, 0x95, 0x53, 0x79, 0x7d, 0xdd, 0x07, 0xc9, 0xa9,
+       0x04, 0x36, 0x20, 0xcc, 0xa9, 0xe0, 0xe7, 0xc0, 0xe6, 0xa8, 0x68, 0x4e,
+       0xe5, 0x27, 0xd4, 0x07, 0xd4, 0xb1, 0xcc, 0x7a, 0xe8, 0x05, 0xec, 0x52,
+       0x5e, 0xe7, 0x38, 0x3e, 0x67, 0x78, 0x38, 0x87, 0x3d, 0xa7, 0x71, 0x16,
+       0xe4, 0x63, 0xaf, 0xf6, 0x2d, 0xf3, 0x76, 0xca, 0x2a, 0xf4, 0xc1, 0x9a,
+       0x4d, 0xf3, 0xbb, 0xb8, 0x6d, 0xed, 0xf5, 0x29, 0xe3, 0x09, 0xab, 0x8c,
+       0xbd, 0x0c, 0x4f, 0xcf, 0xc9, 0x5e, 0x3f, 0xf4, 0xa9, 0x06, 0x1a, 0x73,
+       0x50, 0x37, 0xe7, 0x81, 0xb3, 0xc0, 0x89, 0x4b, 0xb0, 0x51, 0xa7, 0x40,
+       0x73, 0x74, 0x1f, 0x88, 0x89, 0x07, 0x51, 0xa7, 0xcf, 0x9c, 0xbe, 0x65,
+       0x48, 0x4b, 0x9a, 0x7a, 0x7e, 0x09, 0xf3, 0xb1, 0xee, 0x94, 0x8e, 0xc7,
+       0xca, 0x83, 0xdc, 0x2b, 0x6d, 0xdd, 0x22, 0xe8, 0x43, 0x5d, 0x95, 0x31,
+       0x20, 0xed, 0x5e, 0x18, 0xa3, 0xb5, 0xeb, 0x18, 0xad, 0x4b, 0xf3, 0x83,
+       0xbc, 0xbe, 0x35, 0x41, 0xac, 0xec, 0x72, 0xb9, 0x87, 0x33, 0x06, 0xeb,
+       0x58, 0x0e, 0x62, 0xc1, 0xbc, 0xe2, 0xfb, 0xef, 0xe1, 0x5c, 0x99, 0xa7,
+       0x09, 0xcf, 0xef, 0x2b, 0x66, 0xdf, 0x43, 0x52, 0xe9, 0x92, 0xc4, 0x66,
+       0xd0, 0x53, 0x9a, 0xa1, 0xdf, 0xfd, 0x69, 0x1d, 0x83, 0x24, 0xdd, 0xf3,
+       0xeb, 0xed, 0x1d, 0x97, 0xa1, 0xb7, 0x23, 0x17, 0xd4, 0xdb, 0xaf, 0x25,
+       0xa2, 0x7a, 0x7b, 0xc7, 0x65, 0xe8, 0xed, 0xbe, 0xcb, 0xd2, 0x5b, 0xee,
+       0x8d, 0x98, 0x14, 0xe6, 0xc4, 0x56, 0xfb, 0x59, 0xe1, 0xba, 0xe3, 0x58,
+       0x33, 0x7f, 0x9e, 0x35, 0xc7, 0xce, 0x9b, 0x5b, 0x6d, 0xf6, 0xb1, 0x2e,
+       0xe5, 0xbc, 0x19, 0x5b, 0xd1, 0xde, 0xb6, 0x1b, 0xbb, 0x74, 0x9f, 0x89,
+       0xe7, 0xc3, 0xb8, 0x3e, 0xaa, 0x3f, 0x94, 0x0b, 0xca, 0xc2, 0x77, 0xc0,
+       0x2f, 0xca, 0x43, 0xa8, 0x73, 0xdd, 0x4d, 0x32, 0xb8, 0x88, 0x78, 0xbf,
+       0xdb, 0xc8, 0x20, 0xcf, 0xba, 0x4f, 0x7f, 0x67, 0xaa, 0x7a, 0x4f, 0x05,
+       0x71, 0xbe, 0x8b, 0x67, 0x35, 0xd4, 0x35, 0xf0, 0x24, 0x19, 0xb6, 0x91,
+       0x8f, 0x2e, 0x7c, 0x9e, 0x1d, 0xf0, 0xd7, 0xc0, 0x23, 0x5d, 0xbf, 0x32,
+       0x27, 0x7c, 0x61, 0x3c, 0x93, 0x4a, 0x1c, 0x7d, 0x4f, 0x0c, 0x42, 0xc7,
+       0x07, 0x89, 0x51, 0x35, 0xc4, 0x3d, 0x94, 0x43, 0xca, 0xe6, 0xb6, 0xfe,
+       0x5d, 0x8a, 0x3e, 0xd5, 0x13, 0x88, 0x83, 0x29, 0xaf, 0x69, 0xd9, 0xe5,
+       0x6f, 0x3b, 0x7d, 0x56, 0x71, 0x8d, 0x7a, 0xbd, 0xc4, 0x58, 0xd1, 0x11,
+       0xb5, 0x75, 0xe0, 0xbf, 0x13, 0xb4, 0x4b, 0x57, 0xb8, 0x31, 0x23, 0x6b,
+       0x79, 0xbc, 0x53, 0x6e, 0x7f, 0x08, 0x7b, 0xcf, 0xef, 0xfd, 0xaf, 0xa1,
+       0x3e, 0x05, 0x9d, 0xa7, 0x7d, 0x67, 0x3c, 0x72, 0x93, 0xe9, 0xd7, 0xad,
+       0xbf, 0x57, 0x16, 0xb2, 0x37, 0x98, 0x6f, 0x57, 0xb4, 0x3f, 0x19, 0xda,
+       0xec, 0x15, 0xe7, 0xcc, 0xfb, 0x12, 0x45, 0x1d, 0xcf, 0x70, 0xbc, 0x96,
+       0x49, 0xc4, 0x20, 0x76, 0x24, 0x97, 0x9e, 0x30, 0xb1, 0x1b, 0x75, 0xac,
+       0x1d, 0x67, 0xe8, 0x9b, 0x58, 0x85, 0xf1, 0xeb, 0xca, 0x7b, 0x12, 0x6b,
+       0xcb, 0xc0, 0x96, 0x0f, 0x20, 0x03, 0xcd, 0xe7, 0x97, 0x80, 0xee, 0x87,
+       0xe7, 0x17, 0xfa, 0x31, 0x73, 0x66, 0xdf, 0xdd, 0xc1, 0x19, 0xfe, 0xbf,
+       0xd8, 0xa7, 0x15, 0xd9, 0x67, 0x88, 0x47, 0x0f, 0x98, 0x7d, 0xde, 0xd4,
+       0x84, 0x47, 0x23, 0x4d, 0x3a, 0xfb, 0x71, 0xe2, 0xd1, 0x9f, 0xac, 0xff,
+       0xf8, 0xf1, 0x88, 0xfb, 0xea, 0x5e, 0x13, 0x87, 0x82, 0x7d, 0x3c, 0x22,
+       0x2a, 0xf7, 0x51, 0xc6, 0x7b, 0x1f, 0xe4, 0x7c, 0xa2, 0x38, 0xc2, 0x33,
+       0xe9, 0xd0, 0x3e, 0x6c, 0xa0, 0x7b, 0xb0, 0xe5, 0xd5, 0xb8, 0xbc, 0x7e,
+       0x57, 0x42, 0xfe, 0xf7, 0x46, 0x7e, 0x0f, 0xb3, 0x4d, 0x4e, 0x8b, 0xe5,
+       0xd7, 0xd6, 0x07, 0x76, 0xe8, 0xb5, 0x4d, 0x81, 0xdd, 0xe1, 0x98, 0x50,
+       0x9f, 0x1d, 0xb4, 0xb3, 0xad, 0x5b, 0x96, 0x3a, 0x2f, 0x27, 0x06, 0xdc,
+       0xe6, 0xbc, 0xa1, 0xd6, 0x8a, 0x01, 0x2f, 0x9c, 0x0f, 0x5c, 0x8e, 0x01,
+       0x89, 0xb3, 0x9d, 0x5a, 0x36, 0x4a, 0x49, 0xc6, 0x3e, 0x7d, 0x06, 0x3b,
+       0xf9, 0x8e, 0xd8, 0xd6, 0x43, 0xbc, 0xeb, 0x21, 0xd6, 0xf5, 0x10, 0xff,
+       0x7a, 0x88, 0x71, 0x3d, 0xc4, 0xb6, 0x1e, 0x62, 0x5b, 0x0f, 0xb1, 0xad,
+       0xd7, 0x6f, 0x62, 0xe4, 0x11, 0x93, 0xf7, 0xe7, 0x77, 0x72, 0xe6, 0x17,
+       0x2a, 0xb0, 0x25, 0x93, 0xbc, 0xe7, 0xa0, 0x0a, 0xd9, 0xf5, 0x66, 0x7f,
+       0x61, 0x4e, 0xbc, 0xc7, 0xe4, 0x6c, 0x5e, 0xd7, 0x79, 0x43, 0x51, 0xb3,
+       0xad, 0xc1, 0xb7, 0x74, 0xde, 0xc7, 0xf8, 0x2d, 0xf8, 0x25, 0xfa, 0x3e,
+       0x13, 0x75, 0xb4, 0xae, 0x72, 0xcc, 0xc9, 0x88, 0x52, 0xb9, 0xeb, 0x31,
+       0x66, 0x47, 0x10, 0x13, 0x24, 0x25, 0xa6, 0x72, 0x6d, 0xe4, 0xa9, 0xa5,
+       0x72, 0x1b, 0xcc, 0x5c, 0x47, 0x5b, 0x03, 0xdf, 0xaa, 0x8f, 0x65, 0x5b,
+       0xe5, 0x6e, 0xe6, 0x13, 0xe7, 0x1e, 0xd6, 0xf7, 0x74, 0xae, 0x5c, 0x6b,
+       0x4a, 0xe3, 0x7b, 0x21, 0x7b, 0x37, 0xe6, 0xd3, 0xf7, 0x88, 0x1a, 0xfc,
+       0x56, 0xe7, 0xe5, 0xf7, 0x94, 0xe1, 0x77, 0xc0, 0xe3, 0x18, 0xfb, 0xe9,
+       0xbc, 0x30, 0x79, 0x1d, 0xce, 0xa7, 0xf3, 0x7a, 0x58, 0x47, 0xdf, 0xa5,
+       0xc0, 0x53, 0xc5, 0xa5, 0x63, 0xf4, 0x9e, 0xb8, 0x1b, 0x5d, 0x37, 0xfc,
+       0x26, 0x7e, 0x29, 0x6b, 0x76, 0xeb, 0xef, 0x68, 0x81, 0xcd, 0x98, 0xd2,
+       0x32, 0x68, 0xe7, 0xb8, 0xaf, 0xf7, 0x21, 0x7f, 0x53, 0x5a, 0xfe, 0x8a,
+       0x88, 0x63, 0x26, 0x07, 0xb7, 0xa5, 0x6d, 0x75, 0xa0, 0x95, 0xf9, 0xd7,
+       0x61, 0x3f, 0xc4, 0x3d, 0xae, 0xd7, 0x6c, 0xc7, 0x99, 0x57, 0x0b, 0xf1,
+       0x4c, 0xb6, 0x04, 0xf9, 0xb6, 0x0f, 0xa3, 0x4b, 0xad, 0x4d, 0xba, 0x14,
+       0xee, 0x93, 0xfb, 0xe7, 0x73, 0xed, 0x3b, 0x15, 0x8b, 0x7e, 0xe4, 0xfb,
+       0x48, 0x43, 0x36, 0x78, 0xb7, 0xe4, 0x8b, 0x90, 0x41, 0xfd, 0x9d, 0x02,
+       0x7a, 0x54, 0xaf, 0x0f, 0x33, 0xc7, 0xbc, 0xf3, 0x0b, 0xe6, 0xde, 0x82,
+       0x3c, 0xcc, 0xfc, 0x83, 0xbd, 0x2a, 0xff, 0x30, 0x0c, 0x59, 0x81, 0x0f,
+       0xe0, 0x75, 0x68, 0x9f, 0x4e, 0xb9, 0xf4, 0x07, 0x9a, 0xbf, 0xbf, 0x3c,
+       0xda, 0x16, 0xf0, 0xe1, 0xed, 0xd6, 0xe0, 0x1b, 0xc4, 0xdf, 0x26, 0x57,
+       0x96, 0x39, 0xfe, 0x7f, 0x8c, 0xac, 0x1c, 0x86, 0x6d, 0x1e, 0x86, 0x2c,
+       0x22, 0x26, 0xd7, 0xf3, 0x1d, 0x96, 0xd2, 0xd3, 0x0b, 0x9d, 0x2b, 0xfb,
+       0xa3, 0xee, 0x58, 0xd8, 0xff, 0xb1, 0xa6, 0xfe, 0x8f, 0xa1, 0xff, 0x0b,
+       0x4d, 0xfd, 0x1f, 0x8b, 0xf4, 0x3f, 0xda, 0xd4, 0x1f, 0x31, 0xe2, 0xd3,
+       0xff, 0xdc, 0xd4, 0xff, 0x68, 0xa4, 0xff, 0x6c, 0x53, 0xff, 0x59, 0xf4,
+       0x7f, 0xad, 0xa9, 0x3f, 0xea, 0x8e, 0xb5, 0x98, 0xef, 0x62, 0xc4, 0xd8,
+       0x7d, 0x26, 0x16, 0xc7, 0xb3, 0xd6, 0xfc, 0xad, 0x85, 0x72, 0xd7, 0x83,
+       0x33, 0x08, 0xef, 0xb4, 0x51, 0x5f, 0xf3, 0xd0, 0xd7, 0x65, 0x5f, 0x26,
+       0x90, 0xc7, 0xa8, 0x2c, 0x12, 0x1f, 0x2a, 0x12, 0x73, 0x7d, 0xfa, 0x47,
+       0x56, 0xb9, 0x1a, 0xda, 0x24, 0xde, 0x5b, 0xe2, 0x7d, 0xd7, 0xc0, 0xf6,
+       0xc6, 0xdd, 0x45, 0x13, 0x83, 0x5d, 0xd1, 0x06, 0xda, 0x81, 0x97, 0x21,
+       0x66, 0xca, 0xe1, 0x40, 0x6f, 0x28, 0xbf, 0x9c, 0xdf, 0xe8, 0x0f, 0x65,
+       0xd5, 0xac, 0x33, 0xbc, 0x0a, 0xd7, 0xd2, 0xab, 0x72, 0x5b, 0xb1, 0x4b,
+       0xc0, 0xb5, 0x91, 0x06, 0xae, 0x7d, 0x51, 0xe6, 0x1a, 0xf1, 0xf6, 0x19,
+       0xd9, 0xef, 0xed, 0xe1, 0x3d, 0x9d, 0xc3, 0x79, 0xf9, 0x68, 0xe2, 0xed,
+       0x3d, 0x0d, 0x3b, 0xc9, 0x3b, 0x1d, 0xe9, 0x83, 0xbc, 0x83, 0x1b, 0xe6,
+       0x66, 0x27, 0xbd, 0x5f, 0xc7, 0xfe, 0x69, 0x33, 0x2f, 0x37, 0xde, 0xe6,
+       0x7c, 0x49, 0xd9, 0x1f, 0xdc, 0x77, 0x68, 0xcc, 0x5b, 0x69, 0xcc, 0x9b,
+       0x32, 0xfa, 0x46, 0x1b, 0xbc, 0x6c, 0x2f, 0x8b, 0xb0, 0x97, 0x63, 0x88,
+       0xb9, 0x17, 0xbd, 0xb5, 0xf2, 0xa3, 0x97, 0x6b, 0x2f, 0x9b, 0xf3, 0xcc,
+       0xcd, 0xf6, 0x92, 0xeb, 0x34, 0xe7, 0x96, 0xd3, 0x4d, 0xf8, 0x4f, 0x79,
+       0x3a, 0x67, 0x7c, 0x6a, 0x3c, 0xab, 0xe7, 0xa0, 0x8f, 0x4a, 0xc6, 0xb4,
+       0xfc, 0xb2, 0x1c, 0xc6, 0x96, 0xf7, 0x34, 0x62, 0xcb, 0xe5, 0x78, 0x10,
+       0xbe, 0x6b, 0xff, 0x67, 0x0c, 0x3e, 0xd2, 0x47, 0x76, 0xac, 0xb2, 0xb7,
+       0x5b, 0xed, 0xd5, 0x6d, 0xcc, 0x97, 0x5e, 0x2b, 0xb7, 0xea, 0x38, 0xfe,
+       0x8c, 0xc9, 0x4d, 0xcd, 0x69, 0xff, 0x9f, 0xdf, 0x0b, 0xca, 0xd9, 0x4d,
+       0xc6, 0xdf, 0xbb, 0x18, 0xae, 0xae, 0x8c, 0x4d, 0x95, 0x3a, 0x88, 0xb1,
+       0x8c, 0x4d, 0xfb, 0xdb, 0x89, 0xa1, 0x05, 0xff, 0x82, 0xe3, 0x31, 0x8e,
+       0xe3, 0xd9, 0x47, 0xc7, 0xa1, 0xe8, 0xb7, 0x68, 0xc6, 0x07, 0x71, 0x68,
+       0xc1, 0xff, 0x71, 0x5b, 0x80, 0x83, 0x17, 0x8a, 0x59, 0x3e, 0xdf, 0xce,
+       0xbc, 0xde, 0xa2, 0x77, 0x31, 0x5a, 0x57, 0xc7, 0xbd, 0xb1, 0x55, 0x71,
+       0xaf, 0x6d, 0xe2, 0xda, 0x5f, 0xd2, 0x71, 0x6f, 0xc0, 0x63, 0xee, 0x25,
+       0x1a, 0x47, 0xb9, 0xc0, 0x42, 0x7e, 0x53, 0x21, 0x3e, 0xd0, 0x47, 0x81,
+       0x9f, 0x35, 0xfd, 0x8b, 0xe0, 0x73, 0x72, 0x0d, 0xb9, 0xf9, 0xb8, 0xed,
+       0x44, 0xb8, 0xf7, 0x73, 0x12, 0xe4, 0xeb, 0x76, 0x83, 0x16, 0xc6, 0x56,
+       0x71, 0x23, 0x0f, 0x3f, 0x35, 0xf7, 0x2a, 0xc3, 0x7e, 0x61, 0x1c, 0xdf,
+       0xf8, 0xee, 0x5a, 0xc9, 0xaf, 0xc8, 0x9f, 0x74, 0x33, 0x0d, 0x8d, 0x73,
+       0xcf, 0x5f, 0xc6, 0x77, 0x8b, 0x0f, 0x73, 0x3f, 0xa2, 0xd9, 0xae, 0xf1,
+       0xbb, 0x29, 0xbf, 0x95, 0x8a, 0x75, 0x67, 0x9f, 0x0b, 0x1d, 0xe0, 0xbd,
+       0xe1, 0x28, 0xbe, 0x26, 0xa4, 0x34, 0x2b, 0x89, 0x64, 0x8e, 0xdf, 0x00,
+       0x68, 0xff, 0x7f, 0x68, 0xf6, 0x99, 0x92, 0x7d, 0x33, 0x41, 0xce, 0x53,
+       0x5d, 0xf0, 0x5e, 0xdc, 0xe3, 0xe0, 0x43, 0xe6, 0x50, 0x98, 0xf3, 0x54,
+       0xc1, 0xbd, 0xb8, 0x43, 0x1f, 0xdd, 0xbd, 0x38, 0xce, 0x6f, 0xcb, 0x9e,
+       0x35, 0xee, 0xc5, 0xc5, 0x2e, 0xf1, 0x5e, 0xdc, 0x26, 0x9d, 0xf3, 0xe4,
+       0x3c, 0x41, 0xce, 0x93, 0xe5, 0xad, 0x03, 0xcc, 0x95, 0xf0, 0xee, 0xdb,
+       0xa0, 0xbe, 0x2f, 0xbc, 0x75, 0xe0, 0xe7, 0x11, 0xa3, 0xfc, 0x75, 0xfb,
+       0xc7, 0x1f, 0xa3, 0x70, 0x2f, 0xbf, 0x11, 0x7c, 0xdf, 0x95, 0xcb, 0xc9,
+       0x03, 0x7c, 0xb8, 0xbc, 0xe6, 0x3e, 0x9d, 0xd7, 0x7c, 0xa7, 0x3d, 0x9a,
+       0xd7, 0x54, 0x17, 0xb9, 0x1b, 0xb6, 0x6f, 0x8d, 0xbc, 0x66, 0x3c, 0x72,
+       0x37, 0x2c, 0x6e, 0xee, 0x86, 0x6d, 0x72, 0x11, 0x4b, 0x9a, 0x3c, 0xa6,
+       0xba, 0xe0, 0xdd, 0xb0, 0xce, 0x0d, 0x1f, 0x3e, 0x8f, 0xb9, 0xea, 0x6e,
+       0x18, 0x6c, 0xdd, 0x16, 0x49, 0x5f, 0x56, 0xdc, 0xf3, 0x61, 0x62, 0x1e,
+       0xde, 0xab, 0x6f, 0xc1, 0x9e, 0xe3, 0xb2, 0x27, 0x49, 0xf9, 0xe4, 0xdd,
+       0xc6, 0x3e, 0xe8, 0x02, 0x9e, 0x3e, 0xcb, 0xfd, 0x3c, 0x23, 0x6b, 0xa4,
+       0x6f, 0xe5, 0x3d, 0x84, 0xe5, 0x3b, 0xbd, 0x89, 0xc6, 0x9d, 0xde, 0x29,
+       0xc8, 0x8d, 0x9a, 0x49, 0xc8, 0x7c, 0x44, 0xa6, 0x26, 0x3d, 0xf8, 0x4b,
+       0xb3, 0x8e, 0x69, 0xe7, 0xff, 0xef, 0x48, 0x02, 0xf3, 0x78, 0x0f, 0xb8,
+       0x43, 0x62, 0xb3, 0xc1, 0x37, 0xcb, 0xe0, 0xff, 0xb8, 0xa4, 0xd0, 0x87,
+       0x77, 0x3c, 0xe3, 0xb2, 0x5f, 0xe7, 0x2c, 0x42, 0x59, 0xfe, 0x35, 0xf0,
+       0x78, 0x73, 0x7e, 0xb9, 0x9c, 0x5c, 0xc3, 0xee, 0x27, 0xa5, 0x3c, 0x43,
+       0x79, 0xbe, 0xc1, 0xfc, 0xff, 0x82, 0xd3, 0x52, 0xf6, 0x4f, 0x99, 0xf8,
+       0x42, 0x7f, 0xdb, 0x01, 0x2f, 0xb7, 0x18, 0x1b, 0x8c, 0x67, 0x75, 0x0b,
+       0x6d, 0x1e, 0xd6, 0x38, 0x2e, 0xc3, 0xd3, 0x3b, 0x52, 0x7b, 0x81, 0x77,
+       0x63, 0x7a, 0xcd, 0xcb, 0xe1, 0xb9, 0x75, 0x9e, 0xef, 0x8d, 0x97, 0xca,
+       0xf7, 0xd0, 0x3f, 0xae, 0x62, 0x7f, 0x5b, 0x20, 0x1f, 0x5f, 0x95, 0xe2,
+       0xb1, 0x6b, 0x65, 0xf8, 0x68, 0x06, 0xf4, 0xbc, 0x5f, 0x2f, 0x67, 0xe1,
+       0x4b, 0x3f, 0xcd, 0x7b, 0x63, 0xc0, 0x50, 0xf0, 0xed, 0xf9, 0x55, 0xdf,
+       0xb1, 0xa3, 0x77, 0xcd, 0xfa, 0x1b, 0x77, 0x87, 0x9e, 0xf5, 0x25, 0xd1,
+       0x49, 0x9a, 0x67, 0x96, 0xef, 0x8f, 0x2f, 0xfa, 0xbb, 0xb4, 0x6d, 0x7b,
+       0xc6, 0x5f, 0x91, 0xfb, 0xd1, 0x67, 0x38, 0x5e, 0xfb, 0x1e, 0xec, 0xdb,
+       0x39, 0x8b, 0xf6, 0x6d, 0xca, 0x93, 0xab, 0x63, 0xc2, 0xf3, 0x10, 0x0b,
+       0x3c, 0xd0, 0x77, 0x38, 0x82, 0xef, 0xfb, 0x3d, 0xfa, 0x5c, 0x03, 0xac,
+       0x58, 0x88, 0xdc, 0xc1, 0x58, 0x3e, 0xdb, 0xe0, 0x6e, 0x46, 0x70, 0x16,
+       0xc1, 0xfd, 0x11, 0xed, 0x6f, 0x1e, 0xdc, 0xe3, 0x06, 0xf7, 0x47, 0x7a,
+       0x67, 0x59, 0xd7, 0xd5, 0x64, 0xfb, 0x12, 0x90, 0x01, 0xde, 0x3b, 0xe2,
+       0xbd, 0x71, 0xd2, 0xac, 0x73, 0x1d, 0xff, 0x47, 0xdd, 0xd5, 0xc7, 0xb6,
+       0x75, 0x5d, 0xf7, 0xc3, 0x47, 0xea, 0xc3, 0xb4, 0x2c, 0x53, 0x32, 0x25,
+       0xd3, 0x96, 0x2c, 0xbf, 0x27, 0x3d, 0x59, 0x72, 0xac, 0x14, 0xac, 0xab,
+       0xad, 0x02, 0x46, 0xa4, 0x0c, 0x49, 0x7f, 0xb4, 0x08, 0x06, 0xfa, 0xa3,
+       0x99, 0x8b, 0x66, 0xab, 0x4b, 0xd9, 0x4e, 0x0a, 0xf4, 0x0f, 0xb7, 0xc5,
+       0x80, 0x6c, 0x58, 0x60, 0x86, 0xb4, 0x12, 0x63, 0x56, 0x4c, 0xd6, 0x66,
+       0x85, 0x0c, 0xd8, 0x30, 0x4e, 0x54, 0x9c, 0x14, 0x50, 0xc6, 0x04, 0x69,
+       0x83, 0xa2, 0x58, 0x61, 0x45, 0x76, 0x36, 0x6c, 0x7f, 0x65, 0x43, 0xd0,
+       0x05, 0x9b, 0xb3, 0x38, 0x76, 0xb0, 0x06, 0x45, 0xd6, 0x7d, 0x62, 0x18,
+       0xd0, 0x0d, 0xdc, 0xf9, 0xdd, 0x0f, 0xf2, 0xf1, 0xf1, 0x51, 0x1f, 0x89,
+       0x33, 0x60, 0x02, 0x04, 0xbe, 0xf7, 0x78, 0xdf, 0x7b, 0xf7, 0x9e, 0x7b,
+       0xce, 0xb9, 0xbf, 0x73, 0xee, 0x39, 0x87, 0x9e, 0x7b, 0xdb, 0x9b, 0xf3,
+       0xb9, 0xca, 0x77, 0x8e, 0x8a, 0x77, 0x0e, 0x28, 0x9d, 0xa5, 0xe3, 0xc5,
+       0x63, 0xc6, 0x6c, 0x61, 0x22, 0xe2, 0x67, 0xfe, 0x9e, 0xad, 0xc2, 0xbe,
+       0x6e, 0x87, 0xe1, 0xd6, 0xa2, 0x67, 0xbc, 0x85, 0x9e, 0xcd, 0x32, 0xc1,
+       0xf6, 0x78, 0x5d, 0x77, 0x4b, 0xda, 0xc9, 0xeb, 0x88, 0x85, 0xd7, 0x31,
+       0x0e, 0x92, 0x76, 0x75, 0x19, 0xba, 0xe2, 0x8c, 0x6f, 0x68, 0xd0, 0xee,
+       0x74, 0x9d, 0x76, 0x3b, 0xff, 0x1f, 0xd1, 0xee, 0x1d, 0x81, 0x7f, 0x5f,
+       0xad, 0x22, 0x6e, 0x4d, 0x63, 0x00, 0x9d, 0x3b, 0x04, 0x3a, 0x42, 0x9f,
+       0x5a, 0xe5, 0x15, 0x82, 0x4e, 0x45, 0x5c, 0x71, 0xad, 0xf6, 0x5a, 0xb4,
+       0xee, 0xa7, 0x64, 0xbb, 0x04, 0xf6, 0x09, 0xfc, 0x79, 0xed, 0xd7, 0xc8,
+       0x63, 0x1f, 0x6b, 0x8d, 0x04, 0x56, 0x72, 0xdb, 0x27, 0x0c, 0x08, 0x1d,
+       0xf6, 0xc9, 0xb1, 0x4d, 0xda, 0x27, 0xe7, 0xa5, 0x7d, 0x92, 0xdd, 0xb8,
+       0x7d, 0xb2, 0xbb, 0x25, 0xae, 0xab, 0x31, 0x9e, 0xcd, 0xdb, 0x27, 0xc6,
+       0x9a, 0xf6, 0xc9, 0x90, 0xc3, 0x17, 0x83, 0xfe, 0xfe, 0x06, 0x65, 0x8f,
+       0x43, 0xc7, 0x69, 0x3a, 0x83, 0xc6, 0xc7, 0x5d, 0x7e, 0xe1, 0x4f, 0x93,
+       0xd6, 0xbf, 0xf8, 0x3f, 0xa6, 0xf5, 0x50, 0x8b, 0xcf, 0xbb, 0x31, 0x1e,
+       0x0a, 0xef, 0xd8, 0x14, 0x8e, 0x77, 0xd3, 0x7a, 0xa8, 0xad, 0xef, 0xb4,
+       0x7d, 0xcc, 0x62, 0xb3, 0xef, 0x74, 0xd4, 0x68, 0xa7, 0xdb, 0xff, 0xd8,
+       0xe1, 0x53, 0x75, 0xea, 0x77, 0xc8, 0x14, 0xf9, 0x8e, 0x4d, 0xe8, 0x77,
+       0x41, 0x96, 0xac, 0x6c, 0x96, 0x60, 0x33, 0xe1, 0x7d, 0x11, 0x21, 0x6b,
+       0x2e, 0xbc, 0xc5, 0xef, 0x63, 0x7a, 0xbe, 0xf8, 0x87, 0x62, 0x9d, 0x92,
+       0xfe, 0x07, 0xb4, 0x0f, 0xfb, 0xce, 0x88, 0xb6, 0x32, 0xbe, 0x49, 0xf9,
+       0x23, 0x14, 0xf6, 0x6f, 0xe7, 0x87, 0x68, 0x5d, 0xf3, 0x36, 0x67, 0x2b,
+       0x68, 0x19, 0xdf, 0xcb, 0xf3, 0x12, 0x69, 0xb2, 0xb5, 0xa0, 0x3f, 0xcf,
+       0x33, 0x2e, 0x18, 0xad, 0x63, 0x82, 0xe6, 0xb9, 0xb9, 0x28, 0x6c, 0x3a,
+       0xad, 0x3b, 0x57, 0x64, 0xec, 0xa9, 0xb8, 0x0e, 0x9c, 0xa6, 0x75, 0xa7,
+       0x1b, 0x07, 0xef, 0xf5, 0xe0, 0x0b, 0xcf, 0xdc, 0x4f, 0x3d, 0x77, 0x26,
+       0x62, 0xce, 0x53, 0x9e, 0x73, 0x57, 0xcf, 0xe1, 0xca, 0x36, 0xda, 0xca,
+       0xfb, 0x53, 0x62, 0x5c, 0xdf, 0xfc, 0x62, 0x02, 0xb9, 0x6a, 0xf5, 0xfc,
+       0x21, 0x77, 0xce, 0x14, 0xd6, 0x01, 0x2d, 0x87, 0x3a, 0x3f, 0x1b, 0xb4,
+       0x18, 0xf1, 0xc8, 0x99, 0x72, 0xae, 0x25, 0xb8, 0xcf, 0x4d, 0x8b, 0xc6,
+       0x3a, 0x32, 0xa7, 0xd6, 0x91, 0x45, 0x87, 0x1e, 0x6f, 0xc5, 0xed, 0xfd,
+       0x1e, 0xb8, 0xdd, 0x2b, 0x6f, 0x0a, 0x7d, 0x7a, 0x92, 0x71, 0xc8, 0x67,
+       0x80, 0x43, 0x42, 0xc8, 0x5b, 0x92, 0x58, 0x04, 0xdf, 0x17, 0x19, 0x8f,
+       0x44, 0x98, 0x57, 0x7e, 0x44, 0xe7, 0x18, 0x6b, 0x5f, 0xa7, 0xfd, 0xca,
+       0x3e, 0x83, 0xdc, 0xea, 0x38, 0x53, 0xc4, 0xf1, 0xfb, 0x28, 0xfb, 0x98,
+       0x35, 0x19, 0xa7, 0x1f, 0xd1, 0x59, 0x11, 0x33, 0x83, 0xfd, 0x3d, 0xc4,
+       0x1c, 0x3c, 0x20, 0xde, 0x2f, 0x7d, 0x19, 0xf7, 0x23, 0xa6, 0x6e, 0xe3,
+       0xf1, 0xfb, 0x2a, 0xb7, 0x8e, 0xdb, 0xe1, 0x9d, 0x4b, 0x4a, 0xa6, 0xc4,
+       0x35, 0xbe, 0xff, 0x49, 0xa3, 0xf5, 0xfe, 0xb8, 0x91, 0xaa, 0xa6, 0x8c,
+       0x44, 0x05, 0xed, 0x9e, 0x34, 0x92, 0x55, 0xd8, 0x90, 0x9a, 0x47, 0xac,
+       0x28, 0xe4, 0x6d, 0x95, 0xd6, 0xdf, 0x8b, 0x58, 0x24, 0x57, 0x9e, 0xc4,
+       0x06, 0xfa, 0x7d, 0xb8, 0xa9, 0xdf, 0x9a, 0xbe, 0x38, 0x86, 0xbf, 0xe7,
+       0x15, 0xa6, 0xa9, 0xc6, 0xb5, 0x41, 0xf8, 0xd7, 0x27, 0xb3, 0xb4, 0x16,
+       0xae, 0xb5, 0x5a, 0x70, 0xed, 0xe2, 0xba, 0xfd, 0xfe, 0xa4, 0x32, 0x2e,
+       0xf3, 0xa3, 0xfd, 0xb6, 0xc0, 0xaf, 0xdc, 0xef, 0x26, 0x6c, 0xeb, 0xe2,
+       0x29, 0xb4, 0xd1, 0x7e, 0x70, 0xed, 0x07, 0xeb, 0x55, 0xf1, 0xc0, 0x3a,
+       0x3e, 0x21, 0x88, 0x7c, 0xaf, 0x90, 0x8c, 0x6b, 0x85, 0x8d, 0xb5, 0xc2,
+       0xfd, 0x83, 0xbd, 0x05, 0x9f, 0x8f, 0xb0, 0xb7, 0xcc, 0x24, 0x49, 0x5f,
+       0xf7, 0x99, 0xaa, 0xd3, 0xbf, 0xeb, 0x95, 0x4b, 0x39, 0xea, 0x91, 0x4b,
+       0xe9, 0x94, 0xb5, 0x80, 0x43, 0xd6, 0x22, 0x0e, 0xdc, 0x36, 0xcc, 0x76,
+       0x4b, 0x0f, 0xeb, 0x90, 0x1e, 0xb1, 0x6d, 0xe2, 0xbf, 0xea, 0xb4, 0x5b,
+       0xdc, 0x79, 0xf1, 0x90, 0x3b, 0x60, 0x33, 0x69, 0xc3, 0xa4, 0x4a, 0xf5,
+       0x9c, 0x7a, 0x1e, 0x77, 0x23, 0x6f, 0xb1, 0xd2, 0x92, 0x63, 0xe9, 0xd5,
+       0xdf, 0x91, 0x96, 0xfe, 0x62, 0xfd, 0x8a, 0xb7, 0xc5, 0x74, 0x5e, 0x76,
+       0xd5, 0xfd, 0xea, 0x9f, 0x5b, 0x9f, 0xe1, 0x5d, 0xa3, 0xc2, 0xe7, 0x9d,
+       0xad, 0xeb, 0xb2, 0x19, 0xd9, 0xdf, 0x42, 0xb3, 0x9d, 0xe1, 0xbf, 0x42,
+       0x8a, 0x76, 0xde, 0xba, 0x7d, 0x73, 0xfe, 0xb3, 0xad, 0x6e, 0x1c, 0xdc,
+       0x27, 0xfd, 0x62, 0x73, 0x2a, 0x0e, 0x7b, 0x40, 0xd9, 0x7b, 0xeb, 0xf1,
+       0x3b, 0xae, 0xcd, 0x29, 0x5f, 0xa2, 0x65, 0x96, 0x09, 0x7c, 0x7e, 0xfc,
+       0x54, 0x87, 0x1d, 0x52, 0x7b, 0x59, 0xd8, 0xaf, 0x02, 0xdf, 0xeb, 0xe7,
+       0x43, 0x67, 0x6f, 0x64, 0xce, 0xcc, 0x96, 0x39, 0x93, 0x7c, 0x05, 0x5b,
+       0x0b, 0xf1, 0xc5, 0x53, 0xae, 0x18, 0xef, 0x4f, 0x42, 0x8b, 0x5e, 0x8f,
+       0xb8, 0x67, 0xc4, 0x2d, 0xb7, 0xeb, 0xe7, 0x1d, 0x07, 0x2e, 0x47, 0x7f,
+       0x6b, 0xb5, 0x57, 0xa2, 0xbb, 0xe5, 0x5a, 0x5c, 0xf5, 0xc6, 0x48, 0xa1,
+       0x0d, 0xf7, 0xcf, 0xbd, 0xf6, 0xee, 0xda, 0xe0, 0xda, 0x2b, 0xea, 0x8b,
+       0xf8, 0x0e, 0x09, 0x1d, 0xd0, 0x43, 0x95, 0x12, 0xe2, 0xaf, 0x3f, 0x0b,
+       0x99, 0x67, 0x3d, 0xeb, 0xc8, 0x49, 0xf3, 0x9e, 0xc7, 0xfa, 0x9e, 0x4a,
+       0x20, 0x86, 0xbd, 0x3f, 0xc4, 0x96, 0xf4, 0xb3, 0xee, 0x41, 0xfb, 0x71,
+       0xf3, 0x16, 0xfc, 0xbd, 0xca, 0xff, 0x94, 0x52, 0xeb, 0xcb, 0xa1, 0x0d,
+       0xec, 0xad, 0x6c, 0x4e, 0x4f, 0x5b, 0xe6, 0x0a, 0x61, 0xdf, 0x07, 0xf1,
+       0xc2, 0xc7, 0x7a, 0xa9, 0xf7, 0x2b, 0x5d, 0x5d, 0xf6, 0x1f, 0xf4, 0xc9,
+       0xbd, 0x28, 0x7c, 0xd7, 0x43, 0x2f, 0x94, 0x10, 0xcb, 0x8d, 0xef, 0x7e,
+       0x8b, 0xbf, 0xf3, 0xd2, 0x51, 0x3a, 0x16, 0x1d, 0x58, 0x4e, 0xce, 0x4f,
+       0x99, 0x60, 0x2b, 0xd5, 0xe8, 0x6f, 0xa2, 0x9f, 0x93, 0xfb, 0x19, 0xd5,
+       0xfb, 0xbd, 0x57, 0xe3, 0xe5, 0x2f, 0xfc, 0x69, 0xdf, 0xc7, 0x8d, 0x8d,
+       0xfc, 0xd6, 0x86, 0xfc, 0x85, 0xd8, 0xe7, 0xdf, 0xc8, 0x9e, 0x89, 0xde,
+       0x1b, 0x9e, 0x16, 0x39, 0xa7, 0x4e, 0x3e, 0xb8, 0x3f, 0xfb, 0xc3, 0xe0,
+       0x87, 0x91, 0x16, 0x5d, 0xf5, 0xc9, 0xfd, 0xfd, 0x6e, 0xba, 0x06, 0x3d,
+       0x7d, 0x55, 0xde, 0xfb, 0xc0, 0xd8, 0xf3, 0x87, 0x9f, 0xba, 0x4a, 0x67,
+       0xae, 0x81, 0x87, 0x0d, 0xe6, 0xb6, 0x31, 0xca, 0x87, 0x91, 0x57, 0x24,
+       0x72, 0x73, 0xf4, 0xbe, 0xa1, 0xc8, 0x15, 0x3a, 0x23, 0x72, 0x20, 0xc7,
+       0x23, 0xf7, 0x78, 0x3d, 0x3c, 0x53, 0x7d, 0x9b, 0xce, 0x56, 0x82, 0xfc,
+       0xdf, 0xc0, 0xee, 0xad, 0x79, 0x90, 0xcd, 0x3c, 0x7e, 0x4f, 0xf0, 0xf8,
+       0xf0, 0x9a, 0x3c, 0x7e, 0xa4, 0xce, 0xe3, 0x5f, 0xe9, 0x97, 0xfc, 0xdc,
+       0xcb, 0xcf, 0xea, 0xa5, 0x43, 0xe2, 0xb9, 0x6f, 0xf3, 0xf1, 0x56, 0x3a,
+       0x14, 0x92, 0xc7, 0x67, 0x2b, 0xac, 0xe3, 0x0b, 0x6f, 0xd3, 0xb9, 0x6b,
+       0x59, 0x5f, 0x4a, 0xe4, 0x2f, 0x38, 0x6b, 0x69, 0xe8, 0xfb, 0xd1, 0xae,
+       0x1d, 0xff, 0x6b, 0xbd, 0x24, 0x73, 0xae, 0xca, 0x52, 0x3f, 0xd1, 0x5b,
+       0xd1, 0x21, 0x17, 0xff, 0x37, 0xdb, 0x8e, 0xe7, 0xd5, 0x1a, 0x78, 0x7c,
+       0x0d, 0xbf, 0x46, 0x2b, 0x5f, 0xf6, 0x79, 0xe0, 0xe1, 0xa7, 0xfb, 0xe5,
+       0x3e, 0xd5, 0x5a, 0x7e, 0x8d, 0xa6, 0xb8, 0x0e, 0xe7, 0xbe, 0x3d, 0xeb,
+       0xfd, 0x3d, 0x2a, 0x17, 0xf0, 0x87, 0xfd, 0x72, 0xbd, 0x40, 0x7e, 0xe0,
+       0x0a, 0xd3, 0xe1, 0x22, 0x63, 0x95, 0x21, 0xea, 0xbc, 0xaa, 0xc7, 0x3a,
+       0x24, 0xf4, 0xad, 0xd3, 0x4f, 0x73, 0x51, 0xe5, 0x76, 0xe7, 0x1c, 0x63,
+       0xba, 0x28, 0x6c, 0x9c, 0xf6, 0xf2, 0xd6, 0x3e, 0xe6, 0x6a, 0xd8, 0xb5,
+       0x26, 0xb8, 0xf9, 0x0d, 0x75, 0x4a, 0x30, 0xbf, 0x64, 0x48, 0x1c, 0x3c,
+       0xc3, 0xf8, 0x76, 0xb3, 0xfb, 0x45, 0x9f, 0x14, 0x23, 0xba, 0x6b, 0x60,
+       0xb8, 0x8f, 0x31, 0x0f, 0xd2, 0xe6, 0xc8, 0xbc, 0x58, 0x15, 0xba, 0xe0,
+       0xe2, 0x54, 0x8d, 0x92, 0xd1, 0x6d, 0x94, 0x99, 0xe2, 0x77, 0xcf, 0xd8,
+       0x6c, 0x7b, 0xf9, 0x29, 0xcb, 0xf2, 0x9b, 0x99, 0xda, 0xa2, 0xf0, 0xa2,
+       0xf6, 0xa7, 0x77, 0xa9, 0x38, 0x87, 0x5e, 0xb1, 0x2f, 0x29, 0x6b, 0xf5,
+       0xf0, 0x71, 0x45, 0x3f, 0x1b, 0xd7, 0xc1, 0xbb, 0x9d, 0xaa, 0xdd, 0x65,
+       0x47, 0x3b, 0xb4, 0xb9, 0xac, 0xda, 0xe2, 0x99, 0x1a, 0x53, 0x74, 0x2b,
+       0x7d, 0x0b, 0x39, 0x5c, 0x51, 0xb9, 0x7a, 0xc2, 0x7e, 0xa0, 0xd9, 0xfa,
+       0x58, 0x2e, 0x73, 0xdb, 0xff, 0xae, 0xc5, 0x85, 0x2d, 0x77, 0x99, 0x31,
+       0x6f, 0x55, 0xc8, 0x8a, 0xbb, 0x4f, 0x18, 0x8b, 0x5f, 0xec, 0x0f, 0xf1,
+       0xb1, 0x7a, 0xcf, 0xe9, 0x7a, 0x9f, 0x10, 0xa3, 0x61, 0x45, 0xe4, 0xb3,
+       0x74, 0xbb, 0xcb, 0x8e, 0x76, 0x5a, 0x57, 0xe8, 0xfd, 0x87, 0x8f, 0x7c,
+       0xb3, 0x85, 0xdb, 0x3e, 0x19, 0xc3, 0x1b, 0x12, 0xfb, 0xa7, 0x32, 0x46,
+       0x43, 0x1f, 0xc3, 0xbf, 0x8c, 0x98, 0x0a, 0xc4, 0x49, 0x38, 0xf5, 0x8d,
+       0x1c, 0x6f, 0x00, 0x6b, 0x51, 0x15, 0xfb, 0xa6, 0xd8, 0xaf, 0x68, 0x87,
+       0x9d, 0x77, 0x21, 0x36, 0x7f, 0x13, 0x18, 0x74, 0x23, 0xf2, 0x67, 0x7a,
+       0xc8, 0x9f, 0xf3, 0xfd, 0xc8, 0x83, 0x43, 0x3e, 0x5c, 0x76, 0xd2, 0xa0,
+       0x1a, 0xdb, 0x0a, 0x06, 0x95, 0x43, 0x3e, 0x3a, 0x67, 0x5b, 0xd1, 0x8a,
+       0xc0, 0x9a, 0x8f, 0xc0, 0x7f, 0x35, 0xb9, 0x42, 0x07, 0x44, 0xce, 0x38,
+       0x6a, 0x1f, 0x94, 0x79, 0x0d, 0x3e, 0xcd, 0x3c, 0x78, 0x96, 0xed, 0x8f,
+       0xec, 0x49, 0xec, 0xb7, 0xe8, 0x79, 0x41, 0x0e, 0x3c, 0x3e, 0x4d, 0x9e,
+       0xbb, 0xdf, 0xdd, 0x41, 0xc1, 0x38, 0x3f, 0xd3, 0x84, 0x7e, 0xe2, 0xe7,
+       0xa4, 0x29, 0xc1, 0x76, 0x12, 0x6c, 0xd6, 0xd3, 0x27, 0xad, 0x50, 0x99,
+       0x0c, 0x6e, 0x0b, 0xdb, 0x15, 0xcf, 0xc1, 0xfd, 0xf1, 0x50, 0x07, 0xb9,
+       0x73, 0x72, 0x7b, 0x45, 0x9e, 0xe2, 0x5b, 0xd1, 0x07, 0xc9, 0x18, 0x84,
+       0xbe, 0xc2, 0xbc, 0x3d, 0xa0, 0xf6, 0x89, 0xb6, 0xf3, 0xf1, 0x84, 0x3a,
+       0x0e, 0x8a, 0xf9, 0x94, 0xc7, 0x9a, 0xbf, 0xf1, 0xf7, 0xf3, 0x2e, 0xb2,
+       0xfd, 0x6a, 0xfe, 0x9a, 0x62, 0x41, 0x22, 0x63, 0x46, 0x90, 0xce, 0x57,
+       0xd6, 0xf2, 0xbf, 0x78, 0xe5, 0xba, 0x6e, 0xdf, 0x60, 0xae, 0xeb, 0x4f,
+       0x76, 0xc8, 0xdc, 0x32, 0x67, 0x5f, 0xfe, 0x93, 0xfb, 0xe2, 0x85, 0xc9,
+       0x5a, 0x70, 0x22, 0x8f, 0xb7, 0x46, 0x3f, 0x8b, 0x7e, 0x9e, 0xee, 0x84,
+       0x23, 0x2a, 0x66, 0x09, 0x31, 0x4a, 0x0f, 0x2a, 0xbe, 0xd6, 0xba, 0x9f,
+       0x3c, 0x74, 0xff, 0xa3, 0x22, 0x56, 0x53, 0xae, 0x1d, 0x43, 0x8a, 0x1e,
+       0xa0, 0x59, 0xc4, 0x41, 0xb3, 0x01, 0x07, 0xcd, 0x0c, 0x75, 0xbc, 0x4d,
+       0x9c, 0x9f, 0xaf, 0x3c, 0xb5, 0x5d, 0xe6, 0x8b, 0x63, 0x2f, 0xf1, 0x92,
+       0x3a, 0x5e, 0x6f, 0xbc, 0x56, 0x98, 0x82, 0xc2, 0xdf, 0xe4, 0x18, 0xeb,
+       0xcb, 0x44, 0xf6, 0x81, 0x70, 0x2b, 0x0d, 0x5e, 0x73, 0x5c, 0x47, 0x1f,
+       0xc7, 0x1d, 0x7d, 0x1c, 0x75, 0xf4, 0x71, 0x6f, 0x9b, 0x3e, 0xb2, 0x8e,
+       0xe7, 0xf7, 0x9c, 0xad, 0x7e, 0xdc, 0xbe, 0xa2, 0x9f, 0xc8, 0x23, 0x06,
+       0x3d, 0xb7, 0x52, 0x2e, 0x1c, 0x51, 0x6b, 0xc7, 0x2f, 0x55, 0x2e, 0xba,
+       0x57, 0x9f, 0xff, 0x8e, 0xda, 0xcf, 0x9b, 0x93, 0x57, 0x9d, 0xf9, 0xc7,
+       0xdf, 0xa5, 0xa4, 0xcc, 0x23, 0x57, 0xb2, 0x7d, 0xb9, 0x8d, 0x1f, 0x1a,
+       0xf1, 0x1c, 0xc0, 0x20, 0xc2, 0x2e, 0xdc, 0x2d, 0x6b, 0xc1, 0x05, 0x68,
+       0xa9, 0x9e, 0xcb, 0xeb, 0x57, 0xb9, 0x3b, 0xc7, 0xc3, 0xf7, 0x37, 0x8f,
+       0x17, 0xd7, 0xff, 0x4c, 0xf8, 0xf2, 0xe4, 0xfe, 0xd1, 0x8a, 0xca, 0x47,
+       0xb6, 0x4c, 0xc4, 0x06, 0x2c, 0x2e, 0xc3, 0xff, 0xda, 0x2e, 0x77, 0x57,
+       0xea, 0xa2, 0x4c, 0xbd, 0x3e, 0x4a, 0x59, 0xe4, 0x35, 0x48, 0xff, 0x98,
+       0xcc, 0xbf, 0x5d, 0x5c, 0xbe, 0x25, 0x72, 0x5e, 0x13, 0x2a, 0x8f, 0x37,
+       0x43, 0x3d, 0x02, 0xe7, 0x7e, 0xfc, 0xfc, 0xdb, 0x17, 0xc2, 0x9b, 0xcf,
+       0xbf, 0x75, 0xde, 0xb3, 0xb9, 0xfc, 0xdb, 0x10, 0x8f, 0xdd, 0x58, 0x90,
+       0xf9, 0xb7, 0xcd, 0x7b, 0x32, 0x32, 0xff, 0x36, 0xe3, 0xc0, 0x0f, 0x12,
+       0xaf, 0xbf, 0xe5, 0x88, 0xdf, 0x96, 0xb9, 0xb5, 0x8b, 0x75, 0xcc, 0x2a,
+       0x73, 0x6b, 0x65, 0xbc, 0xb7, 0xb3, 0x0e, 0x8c, 0xdc, 0xfb, 0x91, 0xef,
+       0xd9, 0xe6, 0xda, 0xfb, 0x91, 0x39, 0xb5, 0xa6, 0xd1, 0xce, 0x86, 0xc3,
+       0x1a, 0x81, 0x7a, 0x08, 0x71, 0xe6, 0xdd, 0xad, 0x6d, 0xea, 0x21, 0xc4,
+       0xdb, 0xd4, 0x43, 0x70, 0xea, 0x7e, 0x27, 0xc6, 0x02, 0x26, 0xc6, 0xda,
+       0x08, 0x2c, 0x8c, 0x7a, 0x06, 0x51, 0x3a, 0x5f, 0xc7, 0x9e, 0x0f, 0x52,
+       0x5a, 0x61, 0xcf, 0xf3, 0x15, 0xad, 0x8f, 0x46, 0x5d, 0xfa, 0xc8, 0x0b,
+       0x8b, 0x5a, 0x2a, 0xce, 0x47, 0xcb, 0x6b, 0xd6, 0x21, 0xaf, 0x59, 0x0f,
+       0x79, 0xc5, 0x3d, 0xd9, 0x36, 0xfd, 0xfe, 0xa5, 0xba, 0x07, 0xff, 0x4f,
+       0x46, 0x50, 0xb3, 0x85, 0x68, 0xf7, 0x80, 0xc2, 0x7f, 0x0e, 0x79, 0x3d,
+       0xcb, 0xf2, 0xaa, 0xaf, 0xa3, 0xbf, 0xed, 0x6c, 0x00, 0x8d, 0x19, 0x87,
+       0x7c, 0x87, 0xaf, 0xbd, 0x21, 0xe2, 0xa4, 0x9a, 0xed, 0x45, 0x8d, 0x27,
+       0xf6, 0x09, 0x59, 0xba, 0xe3, 0x47, 0xdc, 0x8a, 0xbe, 0x16, 0x52, 0x7e,
+       0x32, 0x4d, 0x8b, 0xce, 0x26, 0xcc, 0xd1, 0xc0, 0x1b, 0x22, 0xc6, 0xd7,
+       0xd1, 0xb7, 0x7f, 0xe5, 0xbe, 0xe9, 0xeb, 0x7a, 0xcd, 0x7c, 0xa7, 0xc9,
+       0x9f, 0x71, 0xa3, 0xa9, 0xee, 0x1f, 0x7c, 0x47, 0xdb, 0xd2, 0x86, 0x9d,
+       0x12, 0x31, 0xa6, 0x7d, 0x36, 0xfc, 0x64, 0x09, 0x96, 0xfd, 0xbe, 0x34,
+       0xe2, 0x99, 0xfb, 0xae, 0x98, 0x74, 0xa2, 0x70, 0x7e, 0x8f, 0xe4, 0x95,
+       0x0b, 0xa2, 0xa6, 0x25, 0x6a, 0x20, 0x26, 0x79, 0x7d, 0x4e, 0x30, 0xe8,
+       0x9c, 0xab, 0x76, 0xd1, 0x22, 0xa3, 0x7b, 0xbf, 0x5d, 0x16, 0xbe, 0x3e,
+       0xd6, 0x49, 0x45, 0xd4, 0x36, 0x35, 0x16, 0x3a, 0xf9, 0xb9, 0x83, 0xb4,
+       0x54, 0x1a, 0x17, 0x35, 0xa1, 0x64, 0x7d, 0x11, 0xb4, 0xf5, 0x51, 0xbf,
+       0xfd, 0x0d, 0xa6, 0xdd, 0xd7, 0x44, 0x8c, 0xe5, 0x62, 0xf1, 0x82, 0xfc,
+       0x2c, 0x3f, 0xa5, 0xde, 0xc1, 0xef, 0xab, 0xfe, 0x98, 0xe2, 0xfd, 0xa6,
+       0xc3, 0x96, 0x73, 0xfe, 0x79, 0xe3, 0x95, 0x63, 0x9b, 0xc2, 0x2b, 0xd9,
+       0x74, 0x03, 0xaf, 0x38, 0x9f, 0xad, 0xb1, 0xcb, 0xe4, 0xa0, 0xac, 0xf7,
+       0x00, 0x1a, 0x6c, 0x05, 0x16, 0x4b, 0x83, 0x96, 0x46, 0xcc, 0x8a, 0x24,
+       0xfc, 0x33, 0x94, 0xaf, 0x5e, 0xa7, 0x4c, 0x11, 0x98, 0x99, 0x3f, 0xcb,
+       0xe7, 0x76, 0x4a, 0x1f, 0x8d, 0xbe, 0x07, 0x7a, 0x65, 0x07, 0xb7, 0xff,
+       0xeb, 0x41, 0x19, 0x97, 0xed, 0xbc, 0xde, 0xcb, 0xd7, 0xbf, 0x10, 0x69,
+       0xbe, 0xbe, 0x85, 0xaf, 0xf7, 0xa7, 0x31, 0x87, 0xc6, 0x15, 0xf8, 0x25,
+       0x27, 0x29, 0xc7, 0xf3, 0x93, 0xaf, 0xf2, 0xda, 0x7a, 0x95, 0xf5, 0x55,
+       0x45, 0xb7, 0x1b, 0x40, 0xce, 0x8e, 0x98, 0x13, 0x83, 0xdb, 0x5c, 0x2c,
+       0x4c, 0x71, 0xbb, 0x21, 0xf2, 0x5f, 0x35, 0x29, 0x5f, 0xd1, 0xbc, 0xaa,
+       0xe3, 0xed, 0xdf, 0x18, 0x90, 0x31, 0x55, 0xef, 0xec, 0x94, 0xf4, 0x9b,
+       0x14, 0x3e, 0x4f, 0xc4, 0x73, 0x3c, 0x23, 0xf8, 0xd0, 0x9a, 0x31, 0xeb,
+       0xef, 0xdf, 0x06, 0xbe, 0x42, 0xdd, 0x54, 0x1e, 0x03, 0xeb, 0xc5, 0x98,
+       0x1d, 0xca, 0xd5, 0x63, 0xd5, 0x9e, 0xdb, 0x2d, 0xef, 0xff, 0xe9, 0x80,
+       0xac, 0x55, 0x7a, 0x5b, 0x9d, 0xeb, 0x35, 0x07, 0xf1, 0xcb, 0x3e, 0x41,
+       0x1b, 0xff, 0x02, 0xf4, 0xa5, 0xc1, 0xc7, 0x3c, 0x9e, 0x34, 0xfa, 0xf8,
+       0xb3, 0x01, 0x5d, 0x9f, 0x50, 0x8e, 0xeb, 0x28, 0xf7, 0x37, 0xc5, 0xe3,
+       0xd2, 0xd7, 0xe3, 0x7c, 0xee, 0x35, 0xbf, 0x78, 0x56, 0x30, 0x2d, 0xeb,
+       0x8b, 0x05, 0xd3, 0x99, 0x49, 0x39, 0xcf, 0x0d, 0x9f, 0x6e, 0xa4, 0xee,
+       0xd3, 0x9d, 0x2b, 0xf4, 0x0f, 0xc2, 0xbf, 0x61, 0x5c, 0xe1, 0xf9, 0x0e,
+       0x3f, 0xc3, 0x6d, 0x91, 0xab, 0x90, 0xe3, 0xcf, 0x1e, 0x15, 0xd7, 0xd3,
+       0xca, 0x2b, 0x32, 0x4e, 0x42, 0xaf, 0x5b, 0xb8, 0x77, 0x80, 0x9f, 0x21,
+       0xd7, 0xae, 0xf6, 0xef, 0xa1, 0x96, 0x38, 0x98, 0x56, 0x1e, 0x5b, 0xcb,
+       0x0f, 0x2b, 0xf6, 0x13, 0x3d, 0xf8, 0x6c, 0xad, 0x7a, 0x06, 0xef, 0x08,
+       0x3f, 0x5a, 0xb2, 0x45, 0x5e, 0x21, 0xc7, 0x01, 0xfa, 0xce, 0x7c, 0x96,
+       0xb6, 0xf0, 0x5c, 0x7d, 0xc3, 0xf8, 0x35, 0xec, 0xb7, 0x93, 0x8c, 0x79,
+       0x62, 0x1a, 0x17, 0xec, 0xc9, 0xb3, 0x06, 0xd3, 0xb9, 0x90, 0xad, 0x05,
+       0xec, 0x1e, 0xea, 0x64, 0x59, 0xfd, 0x22, 0x8d, 0xb1, 0xfd, 0x07, 0x99,
+       0xb5, 0x23, 0x29, 0x82, 0xbc, 0x59, 0xa1, 0xc3, 0xcc, 0x13, 0xc9, 0x2a,
+       0xf8, 0xd9, 0xa0, 0x27, 0x4a, 0x44, 0x8f, 0x97, 0xc6, 0x42, 0xdf, 0x27,
+       0xdb, 0x6c, 0x7c, 0x6f, 0x85, 0x12, 0xdc, 0x8f, 0x54, 0xf5, 0x77, 0xe8,
+       0x43, 0x51, 0xe7, 0x04, 0x74, 0xd4, 0xf3, 0xfe, 0xdb, 0x74, 0x3a, 0x8d,
+       0x7e, 0x6f, 0x5c, 0x3e, 0x4f, 0x6c, 0x4a, 0x3e, 0x83, 0x1e, 0xf2, 0xf9,
+       0xea, 0xa0, 0xe4, 0x9b, 0x1a, 0xf3, 0x68, 0x90, 0x66, 0x8b, 0x88, 0x01,
+       0x7b, 0x18, 0x75, 0xa7, 0x8a, 0x19, 0xd6, 0x4b, 0x99, 0x86, 0x5e, 0xba,
+       0x94, 0xf0, 0xc7, 0x21, 0xe3, 0xa8, 0xcb, 0xa6, 0xe2, 0x7e, 0x30, 0x8e,
+       0xdd, 0x34, 0xb6, 0xb0, 0x95, 0xef, 0xa5, 0x95, 0xc4, 0x74, 0x5c, 0xe5,
+       0xfa, 0x5b, 0x66, 0x92, 0xf5, 0xe3, 0x1c, 0xcb, 0x72, 0xae, 0xf8, 0x00,
+       0x2d, 0x86, 0x87, 0x69, 0x74, 0x41, 0xd7, 0x37, 0xc1, 0x58, 0xff, 0x6d,
+       0x48, 0xea, 0x24, 0x3d, 0xee, 0x5f, 0x11, 0xbe, 0x0b, 0xf3, 0xfa, 0xa7,
+       0x35, 0xee, 0xad, 0xeb, 0xe8, 0xa5, 0xbf, 0x52, 0x32, 0x5b, 0xbb, 0x91,
+       0x88, 0x52, 0x36, 0x31, 0xfd, 0x97, 0x82, 0xff, 0x47, 0xaf, 0xc3, 0x0f,
+       0x07, 0x1d, 0x6d, 0x52, 0xba, 0xe0, 0xa6, 0xc5, 0x30, 0x8f, 0x1b, 0xdf,
+       0xd7, 0xfe, 0x79, 0x36, 0xfa, 0x94, 0x58, 0xfb, 0xc7, 0xae, 0x73, 0x3b,
+       0xb1, 0x36, 0x69, 0xbd, 0xe1, 0xc5, 0x87, 0xba, 0x8e, 0xa5, 0xe6, 0x45,
+       0x19, 0xeb, 0xc9, 0xf8, 0x2d, 0x94, 0xf6, 0xbb, 0x79, 0xf2, 0x23, 0x3a,
+       0x36, 0x6f, 0xd2, 0xf1, 0x82, 0xf5, 0x7c, 0x96, 0x66, 0x58, 0xae, 0x9d,
+       0xeb, 0x05, 0xb7, 0x27, 0xf0, 0x59, 0x8c, 0x65, 0x9f, 0xed, 0xe6, 0xa2,
+       0x29, 0xe3, 0xee, 0x44, 0xed, 0xb9, 0x2e, 0xa1, 0x47, 0x43, 0xf6, 0x3f,
+       0x0d, 0xea, 0xf5, 0x20, 0x53, 0x44, 0x1e, 0x21, 0x7f, 0x96, 0xb9, 0x7d,
+       0x61, 0x90, 0x32, 0x25, 0x3c, 0x07, 0xeb, 0x1d, 0xfa, 0xce, 0xe7, 0x4b,
+       0x72, 0x5e, 0x47, 0xf9, 0xd9, 0xc8, 0xbb, 0x3f, 0x5e, 0x9d, 0x12, 0xb1,
+       0x77, 0xd0, 0xcd, 0x72, 0x3e, 0x63, 0x74, 0xd1, 0x53, 0xaf, 0x28, 0x4c,
+       0xe9, 0x90, 0xef, 0x8c, 0x90, 0xef, 0x98, 0x98, 0x8f, 0x4c, 0xc9, 0x60,
+       0xbc, 0xa6, 0x7d, 0x0f, 0xfd, 0x7c, 0x1e, 0x50, 0x3a, 0x04, 0xdf, 0x0d,
+       0xec, 0x14, 0x71, 0x89, 0x36, 0xae, 0xe3, 0x33, 0x46, 0xcf, 0x30, 0xee,
+       0x7c, 0xb6, 0xd0, 0x45, 0xb7, 0x8a, 0x5d, 0xf4, 0x66, 0x71, 0x98, 0x6e,
+       0xce, 0x6f, 0xa7, 0x8b, 0x8c, 0x99, 0x2f, 0xda, 0x01, 0x33, 0xc7, 0xf6,
+       0xc5, 0x0b, 0x51, 0x11, 0x33, 0xc4, 0x72, 0x87, 0xf6, 0xc0, 0x7f, 0x89,
+       0x5d, 0xcc, 0x73, 0x8c, 0xbd, 0xbb, 0xe9, 0x03, 0x7e, 0x67, 0xae, 0xa0,
+       0x63, 0x1d, 0xe0, 0x93, 0x1f, 0xaf, 0xe3, 0xd7, 0xf5, 0x79, 0x24, 0xb4,
+       0x0e, 0x8f, 0xc4, 0x84, 0xae, 0xcf, 0xcf, 0xf3, 0xf7, 0xf3, 0xf0, 0x9f,
+       0x33, 0xbd, 0x59, 0x3f, 0x7f, 0x3d, 0x80, 0xf6, 0xb8, 0x66, 0xcb, 0x58,
+       0x49, 0x31, 0xb6, 0x08, 0x9f, 0x83, 0xb6, 0x11, 0x45, 0x87, 0x6e, 0x1e,
+       0x9f, 0x4f, 0xb4, 0xcf, 0x2c, 0x75, 0xd3, 0x99, 0x12, 0x63, 0x90, 0x92,
+       0x9f, 0x6d, 0x18, 0xb4, 0x0d, 0xec, 0xd5, 0xf5, 0x5f, 0x2f, 0x72, 0xdf,
+       0x73, 0x25, 0x89, 0x41, 0x72, 0x4b, 0xbd, 0x94, 0x2f, 0xf5, 0xa8, 0xf3,
+       0x07, 0x44, 0x8c, 0xbb, 0xac, 0x63, 0x84, 0xef, 0xd6, 0xd2, 0x6f, 0x6f,
+       0x31, 0x4f, 0x61, 0x4d, 0x95, 0x76, 0x29, 0x74, 0xcd, 0x8d, 0x96, 0xba,
+       0xc4, 0xe0, 0xb9, 0x19, 0xfa, 0x2e, 0xaf, 0xb7, 0xa3, 0x57, 0xe1, 0x3f,
+       0xfe, 0x2a, 0xf8, 0xa6, 0x0c, 0x1e, 0x1b, 0xbd, 0x8a, 0xba, 0x48, 0x7e,
+       0x91, 0xe7, 0x94, 0x0c, 0x4f, 0x8a, 0xdc, 0x10, 0x29, 0xa3, 0x27, 0x45,
+       0x2d, 0xba, 0x1f, 0x0a, 0xdd, 0x64, 0x65, 0x4d, 0x03, 0x78, 0x04, 0x3e,
+       0x18, 0x19, 0x83, 0x75, 0xc2, 0xee, 0x7b, 0x6b, 0x20, 0x36, 0x41, 0xf1,
+       0x41, 0xf0, 0xbd, 0x94, 0x59, 0x55, 0x5f, 0x40, 0xe8, 0xfb, 0xd0, 0x3e,
+       0x9d, 0x2f, 0xa9, 0xcf, 0xf5, 0x5a, 0xa1, 0xcf, 0x7b, 0x5c, 0xdf, 0x87,
+       0x5c, 0xdf, 0xd7, 0xe3, 0xe5, 0x78, 0xcd, 0xe3, 0x75, 0x9e, 0x64, 0x8d,
+       0xa2, 0xcc, 0x82, 0xe4, 0xbf, 0xd0, 0xbe, 0xf1, 0xd0, 0x97, 0x15, 0x06,
+       0xcf, 0x2c, 0x8f, 0x45, 0xfa, 0x8c, 0x1e, 0x7f, 0x66, 0xea, 0xef, 0x6b,
+       0xf1, 0x34, 0x70, 0xd1, 0xdc, 0x4e, 0xa9, 0xe3, 0xd0, 0xaf, 0x6c, 0x14,
+       0xd0, 0xed, 0xe4, 0x72, 0x0f, 0xad, 0x88, 0x9a, 0x5c, 0xc0, 0x18, 0xb8,
+       0x1f, 0xcf, 0xc9, 0x86, 0x3a, 0x08, 0x35, 0xd7, 0x21, 0xe3, 0x07, 0x22,
+       0xd7, 0x79, 0x3e, 0x53, 0xcb, 0xff, 0x55, 0x3b, 0x2d, 0x6a, 0xdc, 0xa0,
+       0x2d, 0x63, 0x48, 0x81, 0xf9, 0x19, 0xbf, 0x34, 0xd9, 0x55, 0x33, 0xe8,
+       0x67, 0x16, 0x7b, 0x2b, 0x86, 0xfd, 0x22, 0xcb, 0x98, 0xdc, 0x2b, 0x4f,
+       0xb9, 0xf6, 0xca, 0x4f, 0x8a, 0xbd, 0x72, 0xec, 0x93, 0x83, 0xae, 0xa0,
+       0xa5, 0x57, 0x4c, 0x0b, 0xe6, 0x31, 0xca, 0xf3, 0x68, 0xd2, 0xc5, 0x6b,
+       0x42, 0xdf, 0x44, 0x93, 0x7e, 0x19, 0x5f, 0x9d, 0xa2, 0xac, 0x88, 0xbf,
+       0x96, 0x9f, 0x71, 0x23, 0x61, 0x5b, 0x93, 0xab, 0x8c, 0x29, 0x2a, 0xc5,
+       0x2d, 0x74, 0xb3, 0xdc, 0xc1, 0x98, 0xef, 0x6f, 0x69, 0xb5, 0x4c, 0x8c,
+       0x0d, 0xb7, 0x53, 0x3e, 0xca, 0xbc, 0x36, 0x19, 0xe4, 0x79, 0x65, 0x7c,
+       0x3b, 0xc9, 0xf2, 0xc7, 0x63, 0xa8, 0x94, 0x6a, 0xef, 0xe7, 0xa2, 0x71,
+       0x33, 0x31, 0xdd, 0xc3, 0xf6, 0x4b, 0x88, 0xff, 0x6d, 0xfe, 0xff, 0x6c,
+       0x04, 0xb4, 0x59, 0x5c, 0xc2, 0xf7, 0x8c, 0x7d, 0x0a, 0xb5, 0xf7, 0x67,
+       0xb9, 0xcd, 0xec, 0x34, 0xec, 0x20, 0xd8, 0x7b, 0x36, 0xff, 0xcb, 0x36,
+       0x15, 0xe6, 0xbb, 0xdc, 0xb5, 0x6c, 0xc4, 0x10, 0x3a, 0x1e, 0x75, 0x5d,
+       0xc6, 0xd4, 0x67, 0xdc, 0x98, 0xe5, 0xbe, 0xdc, 0x24, 0x3c, 0xc3, 0xa4,
+       0x4c, 0x74, 0x1f, 0xcb, 0xc1, 0x76, 0xfe, 0x44, 0x3e, 0xd6, 0x56, 0xca,
+       0x4f, 0x8d, 0xab, 0x7c, 0xac, 0x48, 0x9b, 0x7c, 0x2c, 0xdc, 0xc7, 0x38,
+       0x60, 0xbe, 0x76, 0x6f, 0x36, 0xea, 0x7c, 0x2f, 0x19, 0x99, 0xe8, 0x36,
+       0x81, 0x99, 0x2a, 0x4b, 0xfb, 0xb9, 0x0f, 0x71, 0x33, 0x33, 0xcd, 0x7d,
+       0x2d, 0x39, 0xfb, 0x5f, 0xbb, 0x97, 0x8c, 0xa2, 0x9d, 0xdf, 0xd5, 0x2e,
+       0x4e, 0xa2, 0xed, 0x12, 0xda, 0xd7, 0xfe, 0x27, 0x11, 0xd5, 0xe3, 0x74,
+       0xde, 0x8b, 0xf1, 0x40, 0xbe, 0xf8, 0xb3, 0x72, 0x9b, 0x6e, 0x16, 0x61,
+       0x8f, 0x1b, 0xcc, 0xf7, 0xe8, 0x91, 0x49, 0xd9, 0x0a, 0x63, 0xc0, 0x6b,
+       0x7b, 0x7d, 0xab, 0xc5, 0x37, 0x6a, 0x99, 0xa6, 0xd8, 0x96, 0x66, 0x3f,
+       0xbc, 0xb4, 0xc1, 0x86, 0xc9, 0xbe, 0x82, 0x35, 0x14, 0xeb, 0x67, 0xb6,
+       0xe6, 0xb7, 0x81, 0xf7, 0x60, 0x1b, 0x5d, 0x60, 0xfd, 0x25, 0xe3, 0x93,
+       0x58, 0x97, 0xb2, 0x0e, 0x93, 0xf2, 0x93, 0x6a, 0xfa, 0x39, 0x04, 0xc9,
+       0xc3, 0xa3, 0x8d, 0xb8, 0x48, 0xc7, 0xfe, 0x7a, 0xc0, 0xb1, 0xbf, 0x1e,
+       0x72, 0xc4, 0x45, 0x86, 0x05, 0x3e, 0x6b, 0x60, 0xaa, 0xb0, 0xc2, 0x54,
+       0xc0, 0x5e, 0x52, 0xb7, 0x2d, 0xd6, 0x75, 0xdb, 0x8e, 0x75, 0x74, 0x9b,
+       0x97, 0xad, 0xba, 0xa2, 0xf4, 0x88, 0x15, 0xc5, 0x1a, 0x73, 0x83, 0xf5,
+       0xc5, 0xeb, 0xd5, 0x69, 0xd6, 0x23, 0x51, 0xd6, 0x23, 0x53, 0xac, 0x47,
+       0x26, 0x59, 0x8f, 0xd8, 0x4c, 0x03, 0x93, 0xc7, 0xfe, 0x11, 0xeb, 0x69,
+       0xac, 0x1f, 0x33, 0xf4, 0x4c, 0x15, 0x3a, 0x79, 0x8a, 0x31, 0xd0, 0x47,
+       0xb4, 0x3a, 0xdf, 0xcb, 0xfc, 0x2b, 0x71, 0x4f, 0xb3, 0x5d, 0x83, 0xda,
+       0x2b, 0xf0, 0x17, 0xff, 0x39, 0xf4, 0xce, 0x2b, 0x59, 0x1a, 0xf1, 0xdd,
+       0x2c, 0x82, 0xce, 0xab, 0xa8, 0x55, 0xf1, 0x12, 0x64, 0x1b, 0x35, 0x82,
+       0x7f, 0x30, 0x31, 0xc3, 0x7d, 0x1f, 0xf1, 0xe5, 0x79, 0x5e, 0xbe, 0x1d,
+       0xcd, 0x86, 0xfa, 0x59, 0x06, 0x8e, 0x2b, 0x19, 0x38, 0xde, 0x90, 0x81,
+       0x6c, 0x8e, 0x47, 0xd2, 0xb7, 0xb0, 0x9d, 0xc6, 0x0f, 0x26, 0x76, 0xf5,
+       0xb1, 0xfc, 0x22, 0x66, 0xa2, 0x51, 0xbf, 0xc7, 0x4f, 0xa7, 0xc3, 0x41,
+       0x55, 0xf7, 0xc7, 0x14, 0x39, 0xef, 0xf9, 0xe2, 0xbb, 0x8c, 0x4b, 0x58,
+       0x4e, 0x43, 0x38, 0xbf, 0x0c, 0xbf, 0x28, 0xdb, 0x0d, 0xdd, 0xc2, 0xaf,
+       0xb4, 0x28, 0xda, 0xe2, 0xdc, 0x9a, 0x64, 0x1d, 0x17, 0x5d, 0x31, 0xac,
+       0x99, 0xb8, 0xf1, 0x9b, 0xc3, 0xa8, 0xe1, 0xfe, 0x83, 0xea, 0xe7, 0x86,
+       0xe5, 0xde, 0x5c, 0x72, 0x97, 0xd4, 0x27, 0xcc, 0xa3, 0xe1, 0xb8, 0xb0,
+       0xdd, 0x3a, 0xae, 0xc8, 0xf5, 0x73, 0x91, 0xe7, 0xbb, 0x12, 0x9d, 0xe4,
+       0xf9, 0xee, 0x51, 0x6b, 0x67, 0x96, 0xbf, 0x17, 0xeb, 0x32, 0xaf, 0xa1,
+       0xc3, 0xa8, 0x7f, 0x1f, 0x12, 0x75, 0x22, 0x4e, 0xa2, 0x0e, 0x4f, 0x02,
+       0xcf, 0x63, 0xee, 0x85, 0xfe, 0xf8, 0x07, 0x5e, 0xa3, 0xf1, 0x5e, 0xf0,
+       0x23, 0x1f, 0x97, 0x67, 0xe8, 0x52, 0x41, 0xf7, 0xe1, 0x3d, 0x32, 0xbe,
+       0x8b, 0x7e, 0xf8, 0x68, 0x87, 0xfd, 0x9e, 0xc8, 0x05, 0x31, 0xfe, 0xc4,
+       0xdd, 0xa7, 0xa3, 0xaa, 0x4f, 0xa8, 0x75, 0xd9, 0x85, 0xda, 0x3e, 0x84,
+       0x9a, 0x48, 0x8b, 0xa2, 0x16, 0x65, 0xa7, 0xb0, 0x59, 0x17, 0x85, 0xed,
+       0xb1, 0x7f, 0x57, 0xa3, 0x3e, 0xe6, 0x7e, 0xd7, 0xb5, 0x3b, 0xbc, 0x6e,
+       0x1d, 0x12, 0x18, 0x6d, 0x14, 0xf5, 0xda, 0x45, 0x5e, 0xea, 0x8c, 0xf8,
+       0xce, 0x58, 0xc0, 0x77, 0x0f, 0xa9, 0xef, 0x3e, 0x2f, 0xb0, 0xb1, 0x11,
+       0xeb, 0x66, 0xbd, 0x28, 0xf8, 0x9d, 0xe7, 0xd9, 0x9e, 0x64, 0x7e, 0x8f,
+       0x54, 0xf8, 0xb9, 0xa7, 0x05, 0x3d, 0x35, 0x3d, 0x40, 0x0b, 0xc8, 0x40,
+       0x8f, 0xe2, 0x7f, 0xcb, 0x4c, 0xf9, 0xf5, 0xb8, 0xdb, 0xd1, 0x99, 0xb1,
+       0x4e, 0x01, 0x63, 0xc5, 0x98, 0x4c, 0x5f, 0xbc, 0x1c, 0xf1, 0xe5, 0xe6,
+       0x61, 0xeb, 0x20, 0xdf, 0x65, 0x0f, 0xe2, 0xa9, 0xb8, 0x0f, 0x3b, 0x29,
+       0x9e, 0x46, 0xbf, 0xd0, 0x4e, 0xd3, 0xc0, 0x76, 0xd1, 0xc2, 0x79, 0xdf,
+       0x76, 0x75, 0x5f, 0xb7, 0x98, 0x0b, 0x32, 0xf0, 0x1e, 0xfd, 0x6e, 0xbc,
+       0x17, 0xef, 0xc7, 0x7d, 0x78, 0x9e, 0x7c, 0xee, 0x00, 0xeb, 0xed, 0xc4,
+       0xb4, 0x7c, 0x96, 0x71, 0x5d, 0x7e, 0x37, 0x60, 0x7b, 0xf7, 0x57, 0xce,
+       0x9f, 0x4f, 0xd5, 0xf1, 0xc1, 0xfc, 0x6d, 0xa7, 0xb2, 0xf0, 0x7d, 0xe2,
+       0xbb, 0x11, 0x9f, 0xb0, 0x6b, 0x6d, 0xfe, 0xe4, 0x79, 0x9d, 0xe3, 0xf3,
+       0x33, 0xc5, 0xdb, 0xc2, 0x66, 0xcf, 0xa5, 0x47, 0x7c, 0xe5, 0x32, 0xc6,
+       0x3b, 0xe2, 0x4b, 0xb1, 0x0c, 0x24, 0x8b, 0x89, 0x5a, 0x5e, 0xe2, 0x02,
+       0x3a, 0xdd, 0x6f, 0x85, 0x4e, 0x1b, 0xef, 0x0f, 0xcb, 0x9a, 0xb7, 0x38,
+       0x66, 0x39, 0x2c, 0xb0, 0x1c, 0x16, 0x58, 0x0e, 0x0b, 0x2c, 0x87, 0x6c,
+       0xab, 0xbe, 0x56, 0x60, 0x39, 0xe4, 0xb5, 0xe4, 0x55, 0x5e, 0x4b, 0xa4,
+       0xec, 0xc6, 0x95, 0x7f, 0x53, 0xcb, 0xae, 0x3b, 0x6f, 0x53, 0xcb, 0x2a,
+       0xd6, 0x6f, 0xf2, 0x1d, 0x99, 0x68, 0x96, 0xd9, 0x5b, 0x2c, 0xb3, 0x1d,
+       0xb1, 0x41, 0xba, 0x5b, 0xc2, 0x9c, 0x59, 0xe6, 0x1c, 0xeb, 0xea, 0x94,
+       0x1f, 0x58, 0x2b, 0xc0, 0xf2, 0x04, 0xac, 0x69, 0x31, 0xdd, 0x07, 0xe9,
+       0x1e, 0xeb, 0xeb, 0xbb, 0x25, 0xc8, 0xf0, 0x1e, 0x75, 0x6e, 0xb1, 0x0c,
+       0x63, 0xfd, 0xb3, 0x7d, 0xb7, 0x8a, 0x06, 0x63, 0xb2, 0x40, 0x28, 0x43,
+       0xd0, 0xa7, 0x02, 0xa7, 0xf1, 0xbc, 0xaf, 0xb0, 0xde, 0x87, 0x0f, 0x0f,
+       0xeb, 0xc5, 0x19, 0x1f, 0xaf, 0x17, 0x91, 0x9b, 0xac, 0x4f, 0xcf, 0x97,
+       0x6c, 0x96, 0xfb, 0x7e, 0xfa, 0x56, 0x09, 0xeb, 0x34, 0x68, 0xc4, 0xe7,
+       0x65, 0x12, 0xbe, 0x31, 0x23, 0x86, 0xb1, 0x8f, 0x67, 0x0d, 0xc1, 0x27,
+       0x7f, 0x0a, 0x3a, 0x30, 0xed, 0x5f, 0xdc, 0x85, 0xda, 0xf3, 0x71, 0xa3,
+       0x53, 0xf9, 0x1a, 0x71, 0x8c, 0xf6, 0x68, 0x0b, 0xba, 0xe1, 0xbc, 0xdd,
+       0xbe, 0x24, 0x7e, 0xb3, 0x21, 0x0a, 0xff, 0x9b, 0x4b, 0x7f, 0x5d, 0xe2,
+       0xfb, 0x05, 0xbd, 0x66, 0x12, 0x7e, 0xe4, 0x90, 0xd3, 0xd3, 0xfe, 0xd8,
+       0x0c, 0x3d, 0x5b, 0x45, 0xbf, 0xaf, 0x52, 0x3e, 0x0c, 0x7d, 0x64, 0x45,
+       0xef, 0x90, 0xa4, 0x5d, 0x37, 0xe3, 0xce, 0x27, 0xbc, 0x75, 0x9c, 0x99,
+       0x10, 0x38, 0xb9, 0x8b, 0xf5, 0x0b, 0x68, 0xf3, 0x13, 0xe6, 0x35, 0x7e,
+       0x5f, 0x41, 0xeb, 0xb7, 0x1f, 0xb3, 0xce, 0xc1, 0x9c, 0xe1, 0x7c, 0x6d,
+       0x9d, 0xb6, 0xaa, 0x74, 0x9a, 0xed, 0xd0, 0x69, 0xb9, 0xba, 0x4e, 0x63,
+       0xde, 0x10, 0xba, 0x0c, 0xba, 0xea, 0x51, 0xc6, 0x91, 0xf2, 0x18, 0xf8,
+       0x70, 0x87, 0xd0, 0x5d, 0xac, 0xfb, 0xd9, 0xae, 0x58, 0xac, 0x66, 0x7d,
+       0x87, 0x85, 0x0e, 0xd1, 0xfc, 0xbd, 0x7f, 0xb7, 0x94, 0x8b, 0x6e, 0xa1,
+       0x0f, 0x72, 0x27, 0xa1, 0xb7, 0xbc, 0xda, 0x8f, 0x73, 0x3b, 0xb4, 0xb7,
+       0x23, 0x2f, 0xb1, 0x3e, 0x5b, 0x8c, 0xc2, 0xa6, 0xed, 0x51, 0xb6, 0x0f,
+       0xea, 0x72, 0x61, 0xaf, 0x0b, 0x63, 0xd5, 0xfa, 0x6c, 0x40, 0xf9, 0x35,
+       0xe0, 0x87, 0xc4, 0x9c, 0xb7, 0xc5, 0x08, 0x26, 0x30, 0x02, 0xdf, 0x13,
+       0x60, 0x7a, 0x89, 0x1a, 0xe2, 0x44, 0xef, 0xd2, 0xaa, 0x90, 0x8d, 0x77,
+       0x05, 0x76, 0xc9, 0xf3, 0x77, 0xb3, 0xd3, 0x07, 0x45, 0x3f, 0xf3, 0x4b,
+       0x0d, 0xfd, 0x38, 0x57, 0x78, 0x0f, 0xeb, 0x86, 0xe8, 0x6b, 0x65, 0x42,
+       0xea, 0xc0, 0xc5, 0x32, 0x6a, 0x80, 0x89, 0x3e, 0x73, 0x5f, 0xf5, 0x38,
+       0xd1, 0x0f, 0xad, 0x0f, 0x36, 0x22, 0x7b, 0x8c, 0x6b, 0xfb, 0x31, 0x47,
+       0x59, 0x07, 0x0f, 0x3d, 0xcb, 0xef, 0xc7, 0xb5, 0xf5, 0xc7, 0x73, 0xaf,
+       0x3e, 0x1e, 0xf8, 0xf6, 0x70, 0xcf, 0xbb, 0x74, 0x57, 0x8d, 0xe7, 0x6e,
+       0x7d, 0x3c, 0xcf, 0xa8, 0xf1, 0x50, 0xce, 0x88, 0x0d, 0x28, 0xdc, 0xbf,
+       0xe1, 0x67, 0x77, 0x27, 0x18, 0xc7, 0xe4, 0x96, 0x40, 0xe7, 0xfd, 0x8a,
+       0x9f, 0x9c, 0x7e, 0x54, 0x67, 0x5f, 0xad, 0xc9, 0x3b, 0xac, 0x7f, 0xef,
+       0x09, 0x1c, 0x33, 0xc2, 0x38, 0x06, 0xd7, 0x29, 0x0f, 0x3d, 0x9d, 0x0b,
+       0xa3, 0x4e, 0xed, 0x0c, 0x8f, 0x9b, 0xed, 0xb1, 0x69, 0xfe, 0x14, 0xfe,
+       0x35, 0x3c, 0x47, 0xdf, 0xff, 0x3c, 0xdd, 0x9b, 0x87, 0x2e, 0x07, 0x8e,
+       0x95, 0xb5, 0x6c, 0xef, 0x2d, 0x4b, 0xff, 0x6e, 0xca, 0xd3, 0xbf, 0x0b,
+       0xdf, 0xee, 0x34, 0x70, 0x7e, 0x08, 0x7e, 0xe0, 0xa4, 0xfa, 0xad, 0x8f,
+       0x5c, 0x15, 0xcf, 0xf2, 0xd2, 0x4b, 0x33, 0x8e, 0xd8, 0x38, 0xc4, 0xaa,
+       0x64, 0x59, 0xcf, 0xd8, 0xa1, 0x0e, 0x43, 0xe6, 0xdc, 0xdc, 0xa8, 0x6a,
+       0xec, 0x74, 0x94, 0xe7, 0xcc, 0x8e, 0x1a, 0x46, 0x4a, 0xf8, 0x1a, 0xba,
+       0xed, 0x1e, 0xea, 0xe2, 0x75, 0xf4, 0x2c, 0xa1, 0x96, 0x9a, 0x65, 0x62,
+       0x0f, 0xe0, 0x12, 0xf3, 0x64, 0x3e, 0x6a, 0x45, 0x1e, 0x17, 0x76, 0x29,
+       0xd6, 0x17, 0x03, 0x74, 0x62, 0x5a, 0xa3, 0x0f, 0x7c, 0xbc, 0x84, 0x3a,
+       0x9a, 0x51, 0x1e, 0x3f, 0xfc, 0xc7, 0x63, 0xe6, 0x9b, 0xbc, 0x2e, 0x5d,
+       0x12, 0x7e, 0x99, 0x0b, 0x94, 0x63, 0x39, 0x3d, 0x22, 0xe4, 0xd4, 0x18,
+       0x61, 0x29, 0x62, 0xb9, 0x42, 0x6c, 0xc2, 0xb8, 0xa8, 0xdb, 0x23, 0x6d,
+       0x1d, 0x1e, 0xe5, 0xb2, 0xaa, 0x87, 0x90, 0x86, 0xee, 0xd8, 0xb8, 0x4f,
+       0x22, 0xfd, 0x89, 0x7d, 0x31, 0x4e, 0x4c, 0xe6, 0xf6, 0x7d, 0xc3, 0xae,
+       0x33, 0x45, 0xbd, 0x48, 0xd0, 0x4e, 0xf8, 0x13, 0x8d, 0x29, 0xa6, 0x9b,
+       0xfe, 0xdd, 0x19, 0xa7, 0xdf, 0xe0, 0x9c, 0xc8, 0xeb, 0x7f, 0xa5, 0x2a,
+       0xd7, 0xe0, 0x1c, 0xdb, 0xf4, 0xf9, 0x83, 0x4e, 0x4c, 0x62, 0x15, 0x93,
+       0xc2, 0x97, 0xb3, 0x9b, 0x12, 0x0b, 0x53, 0xf4, 0x68, 0x01, 0x3a, 0x8c,
+       0xee, 0x24, 0x6c, 0xfc, 0xa2, 0x0c, 0x64, 0x7c, 0x8a, 0x52, 0x55, 0xd0,
+       0xc8, 0xc7, 0x58, 0x89, 0x79, 0xaf, 0x88, 0x3d, 0x7f, 0x3e, 0x2e, 0xe3,
+       0x77, 0x54, 0x7e, 0x5d, 0xf9, 0xcb, 0x87, 0x29, 0xb9, 0x40, 0xd9, 0x4c,
+       0xf4, 0x4b, 0xa2, 0xd6, 0x75, 0x26, 0x3a, 0xa1, 0x7c, 0x3b, 0x11, 0xbe,
+       0x0e, 0x7f, 0x99, 0x49, 0x5f, 0x2e, 0x58, 0xd9, 0x0c, 0x49, 0x9f, 0x05,
+       0x71, 0x1f, 0x0c, 0x5e, 0x7b, 0x77, 0xb0, 0x0e, 0x39, 0x21, 0xfc, 0x16,
+       0x8c, 0x54, 0xe6, 0xd1, 0x1e, 0x3e, 0x87, 0x7e, 0x82, 0x9d, 0x96, 0x29,
+       0x3e, 0xa5, 0xda, 0xd6, 0x28, 0xc4, 0xbc, 0x10, 0xfa, 0x55, 0x3b, 0x1b,
+       0x35, 0x1a, 0xf7, 0xc3, 0xe7, 0x71, 0x42, 0xe0, 0xc8, 0x11, 0xb6, 0x79,
+       0x44, 0xbb, 0xda, 0xac, 0xf0, 0x5f, 0xf0, 0x79, 0xf9, 0x81, 0x21, 0xfd,
+       0x9b, 0x08, 0xb8, 0x2e, 0xfd, 0x1a, 0xfc, 0xcc, 0x32, 0xf7, 0xa3, 0x29,
+       0x9e, 0x7e, 0x98, 0xe2, 0x9b, 0xf0, 0x33, 0x9d, 0xbc, 0xaf, 0x7e, 0x26,
+       0xa6, 0x35, 0xaf, 0x3d, 0x37, 0x58, 0x36, 0x5e, 0x5f, 0xd7, 0xfe, 0xfb,
+       0x50, 0xaf, 0xe1, 0x4c, 0xab, 0x90, 0xf8, 0xdd, 0x0c, 0x60, 0xf0, 0x7c,
+       0xf5, 0x71, 0xfc, 0x5e, 0x8c, 0x2f, 0x2d, 0xb0, 0x71, 0x84, 0xb1, 0x0d,
+       0x30, 0xce, 0x98, 0xd8, 0x17, 0x8b, 0x3f, 0x16, 0xf1, 0xe5, 0x97, 0x07,
+       0xc9, 0x0f, 0x7f, 0x9c, 0xad, 0x63, 0x29, 0xba, 0x45, 0xdc, 0xbb, 0xdc,
+       0x8f, 0xc4, 0xfa, 0x0c, 0x9d, 0x78, 0x87, 0xed, 0x86, 0x09, 0x15, 0x87,
+       0xd3, 0x21, 0x6a, 0x53, 0xc9, 0xbd, 0x54, 0xad, 0x53, 0x34, 0xef, 0xe9,
+       0xbd, 0x0e, 0xe7, 0x6f, 0x73, 0x41, 0x76, 0x9d, 0x98, 0x02, 0xfe, 0x29,
+       0x31, 0x47, 0x97, 0x88, 0xe4, 0x1c, 0x37, 0xf6, 0x31, 0xba, 0x78, 0x9e,
+       0x60, 0x0f, 0xc2, 0xef, 0xf7, 0x35, 0xfe, 0xc4, 0x7e, 0xc4, 0xd5, 0x21,
+       0xe0, 0xa8, 0x3e, 0x9b, 0x79, 0x66, 0x1a, 0xe7, 0x83, 0x6c, 0x9f, 0x69,
+       0xdc, 0x2b, 0x7d, 0x51, 0x6c, 0xb3, 0xa9, 0xf9, 0x82, 0x1f, 0x6a, 0x54,
+       0xd5, 0x29, 0xb0, 0xc8, 0xec, 0x07, 0x9d, 0x3e, 0x2d, 0x79, 0x5c, 0x6f,
+       0xef, 0x62, 0x23, 0xb1, 0x4e, 0xf8, 0xdd, 0x30, 0xd4, 0xeb, 0xdc, 0x0b,
+       0xda, 0xf3, 0x1c, 0x39, 0xf7, 0x36, 0x1e, 0xdf, 0xa5, 0x7f, 0xb3, 0xe8,
+       0xfe, 0xcc, 0xdb, 0x16, 0x8f, 0x79, 0xfb, 0xf9, 0x90, 0xdc, 0x3b, 0x7b,
+       0x58, 0xb5, 0xf1, 0x8a, 0x6f, 0x5d, 0xfe, 0x0e, 0xfc, 0x50, 0x8d, 0xfc,
+       0x8b, 0x77, 0x84, 0x5e, 0x69, 0xf5, 0x85, 0x47, 0x58, 0x9f, 0x4a, 0x39,
+       0x3e, 0xe1, 0x21, 0xc7, 0xfd, 0x31, 0xe0, 0x96, 0x8f, 0x2f, 0xc7, 0xc7,
+       0xdb, 0xca, 0xf1, 0x9e, 0x61, 0xe9, 0x8b, 0x6d, 0x95, 0x63, 0xe4, 0x00,
+       0x9d, 0xa8, 0xb6, 0xf3, 0x7b, 0x61, 0x1e, 0x90, 0xcb, 0xee, 0xf4, 0x95,
+       0x80, 0x66, 0xda, 0x5f, 0x82, 0x7d, 0x43, 0xf0, 0x25, 0xf6, 0x5e, 0x4e,
+       0x1a, 0xa9, 0x79, 0xf7, 0x5e, 0xea, 0x46, 0xee, 0xbd, 0xed, 0x71, 0x2f,
+       0xb0, 0x3b, 0x64, 0xc3, 0x8a, 0x48, 0x5f, 0x80, 0xa6, 0xdf, 0xb0, 0xef,
+       0x70, 0xc9, 0xca, 0x96, 0x09, 0xbe, 0xee, 0x30, 0x9d, 0xc3, 0xfe, 0xb4,
+       0xf2, 0x25, 0x1f, 0x2b, 0x48, 0x3a, 0x84, 0x0e, 0x0a, 0xfe, 0x00, 0xbe,
+       0x8d, 0xa4, 0xfd, 0x69, 0x9e, 0x63, 0xe9, 0x47, 0xce, 0x2c, 0x45, 0xd4,
+       0xbc, 0x71, 0x5b, 0x3c, 0xcf, 0x33, 0x5f, 0x10, 0xf3, 0x65, 0x3d, 0xbf,
+       0x52, 0x8f, 0x4f, 0xc6, 0xda, 0x50, 0xa3, 0xff, 0xe0, 0x75, 0xcf, 0x7f,
+       0x30, 0x24, 0x6a, 0x37, 0xdc, 0xa8, 0x1e, 0x64, 0xbc, 0x89, 0x39, 0x85,
+       0x0f, 0x52, 0xfb, 0x88, 0x1f, 0xda, 0x4b, 0xbd, 0x07, 0x18, 0x05, 0x18,
+       0x64, 0x33, 0xbe, 0x34, 0x0e, 0x22, 0xce, 0xdc, 0xe4, 0x7b, 0x50, 0x73,
+       0x6a, 0xdc, 0x4c, 0x51, 0x0f, 0xfc, 0x10, 0xa8, 0x25, 0x6d, 0xe6, 0x9a,
+       0x64, 0xec, 0x94, 0x90, 0xb1, 0xd4, 0xf2, 0x29, 0x25, 0x63, 0xa7, 0x94,
+       0x1f, 0xfe, 0x94, 0x92, 0xb1, 0x53, 0x4a, 0xc6, 0x4e, 0x29, 0x19, 0x3b,
+       0xc5, 0x7c, 0x3e, 0xc6, 0xf8, 0x16, 0x58, 0x44, 0xfb, 0x41, 0x7b, 0x29,
+       0x53, 0xc2, 0x75, 0xac, 0xcf, 0x6e, 0x39, 0x7b, 0x69, 0x44, 0xca, 0x19,
+       0x63, 0x13, 0x19, 0xaf, 0xc7, 0xef, 0xc2, 0x1c, 0xfc, 0x1e, 0xd3, 0xef,
+       0x23, 0x3a, 0x33, 0x8f, 0xbe, 0xfa, 0x28, 0x29, 0x6a, 0xc9, 0x76, 0x50,
+       0xc2, 0x89, 0x85, 0x43, 0xc8, 0x0f, 0x93, 0xb6, 0x5f, 0xb6, 0x6d, 0xae,
+       0x98, 0xe6, 0x93, 0x98, 0x9a, 0x2f, 0xb7, 0x5d, 0xd4, 0x45, 0xe9, 0x22,
+       0xe8, 0x8a, 0x98, 0x4a, 0x93, 0xe7, 0x46, 0xd0, 0x49, 0x86, 0x44, 0xb9,
+       0x68, 0x70, 0x4c, 0xd1, 0xe0, 0xdb, 0x62, 0x8c, 0x88, 0x49, 0x84, 0x2f,
+       0xb3, 0x3d, 0x1d, 0x72, 0x85, 0x31, 0x7e, 0x0e, 0xcb, 0xc2, 0xc1, 0x08,
+       0xeb, 0xa4, 0x8d, 0xd3, 0xa1, 0x31, 0xf6, 0x76, 0xba, 0x67, 0xa3, 0x79,
+       0x39, 0x77, 0x1c, 0x6b, 0x49, 0x44, 0xad, 0x23, 0x12, 0x17, 0x6f, 0xb1,
+       0x6b, 0x74, 0x34, 0xba, 0x97, 0x8f, 0xad, 0x74, 0x96, 0x0e, 0x90, 0xd1,
+       0x57, 0xa3, 0xbf, 0x60, 0x39, 0xe8, 0x66, 0x39, 0x38, 0xaa, 0xec, 0x92,
+       0xa3, 0x75, 0xbb, 0x64, 0xcf, 0x1e, 0xc4, 0x65, 0x64, 0xc4, 0xbe, 0xd7,
+       0x56, 0x55, 0x43, 0x00, 0xbe, 0x6f, 0x9c, 0x77, 0x51, 0x7c, 0x18, 0xe7,
+       0xf8, 0x2d, 0x22, 0x6b, 0x32, 0xee, 0x1b, 0xdf, 0x23, 0xb0, 0xbb, 0xcf,
+       0xc2, 0x3d, 0x47, 0xa5, 0xde, 0xf3, 0x91, 0x7f, 0xfc, 0x36, 0xe3, 0x89,
+       0x1a, 0x3d, 0xc1, 0xef, 0xcc, 0x17, 0xf7, 0xf1, 0xb3, 0x75, 0x4d, 0x09,
+       0x3b, 0x6e, 0xf8, 0xb6, 0x92, 0xbf, 0xaf, 0xdd, 0xbb, 0x2d, 0xc1, 0x8f,
+       0x8c, 0xa7, 0x8d, 0xd9, 0xe8, 0x7b, 0xb5, 0xd3, 0x27, 0xe1, 0x63, 0x87,
+       0x9c, 0x58, 0x21, 0xd3, 0xe7, 0x25, 0x1f, 0x12, 0x2b, 0x35, 0xe2, 0x63,
+       0x21, 0x2f, 0x35, 0xfa, 0x77, 0x1e, 0x5b, 0x88, 0xb0, 0x77, 0x22, 0x9f,
+       0x9f, 0xa6, 0x19, 0x91, 0x83, 0x8d, 0x38, 0xe9, 0x33, 0xf3, 0xfa, 0x5d,
+       0xb6, 0xe2, 0x8d, 0xcf, 0x20, 0xce, 0xad, 0xb8, 0x48, 0x6b, 0xaf, 0x39,
+       0xf0, 0xd7, 0x8d, 0x2d, 0xac, 0xf6, 0x85, 0x45, 0x4e, 0xf8, 0x76, 0xc6,
+       0x48, 0x3a, 0x1e, 0x7a, 0x9c, 0x9f, 0x0f, 0x3f, 0x5e, 0x80, 0x92, 0x57,
+       0xd0, 0xae, 0x93, 0x46, 0x17, 0x6a, 0x5f, 0xe0, 0xef, 0xc5, 0xfe, 0x65,
+       0x86, 0xba, 0xd5, 0xde, 0x44, 0x8f, 0xda, 0xcf, 0x8a, 0xb0, 0xec, 0x35,
+       0x72, 0x9d, 0x47, 0xeb, 0x3e, 0x3d, 0xc8, 0x84, 0xdb, 0xa7, 0xf7, 0xf4,
+       0x3a, 0xeb, 0xd5, 0x7a, 0x72, 0x80, 0x58, 0xd6, 0x2e, 0x52, 0xbe, 0x4a,
+       0x33, 0x4f, 0x1b, 0xcd, 0xe9, 0xdb, 0xf4, 0x3d, 0xdd, 0x9d, 0x31, 0xf3,
+       0xc2, 0x9b, 0x76, 0x50, 0xf1, 0x5f, 0x27, 0x9d, 0x29, 0x05, 0x79, 0xcd,
+       0x87, 0x6e, 0x05, 0xbd, 0xfc, 0xc3, 0xc8, 0x73, 0xf9, 0x7a, 0xa0, 0x93,
+       0x96, 0x96, 0x10, 0x6b, 0xf1, 0x47, 0x7b, 0x64, 0x7c, 0x71, 0x9a, 0xe9,
+       0x72, 0x80, 0xd7, 0x47, 0x43, 0xed, 0x1d, 0xe1, 0x1a, 0x74, 0x89, 0xa8,
+       0x37, 0x1a, 0xf8, 0xd2, 0x44, 0x90, 0xed, 0x02, 0xb9, 0xf7, 0x70, 0x88,
+       0x9f, 0xfd, 0xfd, 0x52, 0x1a, 0xfe, 0xb2, 0xd0, 0x11, 0x7e, 0x7e, 0x92,
+       0xf1, 0x44, 0x9c, 0x3a, 0xa9, 0xb2, 0xd4, 0xc9, 0x76, 0x41, 0x27, 0xe3,
+       0x89, 0xb1, 0xd0, 0xa8, 0x4f, 0xbc, 0x4b, 0xe4, 0xd4, 0x3c, 0x1c, 0x38,
+       0xc0, 0x7c, 0x85, 0x77, 0xbd, 0xae, 0xde, 0xe5, 0x7e, 0xc7, 0x2f, 0x6a,
+       0x38, 0x3f, 0xe2, 0x37, 0x2f, 0xdc, 0xc2, 0xef, 0x51, 0xcd, 0xcf, 0x30,
+       0x76, 0x0e, 0x53, 0x7e, 0xbe, 0x83, 0xc7, 0x10, 0x63, 0x3b, 0x22, 0xca,
+       0xe7, 0x8f, 0x50, 0xb6, 0x7a, 0x92, 0x7e, 0xbf, 0xea, 0xf4, 0x09, 0x3f,
+       0xc2, 0x7d, 0x96, 0x39, 0xfd, 0x5d, 0xdc, 0xaf, 0x0f, 0x6d, 0xb7, 0x8e,
+       0x09, 0x92, 0xff, 0x7b, 0x61, 0xea, 0x7c, 0x0e, 0xbe, 0x97, 0x1a, 0x15,
+       0xa3, 0xd6, 0xa5, 0x3b, 0x24, 0xfd, 0xcf, 0x2f, 0x88, 0xb8, 0x5a, 0xbe,
+       0x9f, 0x9f, 0x39, 0x87, 0x76, 0x2f, 0x98, 0x74, 0xd3, 0x96, 0xf4, 0x7e,
+       0x23, 0x10, 0x26, 0xff, 0xcb, 0x88, 0x7d, 0x02, 0x56, 0x33, 0x2f, 0xd8,
+       0xfb, 0x58, 0xbf, 0x3f, 0x87, 0xfb, 0xf8, 0xf3, 0x65, 0x9c, 0x07, 0x79,
+       0x9c, 0x58, 0xaf, 0x11, 0xef, 0x02, 0xbd, 0x78, 0x20, 0x12, 0x12, 0xfc,
+       0xf7, 0x08, 0xf3, 0x54, 0x87, 0xf0, 0x35, 0xf6, 0xa3, 0xad, 0x3d, 0xc4,
+       0xd8, 0xc2, 0xbc, 0x30, 0xb1, 0x0f, 0xe7, 0xf1, 0x3e, 0x3f, 0xd3, 0x48,
+       0xf2, 0x10, 0xc6, 0xd3, 0xc4, 0xdc, 0x81, 0x43, 0x13, 0xc4, 0xf3, 0x09,
+       0xfc, 0xc1, 0xf3, 0x19, 0x42, 0x7d, 0xa7, 0x20, 0xa5, 0xf8, 0x1d, 0xc9,
+       0x92, 0x1c, 0xf7, 0x5c, 0xd5, 0x4f, 0xd2, 0x4f, 0x75, 0x74, 0x44, 0xff,
+       0x9e, 0x21, 0x0d, 0xe2, 0xd9, 0x5a, 0x56, 0x70, 0xdc, 0x4b, 0x77, 0x4b,
+       0x3d, 0x74, 0x4f, 0xed, 0x69, 0xdd, 0x15, 0x76, 0x19, 0xeb, 0xf0, 0x74,
+       0x2f, 0xdd, 0x59, 0xea, 0x20, 0xea, 0x0f, 0x8a, 0x3d, 0xe7, 0xbb, 0xa5,
+       0x32, 0xbf, 0x3f, 0x31, 0x22, 0xfd, 0x3a, 0x0d, 0x1e, 0xb9, 0xeb, 0xc1,
+       0x23, 0x1f, 0x08, 0x1e, 0xd9, 0x37, 0xb2, 0x36, 0x8f, 0xec, 0x52, 0xb6,
+       0x48, 0x90, 0x3a, 0x15, 0x7f, 0xbc, 0xc4, 0xfc, 0xf1, 0x2c, 0xf3, 0xc7,
+       0xe1, 0x36, 0xfc, 0x61, 0xb8, 0xf8, 0xe3, 0x88, 0xe0, 0x8f, 0x87, 0x46,
+       0xd6, 0xe2, 0x8f, 0xc3, 0xfe, 0xb5, 0x7c, 0x4d, 0xe2, 0xb7, 0x3c, 0x2f,
+       0xcc, 0xd9, 0xbb, 0x99, 0xd7, 0x6d, 0xaa, 0xcc, 0x23, 0x67, 0x61, 0x25,
+       0x6a, 0xd0, 0xbf, 0x08, 0x9b, 0x6c, 0x55, 0xd8, 0xfc, 0x31, 0x11, 0xc3,
+       0xba, 0x28, 0xf8, 0x8b, 0xd7, 0xff, 0x18, 0x72, 0xaa, 0xdc, 0x73, 0xd1,
+       0x4d, 0x37, 0xa3, 0x98, 0x0b, 0x53, 0xcd, 0x05, 0xae, 0x75, 0xe9, 0xfa,
+       0x90, 0x01, 0xbe, 0x7e, 0xe1, 0x03, 0xf0, 0xe8, 0x72, 0x4f, 0x20, 0x59,
+       0xf8, 0xe6, 0x08, 0xf0, 0x5f, 0x7e, 0x99, 0x1c, 0xd7, 0x03, 0x7c, 0x3d,
+       0x2c, 0x7e, 0xfb, 0x09, 0xb2, 0xf2, 0x8f, 0x88, 0x71, 0x64, 0x9e, 0xbc,
+       0x59, 0x1a, 0xa6, 0x5b, 0xa5, 0xdd, 0xb4, 0x5a, 0x1a, 0xa1, 0x37, 0x45,
+       0x2d, 0x0d, 0x99, 0x1b, 0xb9, 0x2a, 0xe6, 0xc8, 0xa0, 0x43, 0x61, 0x6e,
+       0xb3, 0xb4, 0x9b, 0x56, 0x96, 0x34, 0x7f, 0x83, 0xb7, 0xc1, 0x2f, 0xf1,
+       0x3e, 0x99, 0x2f, 0xd7, 0xca, 0x33, 0xc9, 0x26, 0x9e, 0x91, 0xf7, 0x80,
+       0x57, 0xf2, 0xad, 0xb9, 0xbe, 0xdd, 0xa1, 0x18, 0x62, 0xf5, 0x82, 0xd4,
+       0x81, 0xb8, 0x45, 0xc3, 0x9a, 0x3c, 0xe4, 0x07, 0x86, 0xfe, 0x2a, 0xaf,
+       0xb9, 0x3c, 0x67, 0x36, 0xe2, 0x9c, 0x46, 0x18, 0x0f, 0x6f, 0x17, 0xf8,
+       0x37, 0x61, 0x07, 0x22, 0x49, 0xaa, 0x5d, 0x30, 0x6c, 0xd4, 0x73, 0x4c,
+       0xf3, 0xf3, 0x0c, 0xe5, 0x6f, 0xda, 0xe6, 0xe0, 0x3f, 0x37, 0xd6, 0xc5,
+       0x5e, 0xf2, 0x63, 0xdc, 0x67, 0xac, 0xc3, 0x8d, 0xfd, 0x1a, 0xaa, 0xef,
+       0xd7, 0x74, 0xf3, 0xb8, 0xa5, 0xec, 0xcd, 0xda, 0xdc, 0xae, 0xca, 0xed,
+       0xaa, 0xd8, 0xfb, 0xe3, 0xeb, 0x4b, 0xd8, 0x77, 0x1e, 0xa6, 0xd5, 0x79,
+       0xc8, 0x28, 0xfc, 0x21, 0x8d, 0xbd, 0xde, 0xd5, 0x65, 0x5c, 0x87, 0x4f,
+       0xa4, 0xb1, 0xd7, 0xbb, 0xaa, 0xf6, 0x7a, 0x57, 0x97, 0x63, 0x42, 0x6f,
+       0xe7, 0x4b, 0x4c, 0xf7, 0x92, 0x5f, 0xc5, 0x39, 0xee, 0x53, 0xbf, 0x2d,
+       0xf4, 0x98, 0xf0, 0x69, 0xf7, 0xd9, 0x6b, 0xd3, 0xf0, 0x50, 0x0b, 0x0d,
+       0x63, 0x02, 0x67, 0xa5, 0xf8, 0x99, 0xc9, 0xd2, 0x63, 0xff, 0x3b, 0x60,
+       0x78, 0x46, 0x00, 0xf3, 0x9e, 0x30, 0x34, 0xef, 0xc1, 0xe6, 0x8e, 0xf9,
+       0x19, 0x20, 0xf7, 0x14, 0xd9, 0x80, 0xfb, 0x16, 0x90, 0xf2, 0x4a, 0x06,
+       0xad, 0xbc, 0x02, 0xa6, 0x09, 0x75, 0x88, 0xfe, 0xa6, 0xf5, 0x9f, 0xe5,
+       0x60, 0xe3, 0x80, 0x4d, 0x40, 0x73, 0x9b, 0xa7, 0x90, 0x32, 0xf7, 0x0c,
+       0xac, 0x6f, 0xb1, 0xae, 0x6d, 0xb4, 0x01, 0xef, 0xb1, 0x5e, 0x34, 0x85,
+       0x85, 0x61, 0x49, 0x0f, 0x03, 0xb0, 0x7e, 0x00, 0xa5, 0x75, 0x50, 0x1d,
+       0x01, 0x4f, 0xef, 0x02, 0x4d, 0x40, 0xf7, 0x39, 0x01, 0xdb, 0xa2, 0xce,
+       0xfd, 0xca, 0xe0, 0xb5, 0xb2, 0x0d, 0xd0, 0x73, 0xab, 0x16, 0xf5, 0x88,
+       0xc9, 0x83, 0xf2, 0x99, 0x93, 0x0a, 0x03, 0x19, 0x79, 0x81, 0x0d, 0x9a,
+       0x17, 0xc0, 0xe1, 0x04, 0x4c, 0xeb, 0xc0, 0x32, 0x6a, 0x8d, 0x2e, 0xd0,
+       0x3c, 0x1e, 0x16, 0x97, 0x7e, 0x90, 0x18, 0x03, 0x54, 0x8c, 0x05, 0xc8,
+       0x97, 0x01, 0xb6, 0x29, 0x41, 0x7e, 0x05, 0xe5, 0x05, 0x90, 0xd9, 0x20,
+       0xbf, 0x83, 0xca, 0x4e, 0x50, 0x5e, 0x04, 0xb2, 0x97, 0x08, 0x41, 0xfd,
+       0x0c, 0xa4, 0x81, 0xec, 0xe6, 0x29, 0x22, 0x60, 0x7e, 0x52, 0x80, 0x10,
+       0x43, 0x03, 0x3c, 0x1f, 0x10, 0x1b, 0xc6, 0x30, 0xf5, 0x31, 0x64, 0xe4,
+       0x1b, 0x88, 0x19, 0x88, 0x7c, 0xc3, 0xce, 0x70, 0x40, 0x00, 0x16, 0x56,
+       0xff, 0xff, 0x1f, 0x53, 0x61, 0x01, 0xa6, 0x53, 0xd0, 0x3a, 0xd6, 0xdf,
+       0xff, 0x0f, 0x88, 0xb0, 0x30, 0xb4, 0xc0, 0xd7, 0x23, 0xe6, 0xc8, 0x83,
+       0xca, 0xd0, 0x05, 0x40, 0x56, 0x1b, 0xbc, 0x4d, 0xc0, 0x02, 0xbe, 0xef,
+       0x79, 0x01, 0xc3, 0x2f, 0x60, 0x99, 0xf5, 0xff, 0xff, 0x52, 0xb8, 0x5a,
+       0x10, 0x00, 0x00, 0x19, 0x3f, 0x16, 0x21, 0xc4, 0x7d, 0x00, 0x00, 0x00 };
+
+static const u32 bnx2_COM_b09FwData[(0x0/4) + 1] = { 0x0 };
+static const u32 bnx2_COM_b09FwRodata[(0x88/4) + 1] = {
+       0x08001b68, 0x08001ba4, 0x08001ba4, 0x08001ba4, 0x08001ba4, 0x08001ba4,
+       0x08001ab4, 0x08001ba4, 0x08001b28, 0x08001ba4, 0x08001a3c, 0x08001ba4,
+       0x08001ba4, 0x08001ba4, 0x08001a48, 0x00000000, 0x08002abc, 0x08002b0c,
+       0x08002b3c, 0x08002b6c, 0x08002b9c, 0x00000000, 0x0800604c, 0x0800604c,
+       0x0800604c, 0x0800604c, 0x0800604c, 0x08006078, 0x08006078, 0x080060b8,
+       0x080060c4, 0x080060c4, 0x0800604c, 0x00000000, 0x00000000 };
+static const u32 bnx2_COM_b09FwBss[(0x88/4) + 1] = { 0x0 };
+static const u32 bnx2_COM_b09FwSbss[(0x60/4) + 1] = { 0x0 };
 
 static struct fw_info bnx2_com_fw_09 = {
-       .ver_major                      = 0x1,
-       .ver_minor                      = 0x0,
-       .ver_fix                        = 0x0,
+       .ver_major                      = 0x3,
+       .ver_minor                      = 0x4,
+       .ver_fix                        = 0x3,
 
-       .start_addr                     = 0x080000b0,
+       .start_addr                     = 0x080000b4,
 
        .text_addr                      = 0x08000000,
-       .text_len                       = 0x7c5c,
+       .text_len                       = 0x7dc0,
        .text_index                     = 0x0,
        .gz_text                        = bnx2_COM_b09FwText,
        .gz_text_len                    = sizeof(bnx2_COM_b09FwText),
 
-       .data_addr                      = 0x08007d00,
+       .data_addr                      = 0x08007e60,
        .data_len                       = 0x0,
        .data_index                     = 0x0,
        .data                           = bnx2_COM_b09FwData,
 
-       .sbss_addr                      = 0x08007d00,
-       .sbss_len                       = 0x5c,
+       .sbss_addr                      = 0x08007e60,
+       .sbss_len                       = 0x60,
        .sbss_index                     = 0x0,
        .sbss                           = bnx2_COM_b09FwSbss,
 
-       .bss_addr                       = 0x08007d60,
+       .bss_addr                       = 0x08007ec0,
        .bss_len                        = 0x88,
        .bss_index                      = 0x0,
        .bss                            = bnx2_COM_b09FwBss,
 
-       .rodata_addr                    = 0x08007c60,
+       .rodata_addr                    = 0x08007dc0,
        .rodata_len                     = 0x88,
        .rodata_index                   = 0x0,
        .rodata                         = bnx2_COM_b09FwRodata,
 };
 
 static u8 bnx2_CP_b09FwText[] = {
-       0x1f, 0x8b, 0x08, 0x08, 0x8e, 0xfc, 0x2f, 0x45, 0x00, 0x03, 0x74, 0x65,
-       0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xbd, 0x7d, 0x0d, 0x74,
-       0x5c, 0x57, 0x7d, 0xe7, 0xff, 0xdd, 0x79, 0x92, 0xc6, 0xb2, 0x2c, 0x3f,
-       0xcb, 0x63, 0x65, 0x22, 0x0b, 0x7b, 0x46, 0x7a, 0xb2, 0x95, 0x58, 0x64,
-       0xc7, 0xae, 0x00, 0x6d, 0x3b, 0x85, 0xe9, 0x48, 0xb2, 0x9d, 0x0f, 0x8a,
-       0x4c, 0x44, 0x4f, 0x5a, 0xe8, 0x22, 0xc6, 0x76, 0x48, 0x80, 0xb2, 0x4e,
-       0x09, 0x69, 0x80, 0x04, 0x0f, 0x23, 0xf9, 0x83, 0x74, 0xec, 0x51, 0x12,
-       0xc5, 0x76, 0x4f, 0x73, 0x58, 0x55, 0x92, 0x1d, 0x43, 0xa7, 0x1e, 0x27,
-       0x71, 0x68, 0xf6, 0x6c, 0x68, 0xb4, 0x4a, 0xe2, 0xa6, 0x3d, 0xd9, 0xd6,
-       0xf4, 0x84, 0x6e, 0xda, 0x43, 0x77, 0x85, 0x71, 0x88, 0x4b, 0xb3, 0x4b,
-       0xf8, 0x68, 0x61, 0xa1, 0xe5, 0xed, 0xef, 0x77, 0xef, 0x7d, 0xd2, 0xe8,
-       0xc3, 0x09, 0xa1, 0xbb, 0xf5, 0x39, 0xcf, 0x6f, 0xde, 0xfd, 0xfc, 0xdf,
-       0xff, 0xfd, 0x7f, 0xdf, 0x0f, 0xad, 0x17, 0xa9, 0x17, 0xfb, 0x6f, 0x15,
-       0x9e, 0x6d, 0x89, 0x7d, 0xbb, 0xb7, 0x5e, 0xd7, 0x73, 0x1d, 0x7e, 0x6e,
-       0x75, 0x57, 0x46, 0x95, 0xbc, 0x89, 0x7f, 0x89, 0x9f, 0xa1, 0x4c, 0x44,
-       0xc4, 0x0b, 0xfb, 0xe2, 0x23, 0x51, 0x95, 0x1e, 0xfc, 0x64, 0xd6, 0x97,
-       0x68, 0x24, 0x7d, 0xf6, 0xb3, 0xbb, 0x7d, 0x91, 0x4c, 0x79, 0x4b, 0xa2,
-       0x57, 0xfe, 0x25, 0xc8, 0xc7, 0x5c, 0x61, 0xfa, 0x5b, 0xd2, 0xff, 0xfc,
-       0x9f, 0xbe, 0xf2, 0x8e, 0xe4, 0x6b, 0xe3, 0x11, 0x89, 0x7a, 0xe9, 0x8f,
-       0x89, 0xb7, 0x49, 0xa2, 0xad, 0xe9, 0x81, 0x4f, 0x3e, 0xbc, 0xf9, 0x6f,
-       0x44, 0x1a, 0xc3, 0xb6, 0x2e, 0x07, 0x5f, 0xd9, 0x2c, 0xf9, 0x96, 0x74,
-       0x7c, 0xc8, 0x4d, 0x7b, 0xf2, 0x74, 0x45, 0x06, 0x0a, 0xc5, 0xa8, 0x44,
-       0xd2, 0x1d, 0x2f, 0xf5, 0x46, 0xf6, 0x07, 0x11, 0xdf, 0xf7, 0x7a, 0xa5,
-       0xa1, 0x27, 0xdb, 0x8d, 0xf4, 0xf2, 0x56, 0x51, 0x7e, 0x54, 0xb2, 0x15,
-       0x69, 0x50, 0xbe, 0x8f, 0x77, 0xbd, 0xa8, 0x74, 0xd2, 0xcb, 0x46, 0x5c,
-       0x29, 0x54, 0x2e, 0xac, 0x30, 0x6d, 0x96, 0xec, 0xfb, 0x6f, 0xa2, 0xe6,
-       0x8d, 0x36, 0x4b, 0x51, 0x99, 0x8d, 0xc4, 0x05, 0xfd, 0x00, 0xe6, 0x06,
-       0x19, 0x2e, 0x25, 0x24, 0x5b, 0x64, 0xbf, 0xae, 0xe4, 0x3c, 0xf6, 0xd9,
-       0x80, 0xfa, 0x2b, 0x9d, 0xe5, 0xcb, 0xb3, 0xec, 0x4b, 0x28, 0x9b, 0x40,
-       0xb9, 0x56, 0x79, 0xbc, 0x12, 0x97, 0xc7, 0x2a, 0x31, 0x79, 0xb4, 0x72,
-       0x87, 0x64, 0x50, 0xf7, 0x6c, 0x05, 0x7d, 0x97, 0x6a, 0xa5, 0x77, 0xac,
-       0x5e, 0xb2, 0x63, 0xed, 0xf1, 0x9c, 0x04, 0xc1, 0x27, 0x52, 0x1f, 0x95,
-       0xa1, 0x26, 0x94, 0x2f, 0x31, 0x2f, 0xbe, 0x20, 0x2f, 0x97, 0xda, 0xe2,
-       0xe5, 0x94, 0x23, 0x99, 0xc1, 0x64, 0x7c, 0x48, 0xf1, 0xbb, 0x46, 0xb2,
-       0x5d, 0xf8, 0x1e, 0x70, 0x25, 0xe2, 0x07, 0xc1, 0x1d, 0xa9, 0x26, 0xc0,
-       0x91, 0x4c, 0x24, 0x14, 0xeb, 0xb2, 0x5e, 0x32, 0x9f, 0x50, 0x51, 0xc9,
-       0x57, 0xae, 0x93, 0x44, 0x53, 0x10, 0xbc, 0x37, 0xe5, 0x21, 0x5d, 0xa4,
-       0xb7, 0x28, 0xfb, 0x54, 0xda, 0x47, 0x9b, 0x92, 0x52, 0xe9, 0xb5, 0x18,
-       0xc7, 0x16, 0xe0, 0xa9, 0x56, 0x32, 0x31, 0xc9, 0xa8, 0xb4, 0x24, 0x54,
-       0x7a, 0x05, 0xd2, 0x1c, 0xa9, 0xf1, 0xa7, 0x2c, 0x9d, 0xac, 0xc6, 0xb7,
-       0x0c, 0xa8, 0x74, 0xd3, 0xa2, 0xf4, 0x64, 0x42, 0xd4, 0x8f, 0xea, 0xd0,
-       0x67, 0x67, 0x46, 0x31, 0x0d, 0x6f, 0x9d, 0x76, 0xfd, 0x32, 0x69, 0x1f,
-       0x74, 0x16, 0xa6, 0x3d, 0xb5, 0x8a, 0xb0, 0x8a, 0xe2, 0xef, 0x28, 0xe0,
-       0x6a, 0x41, 0xff, 0xed, 0x5e, 0x0d, 0xc6, 0x35, 0x90, 0x4a, 0x7a, 0xfd,
-       0xea, 0xc5, 0x40, 0x9a, 0x09, 0x33, 0xf3, 0x14, 0xf2, 0x50, 0x34, 0x9d,
-       0xc2, 0xbc, 0xb9, 0x72, 0x08, 0x63, 0xbb, 0x38, 0x96, 0xf4, 0xda, 0x14,
-       0xde, 0x53, 0xfc, 0xdd, 0x34, 0x14, 0x49, 0x07, 0x41, 0x36, 0x35, 0x2e,
-       0xb9, 0x72, 0xd2, 0x9b, 0x05, 0x70, 0xbd, 0x63, 0x71, 0x8c, 0x1f, 0xe3,
-       0x88, 0x65, 0x92, 0x6b, 0xa4, 0xcb, 0xce, 0xcf, 0x5f, 0xa2, 0xef, 0x76,
-       0xef, 0x0e, 0xd5, 0xee, 0xa5, 0x54, 0xd2, 0x9b, 0x90, 0x3f, 0xc4, 0x77,
-       0x10, 0xec, 0x4a, 0x25, 0xe3, 0x79, 0xcc, 0xdd, 0xa5, 0x62, 0x4c, 0x5e,
-       0x2e, 0x26, 0x41, 0xa9, 0xc9, 0xce, 0x49, 0xd9, 0x92, 0x9a, 0x04, 0xdc,
-       0x05, 0x3c, 0x07, 0x99, 0x57, 0x46, 0x5e, 0x99, 0x75, 0x83, 0xe0, 0xe6,
-       0xd4, 0x89, 0x60, 0xa8, 0xd9, 0xd0, 0xfe, 0xd3, 0x25, 0xcc, 0x2b, 0xe6,
-       0xe9, 0xb1, 0x12, 0xe6, 0xb5, 0x84, 0x39, 0xd5, 0xf3, 0xdf, 0x89, 0xf9,
-       0x27, 0x8d, 0x90, 0x3e, 0xb6, 0x59, 0x7a, 0x7d, 0xb7, 0x7d, 0x8b, 0x64,
-       0x4b, 0x8e, 0x64, 0x53, 0x3f, 0x09, 0x32, 0x9a, 0x27, 0xc4, 0xe9, 0x2d,
-       0x91, 0x26, 0x6b, 0x00, 0x2b, 0x3f, 0x7f, 0xdd, 0x96, 0x8b, 0x3a, 0x18,
-       0x06, 0xe7, 0x83, 0xf9, 0x51, 0xe5, 0xd7, 0xd9, 0xfc, 0x90, 0xf6, 0xf9,
-       0x0f, 0x74, 0xe7, 0xcf, 0x97, 0xcb, 0x92, 0x36, 0x2b, 0x22, 0xb9, 0x07,
-       0x03, 0xe9, 0x4d, 0x01, 0x5f, 0x6c, 0xd3, 0x4b, 0x89, 0xae, 0xeb, 0xb1,
-       0x8c, 0x2e, 0x8b, 0x7f, 0x3f, 0xae, 0x41, 0x1f, 0x4e, 0x5f, 0x69, 0xbe,
-       0x6e, 0x5f, 0xe9, 0x85, 0x98, 0x85, 0x0f, 0xdf, 0x3d, 0x4e, 0xb6, 0xf2,
-       0x77, 0x76, 0x8e, 0xc3, 0x71, 0x74, 0x2d, 0x43, 0xe3, 0x2e, 0xf8, 0xc1,
-       0x93, 0x5c, 0xb1, 0x07, 0xfd, 0xc6, 0xf0, 0x0e, 0x82, 0x91, 0x54, 0x26,
-       0xe9, 0x4a, 0x1a, 0xdf, 0x03, 0x98, 0xaf, 0x0e, 0xe0, 0x4f, 0xdc, 0xec,
-       0xe6, 0x94, 0xf4, 0x55, 0x40, 0x7b, 0x95, 0x37, 0x96, 0x14, 0x7a, 0x0c,
-       0xa9, 0x7f, 0xb1, 0xb8, 0x61, 0x3f, 0x7c, 0xbb, 0x32, 0x02, 0xfa, 0x28,
-       0x8c, 0xf9, 0x32, 0x5c, 0x9c, 0xf6, 0x94, 0x24, 0x41, 0xbb, 0x69, 0xe9,
-       0xad, 0xf8, 0x52, 0x28, 0xe2, 0x5d, 0x6a, 0x07, 0xfd, 0xba, 0x92, 0x89,
-       0x9b, 0x39, 0x29, 0x14, 0x7f, 0x09, 0xe3, 0x02, 0x8e, 0x7d, 0xfe, 0xee,
-       0xb1, 0xb0, 0x80, 0xf7, 0xbb, 0x53, 0x1a, 0x3f, 0x6f, 0x0e, 0x06, 0xf6,
-       0x8d, 0x31, 0x60, 0x9c, 0x85, 0xb2, 0x8b, 0x77, 0x0c, 0xef, 0x90, 0x16,
-       0xe3, 0x80, 0xa9, 0x55, 0x86, 0x41, 0x8b, 0xbd, 0x82, 0xdf, 0x53, 0x84,
-       0x91, 0xfd, 0xb6, 0xe8, 0xdf, 0xc3, 0x63, 0x1b, 0xf4, 0x77, 0x6e, 0xa0,
-       0x45, 0xf2, 0x53, 0xe1, 0x58, 0x28, 0x0f, 0x28, 0x03, 0x92, 0x87, 0x45,
-       0x28, 0x13, 0x82, 0xe0, 0xc1, 0x14, 0xe5, 0x42, 0x10, 0x3c, 0x96, 0xa2,
-       0x9c, 0x38, 0x07, 0xfe, 0xa7, 0x6c, 0x20, 0xaf, 0xae, 0x55, 0x9c, 0x83,
-       0x6c, 0x11, 0x7d, 0x40, 0x4e, 0xe4, 0xba, 0x4e, 0x40, 0x6e, 0x50, 0xae,
-       0x5c, 0xf8, 0x44, 0xd6, 0xcf, 0xc7, 0x23, 0x1a, 0x0f, 0x98, 0x6f, 0xc8,
-       0xbc, 0x8c, 0x86, 0xbc, 0x4d, 0x0a, 0x5d, 0xa3, 0xb6, 0xcc, 0x65, 0x5d,
-       0xc6, 0x5d, 0x52, 0xe6, 0x76, 0x65, 0xf8, 0xae, 0x15, 0xf3, 0xb1, 0x42,
-       0x11, 0x4f, 0x6d, 0x9b, 0xf8, 0x2d, 0xd1, 0x9a, 0xf4, 0x97, 0x90, 0x37,
-       0x7d, 0xd7, 0x49, 0x7f, 0xb9, 0xbc, 0x59, 0x77, 0x69, 0xde, 0x88, 0xb8,
-       0x7e, 0xb2, 0x73, 0x97, 0x9a, 0x01, 0x3d, 0x05, 0xc1, 0xc9, 0x54, 0x98,
-       0xfe, 0x8f, 0xee, 0xd2, 0x3e, 0x12, 0x35, 0x4b, 0xd3, 0xee, 0x5d, 0x26,
-       0xed, 0xc4, 0x32, 0x69, 0x1b, 0x6a, 0x97, 0xa6, 0xbd, 0x7f, 0x99, 0xb4,
-       0xfb, 0x97, 0x49, 0xfb, 0x5f, 0xcb, 0xa4, 0x7d, 0x67, 0x99, 0xb4, 0xef,
-       0x2d, 0x93, 0xd6, 0x52, 0xb7, 0x34, 0xcd, 0x05, 0x3f, 0x6d, 0x92, 0x42,
-       0xec, 0x73, 0x1c, 0xbb, 0xc5, 0xcd, 0xfe, 0xc8, 0x52, 0xdc, 0xd4, 0xa0,
-       0x5c, 0xeb, 0xa2, 0x72, 0x53, 0xcb, 0x94, 0xab, 0x45, 0xb9, 0xa6, 0x45,
-       0xe5, 0x92, 0xcb, 0xe0, 0xba, 0x4e, 0xeb, 0xaf, 0x85, 0xe5, 0x0a, 0xcb,
-       0x94, 0x63, 0xfa, 0x1e, 0xdb, 0xcf, 0x16, 0x68, 0x99, 0xd7, 0x9b, 0xaf,
-       0x5a, 0x91, 0x66, 0xa6, 0xb7, 0x42, 0x47, 0xac, 0x50, 0x86, 0xdf, 0x29,
-       0x5b, 0x98, 0xe6, 0x81, 0xee, 0xa3, 0xa0, 0x3b, 0xca, 0x47, 0xf0, 0x91,
-       0x4f, 0xfe, 0x5d, 0x25, 0x43, 0xb1, 0x2d, 0xde, 0x2f, 0xa8, 0x06, 0xd0,
-       0x58, 0xd2, 0x4b, 0x28, 0xf2, 0x97, 0xe4, 0x23, 0x69, 0x3f, 0xdf, 0x2b,
-       0x2a, 0xa6, 0x24, 0x90, 0xbe, 0x94, 0x6a, 0x52, 0xb2, 0x1f, 0xfc, 0x93,
-       0x81, 0x4e, 0xda, 0x15, 0xf4, 0x6a, 0x1e, 0x32, 0x65, 0xaf, 0x2c, 0x2b,
-       0x7d, 0x39, 0x48, 0x19, 0x97, 0xce, 0xdc, 0x95, 0xf5, 0xa7, 0x7b, 0x6a,
-       0x41, 0xb3, 0x17, 0x51, 0x67, 0x07, 0x6a, 0xee, 0x2d, 0xbb, 0xd2, 0x57,
-       0xee, 0x04, 0x2f, 0x38, 0x72, 0xde, 0x5f, 0x2d, 0xe7, 0x53, 0x28, 0x5b,
-       0x89, 0xc8, 0x4c, 0xcc, 0x91, 0x19, 0x7c, 0x67, 0x53, 0xc8, 0xab, 0x84,
-       0xbc, 0xd5, 0x29, 0x07, 0x4a, 0xbe, 0x1c, 0x2e, 0xfd, 0x92, 0x0a, 0xf5,
-       0x56, 0x7f, 0x6a, 0xa5, 0x9c, 0xf6, 0x4c, 0xdb, 0x3b, 0xfc, 0x69, 0x68,
-       0x4c, 0x57, 0x2e, 0xfa, 0xc9, 0xf8, 0x8c, 0xe6, 0x89, 0x1f, 0x06, 0x7d,
-       0x68, 0x67, 0xc2, 0x4f, 0x7a, 0x7f, 0x8a, 0xef, 0xa1, 0x32, 0xed, 0x90,
-       0xf9, 0xb6, 0x86, 0xd1, 0xd6, 0xa1, 0xd2, 0x2a, 0xf9, 0xb0, 0xad, 0xbf,
-       0xdd, 0x9f, 0xee, 0x04, 0xcf, 0x79, 0xa7, 0x28, 0x23, 0x8a, 0x80, 0x6b,
-       0x10, 0xbc, 0x8d, 0xba, 0xcf, 0x69, 0x39, 0x05, 0xbb, 0xa5, 0xb8, 0x1a,
-       0x72, 0xf7, 0x1f, 0x83, 0x0f, 0xc7, 0x58, 0x9e, 0x69, 0xd4, 0x25, 0x32,
-       0xaa, 0xd2, 0x90, 0x09, 0xdd, 0x94, 0x85, 0x09, 0xc8, 0x41, 0xc8, 0x96,
-       0xd2, 0x4f, 0x83, 0x8c, 0x5b, 0x2d, 0xdf, 0x24, 0x3f, 0x5f, 0x86, 0x69,
-       0x09, 0x23, 0x2f, 0x4b, 0xb3, 0x73, 0xb2, 0x22, 0x0f, 0xf9, 0xf2, 0x74,
-       0x85, 0x72, 0xe1, 0x7a, 0xf0, 0x68, 0xab, 0xf4, 0x15, 0x93, 0xf9, 0x8c,
-       0x6c, 0xc2, 0xfc, 0x7d, 0x1e, 0x73, 0xea, 0xe2, 0xb9, 0xaf, 0x5e, 0x1a,
-       0x53, 0xd0, 0xcd, 0x4c, 0x47, 0xa3, 0xcd, 0x51, 0xc8, 0xa8, 0xdf, 0x03,
-       0x1e, 0x86, 0x39, 0xe7, 0xf1, 0x6c, 0xc4, 0x19, 0xa0, 0x3d, 0x32, 0x40,
-       0xfd, 0x50, 0x66, 0xdb, 0x84, 0x37, 0x6e, 0x7f, 0x47, 0xb5, 0x8c, 0x31,
-       0xbf, 0x1b, 0xf0, 0x3b, 0x61, 0x7f, 0x7b, 0xf8, 0xed, 0xdb, 0xdf, 0x31,
-       0xfc, 0xee, 0xb4, 0xbf, 0xa1, 0x5b, 0x8b, 0x5d, 0xfa, 0xf7, 0x48, 0x69,
-       0xfb, 0x76, 0xe5, 0x5f, 0x27, 0xb9, 0xa9, 0x56, 0x39, 0x50, 0xf4, 0xad,
-       0x6c, 0xc1, 0x23, 0x4f, 0x3a, 0x66, 0x9c, 0x80, 0x9b, 0xb2, 0xb3, 0x94,
-       0x77, 0x06, 0x08, 0x3f, 0x68, 0xa0, 0xb7, 0xb8, 0xc5, 0x5b, 0x23, 0xa4,
-       0x81, 0x11, 0xa7, 0xb7, 0xe2, 0x64, 0x60, 0xaf, 0xc5, 0x87, 0xe5, 0x30,
-       0x7e, 0x8b, 0x17, 0x49, 0x3f, 0x89, 0xb7, 0xc1, 0x01, 0xf5, 0xce, 0x70,
-       0x89, 0xf2, 0xd2, 0xc7, 0xd8, 0x13, 0x72, 0x6e, 0x81, 0x0d, 0x45, 0x5c,
-       0x28, 0xc9, 0x8d, 0x25, 0x4f, 0xe4, 0x25, 0x99, 0x1f, 0x07, 0x43, 0xec,
-       0x4a, 0xb9, 0xf2, 0xde, 0x14, 0x68, 0xf7, 0x3a, 0x47, 0xb6, 0x5f, 0xe7,
-       0xc2, 0xe6, 0xf1, 0xc7, 0xb7, 0x83, 0xfe, 0x31, 0xcf, 0x9a, 0x1e, 0xd4,
-       0x19, 0x81, 0x9d, 0x08, 0x6c, 0x9f, 0xe9, 0xea, 0x1b, 0x2e, 0xe6, 0x3e,
-       0xa6, 0xd2, 0xfb, 0x3e, 0x95, 0xed, 0xbe, 0x46, 0x72, 0x83, 0x0a, 0x38,
-       0x6a, 0x1e, 0x82, 0x1e, 0xc4, 0xb8, 0x82, 0x00, 0xf4, 0x0c, 0x79, 0x7e,
-       0xf3, 0xcd, 0x91, 0x74, 0x8d, 0xf4, 0x0e, 0x36, 0xa3, 0x0e, 0xf3, 0x88,
-       0xaf, 0xaf, 0xa2, 0x9d, 0x64, 0xa2, 0x4f, 0xe4, 0x9e, 0x91, 0xee, 0x59,
-       0x67, 0x78, 0xf4, 0x37, 0xc0, 0x93, 0x5b, 0x51, 0xff, 0x01, 0xd4, 0x7f,
-       0xcd, 0x29, 0x8c, 0xfd, 0xc8, 0x19, 0x1e, 0xfb, 0x9e, 0x33, 0x32, 0xb6,
-       0x61, 0x43, 0x7f, 0xcf, 0x86, 0x0d, 0xbb, 0x7b, 0x5c, 0x99, 0x00, 0x8f,
-       0x65, 0xbc, 0x0d, 0x1b, 0x46, 0x7a, 0xba, 0x80, 0x83, 0x2d, 0x5e, 0x9f,
-       0xf8, 0xde, 0x76, 0x01, 0xff, 0xc4, 0xd8, 0x67, 0x14, 0xf9, 0x49, 0xe4,
-       0xb3, 0x7e, 0x5c, 0xe7, 0xf7, 0xca, 0x96, 0x78, 0x93, 0xb0, 0xff, 0x88,
-       0x2d, 0x53, 0x13, 0x91, 0xfa, 0x07, 0xec, 0xfc, 0x66, 0x9c, 0x1a, 0x9f,
-       0xe9, 0x1c, 0x0b, 0xd3, 0x39, 0xb7, 0x7f, 0x67, 0x6d, 0xd5, 0xd5, 0x48,
-       0xe7, 0x37, 0x71, 0x46, 0xbc, 0xd0, 0xc6, 0xa8, 0xd1, 0xb6, 0x61, 0xae,
-       0x48, 0x9a, 0x71, 0x65, 0x4f, 0xd1, 0x41, 0x1d, 0xd0, 0xc5, 0x19, 0xfb,
-       0x1c, 0x05, 0x6c, 0x83, 0x68, 0xeb, 0xe8, 0x21, 0xd4, 0xa3, 0xcc, 0x48,
-       0x76, 0x8a, 0xfa, 0x00, 0xca, 0x6c, 0xf1, 0xd6, 0x0a, 0x6d, 0x89, 0x3b,
-       0x25, 0x57, 0x22, 0x7f, 0x77, 0x00, 0x9e, 0xa8, 0x24, 0x9a, 0xf1, 0x5d,
-       0x81, 0x4d, 0xf1, 0x60, 0x8d, 0x58, 0xdb, 0x45, 0xe6, 0x6d, 0x91, 0x3b,
-       0x94, 0xc0, 0xde, 0x18, 0x9a, 0x5c, 0x8f, 0x72, 0x0e, 0xf0, 0x42, 0xfb,
-       0x03, 0xb4, 0x36, 0x99, 0x91, 0xec, 0x26, 0xf0, 0xc9, 0xa4, 0x87, 0x6f,
-       0xc0, 0x35, 0xf9, 0x16, 0xbc, 0x23, 0xfa, 0xdb, 0xc0, 0x09, 0xbc, 0xa6,
-       0x22, 0x56, 0x67, 0x75, 0xa1, 0xef, 0xf7, 0x48, 0x76, 0x34, 0x4e, 0x5b,
-       0x62, 0x75, 0xd6, 0xcf, 0x40, 0xd7, 0x2b, 0x28, 0x41, 0x8c, 0x61, 0xd2,
-       0x81, 0x3c, 0xa9, 0x95, 0xdd, 0x8f, 0xe0, 0xf7, 0x83, 0xc6, 0xe6, 0xdd,
-       0x3d, 0xc9, 0x7e, 0x1a, 0x00, 0x13, 0x6c, 0x90, 0x47, 0x60, 0x9b, 0x3e,
-       0x02, 0x1b, 0xe4, 0x91, 0x66, 0x3c, 0x1c, 0x1b, 0xdb, 0x9f, 0x59, 0x03,
-       0x31, 0xa9, 0xbf, 0x73, 0xa4, 0x57, 0xd8, 0xea, 0xb9, 0x62, 0xca, 0x94,
-       0x2f, 0x76, 0xeb, 0xb7, 0xa1, 0xeb, 0x1e, 0xfb, 0x3b, 0xae, 0xf9, 0x3a,
-       0xdf, 0x04, 0x9a, 0xaf, 0x74, 0x69, 0x99, 0x93, 0xf5, 0xf1, 0x86, 0xcd,
-       0x99, 0x69, 0xe2, 0x18, 0xe3, 0x36, 0x2d, 0xae, 0xd3, 0x12, 0x4d, 0xd6,
-       0xde, 0x28, 0x59, 0x5b, 0x03, 0xb8, 0x19, 0x6a, 0x06, 0xc4, 0x94, 0xcf,
-       0x12, 0xe2, 0x93, 0x32, 0x00, 0xf4, 0x0b, 0x9b, 0xe2, 0xdc, 0x15, 0xe5,
-       0xdf, 0xac, 0xb6, 0xb1, 0xce, 0x56, 0x48, 0xc7, 0xa4, 0xed, 0x20, 0xb8,
-       0x3f, 0x55, 0x87, 0xf6, 0xc9, 0xf3, 0xb0, 0x40, 0x8e, 0x02, 0x26, 0x60,
-       0xa2, 0xc6, 0x3f, 0xab, 0x69, 0xa0, 0xd6, 0x27, 0x0d, 0x57, 0xf3, 0x97,
-       0xe8, 0xf1, 0x9e, 0x05, 0x8f, 0xc1, 0xbe, 0x81, 0xfd, 0xd6, 0x01, 0xdb,
-       0x98, 0x7d, 0x1c, 0xe6, 0xb7, 0xa7, 0xc0, 0x53, 0xd9, 0x39, 0x9e, 0x12,
-       0x99, 0x28, 0x12, 0x37, 0xa1, 0x5d, 0xc7, 0x79, 0x26, 0x7e, 0x32, 0x18,
-       0x33, 0xdf, 0x7d, 0x16, 0x4f, 0x3b, 0x2d, 0x9e, 0x6e, 0xb2, 0xef, 0x11,
-       0xbc, 0x69, 0xe3, 0x0d, 0xe0, 0xcd, 0xf9, 0x19, 0xc4, 0x9b, 0xbc, 0x75,
-       0x0b, 0xde, 0x28, 0x5b, 0xca, 0xc8, 0x6e, 0x6d, 0x87, 0x45, 0xe4, 0x57,
-       0xb4, 0x6c, 0xfb, 0x02, 0xe6, 0xb2, 0x48, 0xfa, 0x95, 0x7c, 0x2c, 0x02,
-       0x9c, 0x14, 0xf0, 0xfb, 0x4e, 0xd7, 0xd0, 0x2a, 0x71, 0xb2, 0xc0, 0x57,
-       0xaa, 0x82, 0x29, 0x66, 0xe5, 0x5c, 0x42, 0xdb, 0xfa, 0xb9, 0xe2, 0x07,
-       0x34, 0x5c, 0xb7, 0x42, 0xde, 0xe5, 0x45, 0x35, 0x43, 0x37, 0x80, 0x16,
-       0x54, 0x0c, 0x9a, 0x2b, 0x78, 0x06, 0x7a, 0x29, 0x37, 0x49, 0xdb, 0xb8,
-       0x8d, 0x7e, 0x49, 0x34, 0xd7, 0xd5, 0x48, 0x3a, 0x52, 0x0a, 0xf6, 0x17,
-       0xbe, 0x55, 0xae, 0x4b, 0xd3, 0xa9, 0xa3, 0xfc, 0x98, 0xb6, 0x7f, 0x5d,
-       0x1f, 0xd2, 0xd6, 0xf8, 0xbd, 0xae, 0xf2, 0xd7, 0x2e, 0x4e, 0x4b, 0x50,
-       0x0f, 0xa3, 0x5e, 0x22, 0xd7, 0xd5, 0x4c, 0x1e, 0xf3, 0x40, 0xbf, 0x19,
-       0xe5, 0x6b, 0xdf, 0x27, 0xaf, 0xba, 0x57, 0x2f, 0x2a, 0xaf, 0xdf, 0x8e,
-       0xfd, 0x76, 0xed, 0xdb, 0xb3, 0xef, 0x84, 0x7d, 0xe7, 0xdd, 0x6e, 0xbe,
-       0x1d, 0x71, 0xd3, 0x7c, 0x83, 0x92, 0xd3, 0x6c, 0x43, 0xf3, 0x95, 0x95,
-       0x33, 0x1d, 0x5e, 0x41, 0xc8, 0x57, 0x9f, 0x93, 0x5b, 0x27, 0x8d, 0xfc,
-       0xdd, 0x0e, 0x19, 0x04, 0xff, 0xcc, 0x9b, 0x11, 0xc0, 0x3f, 0x98, 0x96,
-       0x5b, 0x2b, 0xc4, 0xdb, 0xef, 0x02, 0x7f, 0x60, 0xe2, 0x7a, 0xea, 0x74,
-       0xca, 0xdd, 0x3b, 0x61, 0xf7, 0xa2, 0x7c, 0x91, 0x38, 0x1f, 0xd2, 0x73,
-       0x53, 0x28, 0xee, 0xd1, 0x73, 0x73, 0xb0, 0x38, 0x03, 0xfc, 0xdc, 0x06,
-       0xba, 0x0f, 0x82, 0x99, 0x54, 0x01, 0x94, 0xf3, 0x11, 0xfc, 0x86, 0x1d,
-       0x50, 0xfc, 0x18, 0xf2, 0x1b, 0xa5, 0x30, 0x4a, 0x9e, 0x73, 0x2d, 0x0f,
-       0xbf, 0x13, 0xfc, 0x14, 0x45, 0xbb, 0x48, 0xeb, 0xe6, 0xef, 0x9f, 0x20,
-       0x0f, 0xef, 0x49, 0x4c, 0x62, 0x33, 0x6d, 0x1d, 0xf6, 0xcd, 0xb9, 0xe3,
-       0x9c, 0xc5, 0xb4, 0x2c, 0x3f, 0x3b, 0x37, 0x6f, 0x97, 0xe7, 0xe8, 0x36,
-       0x4f, 0x1f, 0x8f, 0xf9, 0x1a, 0x56, 0xd2, 0xfd, 0xb7, 0xb4, 0x5c, 0x72,
-       0x8f, 0xce, 0xac, 0x30, 0xef, 0xc5, 0x75, 0x39, 0xe7, 0xd5, 0x34, 0x48,
-       0xbf, 0x25, 0xd9, 0x93, 0x07, 0x3f, 0x61, 0x9c, 0xd2, 0xa7, 0x7d, 0x1d,
-       0xd2, 0x04, 0x69, 0x60, 0xdc, 0xd2, 0xe6, 0x94, 0xa5, 0xcd, 0x27, 0xf1,
-       0xc6, 0x53, 0xba, 0x60, 0x69, 0xf3, 0x29, 0xbc, 0xf1, 0x94, 0x5e, 0x9c,
-       0xe3, 0xe3, 0x5e, 0xf8, 0x72, 0xdb, 0xa1, 0xdf, 0x76, 0x57, 0x40, 0xbf,
-       0xe0, 0xbb, 0x1c, 0x7c, 0x80, 0x5c, 0x69, 0x1f, 0xde, 0xec, 0x67, 0xa3,
-       0x6d, 0x3f, 0x23, 0x7b, 0x4a, 0x01, 0xc6, 0x78, 0x37, 0xc6, 0xfb, 0x39,
-       0xbc, 0x3f, 0xa3, 0xe5, 0x8c, 0xf2, 0x0f, 0x5b, 0x79, 0xf5, 0x79, 0xbc,
-       0xdb, 0xe3, 0x07, 0xa5, 0xdd, 0x8b, 0xc8, 0x34, 0xda, 0xfa, 0xba, 0xec,
-       0xa9, 0xcc, 0xe2, 0xb9, 0x84, 0xe7, 0x55, 0x3c, 0x97, 0xd1, 0xde, 0x0b,
-       0x48, 0x5f, 0x29, 0xd3, 0x5e, 0x3d, 0xca, 0xbf, 0x86, 0xdf, 0xcf, 0xcb,
-       0xd0, 0x23, 0x2f, 0xe1, 0xf9, 0x01, 0xf2, 0x9f, 0x45, 0xfd, 0x60, 0xf5,
-       0x8c, 0x4f, 0x19, 0xf6, 0x9c, 0x6d, 0x3b, 0xe5, 0xe4, 0x2a, 0xa0, 0xe9,
-       0xd2, 0x00, 0xfa, 0xde, 0xa3, 0x79, 0xa6, 0x0f, 0x32, 0x3f, 0x07, 0x19,
-       0x37, 0xa4, 0x61, 0x6a, 0x07, 0x7c, 0x79, 0xcc, 0x05, 0xde, 0x93, 0xb5,
-       0x32, 0x1b, 0xa3, 0x1d, 0x79, 0x93, 0x2e, 0x9f, 0x2b, 0x35, 0x69, 0xbb,
-       0x7a, 0x7c, 0x09, 0xff, 0xd0, 0xef, 0x0a, 0xe5, 0x81, 0x91, 0xc6, 0x13,
-       0x45, 0xca, 0x02, 0xe8, 0x9f, 0xe2, 0x08, 0xde, 0xb5, 0x5a, 0x26, 0x14,
-       0x24, 0x94, 0x07, 0xac, 0x47, 0x99, 0x50, 0x2d, 0x77, 0x28, 0x6b, 0x28,
-       0x7b, 0x28, 0x4b, 0xcc, 0x7c, 0xec, 0x7e, 0x90, 0x32, 0x1c, 0xb4, 0x10,
-       0xa3, 0xfd, 0xe1, 0x19, 0x1f, 0x64, 0xec, 0x3e, 0x2b, 0x4f, 0x47, 0xf5,
-       0x5c, 0xec, 0x29, 0xaa, 0x98, 0x2b, 0xa7, 0x91, 0x86, 0xe7, 0xf8, 0xc3,
-       0x78, 0x7f, 0x49, 0xf6, 0xe0, 0xc9, 0x1d, 0xff, 0x02, 0x7e, 0x73, 0x6e,
-       0xca, 0x28, 0x87, 0xa7, 0x74, 0x02, 0x6f, 0x3c, 0xa5, 0x31, 0x2b, 0x47,
-       0xc6, 0xad, 0x1c, 0xe1, 0x9c, 0xde, 0x04, 0x3c, 0x70, 0x7c, 0x4a, 0xc7,
-       0x17, 0xc0, 0xcf, 0x4e, 0x6e, 0xf2, 0x5d, 0xd6, 0x8f, 0x6d, 0x14, 0xc3,
-       0x83, 0x78, 0x3a, 0xc9, 0xcf, 0x0d, 0xda, 0x0e, 0xce, 0x69, 0xda, 0xfd,
-       0x2b, 0xd7, 0xf0, 0x62, 0xcc, 0xe8, 0x14, 0xaf, 0x59, 0x34, 0xef, 0xcf,
-       0xe1, 0x31, 0x63, 0xf1, 0xc8, 0xdf, 0xca, 0xfe, 0x86, 0xdc, 0x82, 0x4d,
-       0x9b, 0xf5, 0x7d, 0xcc, 0x03, 0xc6, 0x72, 0x7c, 0x14, 0x7d, 0x3b, 0xb2,
-       0xdb, 0xa7, 0x0c, 0x67, 0x0c, 0x81, 0xe3, 0x63, 0xbb, 0x48, 0xd7, 0x38,
-       0x48, 0xc9, 0xbc, 0x6f, 0x7e, 0x13, 0xe6, 0x2c, 0x23, 0x7b, 0x4b, 0xf7,
-       0x6a, 0x5f, 0xb9, 0xf6, 0x68, 0x93, 0xf5, 0x73, 0xc2, 0x72, 0xa0, 0xd5,
-       0x18, 0x6d, 0x9b, 0x2f, 0xc5, 0x0c, 0xcd, 0xf3, 0x37, 0xe5, 0x73, 0xb5,
-       0xbc, 0x37, 0x76, 0x4d, 0x61, 0x81, 0xac, 0xa3, 0x6d, 0x81, 0x39, 0x2b,
-       0x57, 0xe3, 0x9d, 0xbe, 0x3b, 0xf9, 0x8a, 0xfc, 0x74, 0x10, 0x3c, 0xf1,
-       0x5d, 0xcb, 0xfb, 0xf4, 0x35, 0xd8, 0xe7, 0x62, 0x7e, 0xf2, 0x60, 0xfb,
-       0xba, 0x72, 0x0a, 0xb6, 0xdb, 0xf6, 0xb9, 0x36, 0xae, 0x06, 0x3c, 0x51,
-       0x79, 0xa4, 0xd8, 0x20, 0x93, 0x45, 0xd5, 0x1c, 0xb1, 0xb2, 0x33, 0x22,
-       0x09, 0x4d, 0xdf, 0xb4, 0xef, 0x7a, 0xc7, 0x22, 0x96, 0xee, 0xd6, 0xd5,
-       0x48, 0xfd, 0xef, 0x42, 0xc7, 0xa6, 0xa1, 0x63, 0x1b, 0xa1, 0x83, 0x17,
-       0xcb, 0x88, 0x35, 0x35, 0x4b, 0x65, 0x04, 0xeb, 0x24, 0xe1, 0x75, 0x1f,
-       0x44, 0xbd, 0x90, 0xfe, 0xa2, 0x9a, 0xd6, 0x72, 0x92, 0x77, 0xb6, 0x57,
-       0x46, 0x9c, 0x1d, 0x95, 0xc5, 0x3a, 0x68, 0x8b, 0xe7, 0x8a, 0x81, 0xf5,
-       0x91, 0x22, 0x6d, 0xd4, 0x64, 0x2a, 0x0b, 0x9c, 0xec, 0x00, 0xcc, 0xcf,
-       0x8c, 0xc2, 0x4f, 0xa7, 0x5c, 0x06, 0xcc, 0xa7, 0x01, 0xf3, 0xc4, 0xa8,
-       0x13, 0xda, 0x06, 0xc2, 0xa0, 0xc8, 0xc4, 0x58, 0x97, 0xcc, 0x4c, 0x91,
-       0x0e, 0x21, 0x03, 0x46, 0x31, 0x9f, 0xa9, 0x15, 0xb0, 0x03, 0xd8, 0x3f,
-       0xe4, 0xf6, 0x58, 0x8b, 0xce, 0x33, 0xfa, 0xbc, 0x55, 0x66, 0xca, 0x69,
-       0x0b, 0xdb, 0xe1, 0x2a, 0xd8, 0x56, 0xcc, 0xc1, 0xb6, 0x03, 0xb0, 0xed,
-       0x5c, 0x16, 0xb6, 0xe5, 0x74, 0x71, 0x1b, 0x6c, 0x1a, 0xa3, 0x8b, 0x0d,
-       0x5e, 0x9b, 0x2d, 0x3d, 0xbc, 0xdf, 0xda, 0xbb, 0xb4, 0x89, 0x7e, 0x0a,
-       0x78, 0x48, 0x63, 0xf8, 0x3d, 0x79, 0x2f, 0x65, 0x19, 0xd2, 0xf9, 0xbd,
-       0x07, 0x65, 0xf0, 0x3d, 0xf9, 0x67, 0x2b, 0x4c, 0xd9, 0xbb, 0x2d, 0x2c,
-       0xb4, 0x13, 0x32, 0xb0, 0x89, 0xfb, 0x9c, 0xec, 0x24, 0x61, 0xf8, 0x8f,
-       0x80, 0x17, 0x79, 0x95, 0xea, 0x36, 0xf9, 0x66, 0xbb, 0xd7, 0xda, 0x76,
-       0xd8, 0x76, 0x38, 0x96, 0x95, 0x56, 0xcf, 0x87, 0xf4, 0x15, 0xda, 0xd7,
-       0x23, 0x4e, 0x66, 0xc9, 0xb8, 0xaa, 0x69, 0x8e, 0xf2, 0xd6, 0x95, 0x7e,
-       0xd0, 0x49, 0xff, 0x02, 0x5a, 0x33, 0x72, 0xc3, 0xd0, 0xf1, 0x0a, 0x3b,
-       0xbe, 0x1a, 0xc3, 0x37, 0xa9, 0x28, 0xf4, 0x21, 0xe5, 0xcd, 0x0e, 0xe3,
-       0x9b, 0xcb, 0x43, 0x80, 0x35, 0xfc, 0x3e, 0xa8, 0x6d, 0xce, 0xa7, 0x4b,
-       0x94, 0x49, 0xf3, 0xb4, 0x68, 0x7c, 0x97, 0x56, 0xf4, 0x55, 0x6d, 0xaf,
-       0xbb, 0x32, 0x60, 0xe6, 0xfc, 0x30, 0xe7, 0x9c, 0xbe, 0x48, 0xfb, 0x03,
-       0x03, 0x96, 0xbf, 0x92, 0xa3, 0x79, 0x79, 0xbb, 0x1d, 0xfb, 0x1f, 0x2e,
-       0x33, 0x77, 0x8d, 0x73, 0x73, 0x37, 0x50, 0x59, 0x3c, 0x46, 0x91, 0xb6,
-       0x07, 0x58, 0xcf, 0x85, 0x8d, 0x94, 0x92, 0x5a, 0x9f, 0xf2, 0x93, 0xb6,
-       0x12, 0xd2, 0x27, 0xb6, 0x78, 0x4d, 0xf0, 0x01, 0x9e, 0x5e, 0x62, 0x77,
-       0x25, 0xac, 0xdc, 0xa4, 0x1f, 0x1c, 0xf6, 0x91, 0xb7, 0x72, 0x32, 0x8f,
-       0xf6, 0x47, 0x9c, 0xfe, 0xca, 0x72, 0xf2, 0x32, 0x94, 0x93, 0x1c, 0x8f,
-       0x23, 0x77, 0x3c, 0x48, 0x1e, 0x7d, 0xbf, 0xb6, 0xaf, 0xb7, 0x6e, 0xab,
-       0x01, 0xfe, 0x08, 0xc7, 0xcc, 0x1a, 0xa2, 0x33, 0xf7, 0x08, 0x6c, 0x22,
-       0x3b, 0x6f, 0xbb, 0xe7, 0xe6, 0x5f, 0xd3, 0x05, 0x7e, 0x33, 0x8e, 0x6a,
-       0x68, 0xa4, 0xc6, 0x77, 0x34, 0x2d, 0xd4, 0x2e, 0xb1, 0x65, 0x39, 0x06,
-       0xda, 0xb3, 0xb5, 0xc6, 0x16, 0x2c, 0xd1, 0xfe, 0xa4, 0xec, 0xa2, 0xfd,
-       0xf9, 0x43, 0xe0, 0x88, 0xe3, 0xe9, 0xb2, 0x69, 0xb4, 0x53, 0x17, 0x8f,
-       0x6f, 0xb1, 0xff, 0x48, 0x38, 0x09, 0xb7, 0xa1, 0xad, 0x84, 0x22, 0x6c,
-       0x81, 0x0c, 0x80, 0x97, 0x39, 0x07, 0x8a, 0xb6, 0xeb, 0xb6, 0xbf, 0xa8,
-       0x31, 0x31, 0xe4, 0xd5, 0xb5, 0x52, 0xcf, 0x3e, 0xc9, 0x7f, 0x7c, 0xaf,
-       0xd2, 0xf6, 0xef, 0x52, 0x59, 0x56, 0xad, 0x7b, 0xae, 0x9e, 0xc3, 0x5f,
-       0xff, 0x82, 0x39, 0x0a, 0xf1, 0x17, 0xd2, 0x45, 0x35, 0x0e, 0x49, 0x13,
-       0x86, 0x16, 0x0c, 0x2d, 0x6e, 0xb4, 0xfa, 0x26, 0xa4, 0xbd, 0xab, 0x40,
-       0x7b, 0xf7, 0x81, 0xc6, 0x28, 0xc3, 0x19, 0x97, 0x5b, 0x8b, 0xef, 0x23,
-       0xf8, 0x0e, 0xf9, 0xe4, 0x4a, 0x32, 0x9c, 0xf2, 0x9b, 0x75, 0xb2, 0x56,
-       0xee, 0x87, 0x7e, 0x2e, 0xeb, 0x70, 0xdc, 0x94, 0xff, 0xff, 0x15, 0xed,
-       0xac, 0xad, 0x35, 0xf6, 0xca, 0x8d, 0xb5, 0x94, 0xaf, 0x6b, 0xe4, 0x60,
-       0x55, 0xda, 0x95, 0xe4, 0x77, 0xf5, 0x98, 0xd7, 0xff, 0x3f, 0x18, 0x73,
-       0x7c, 0xd1, 0x98, 0x3d, 0x3b, 0xe6, 0x77, 0x21, 0xbf, 0xc9, 0xf8, 0x38,
-       0x1e, 0xf9, 0x2e, 0x1c, 0xb3, 0xc5, 0x85, 0x1e, 0x57, 0xb5, 0x9c, 0x08,
-       0x65, 0x04, 0xc7, 0x35, 0x60, 0xc7, 0xf0, 0xb9, 0xaa, 0x71, 0x0d, 0xbc,
-       0x89, 0x71, 0xb5, 0x2e, 0x18, 0xd7, 0xf6, 0x2b, 0x8e, 0x6b, 0x39, 0x1e,
-       0x27, 0x2f, 0x87, 0xe3, 0x8b, 0xca, 0xae, 0x22, 0xc7, 0xd8, 0x8f, 0x31,
-       0x1e, 0xd4, 0xfe, 0x80, 0x19, 0x63, 0xda, 0x8e, 0x51, 0x54, 0xdb, 0xb6,
-       0x7f, 0x8f, 0xdf, 0xd5, 0xe3, 0xa3, 0xee, 0xff, 0x3e, 0x68, 0xba, 0x4e,
-       0xb2, 0x5d, 0x75, 0x56, 0xfe, 0xdf, 0x24, 0x1f, 0x2e, 0x71, 0xae, 0x93,
-       0x19, 0x91, 0x51, 0xe8, 0xe0, 0xff, 0x5c, 0xcb, 0xd8, 0xfd, 0xf6, 0x94,
-       0xd5, 0x63, 0xd0, 0x17, 0x3b, 0x60, 0xf3, 0xf5, 0x17, 0x55, 0x77, 0x44,
-       0x82, 0xe0, 0xb6, 0xd4, 0xa7, 0xd1, 0xf7, 0x7e, 0xed, 0xab, 0x2e, 0x8d,
-       0x9b, 0x3f, 0x57, 0x2b, 0x3e, 0xed, 0x0d, 0xea, 0x73, 0xe8, 0xbb, 0xe3,
-       0xb4, 0xc1, 0xb2, 0xb0, 0x93, 0x33, 0xf1, 0x88, 0xb6, 0xc5, 0xa8, 0x13,
-       0x93, 0xf1, 0x8c, 0xa4, 0xd1, 0x5f, 0x26, 0xae, 0x84, 0x7d, 0xc0, 0x56,
-       0x83, 0x0d, 0xf9, 0xe1, 0xca, 0x3e, 0x3c, 0x0f, 0xcb, 0xad, 0xb0, 0x77,
-       0x6e, 0x7d, 0xe4, 0x0b, 0x72, 0x1b, 0x6c, 0x9d, 0xdb, 0x1e, 0x19, 0x93,
-       0xbd, 0xb0, 0x6d, 0xf6, 0xc2, 0xce, 0xd9, 0x5b, 0xa1, 0xed, 0x39, 0x8e,
-       0xb2, 0xad, 0x55, 0xb4, 0x46, 0x1b, 0x87, 0xe3, 0x23, 0xee, 0x0f, 0x72,
-       0x0e, 0x52, 0x09, 0xf5, 0x8a, 0x9e, 0x97, 0xa6, 0x05, 0x69, 0xaf, 0x27,
-       0xab, 0x42, 0xfd, 0xb4, 0xca, 0xc6, 0x8d, 0x8c, 0x0d, 0x78, 0x65, 0xda,
-       0x22, 0x8d, 0x78, 0xc0, 0x33, 0xf1, 0x47, 0xda, 0xaa, 0x1e, 0x7f, 0x63,
-       0x9d, 0xf8, 0x2b, 0xeb, 0xa4, 0xfe, 0x73, 0x90, 0xaf, 0xd5, 0x34, 0xc5,
-       0xb7, 0x67, 0x75, 0x0d, 0x69, 0x8b, 0x32, 0x38, 0xa4, 0x87, 0x8d, 0xaf,
-       0x23, 0x7f, 0xaf, 0x48, 0x4f, 0xfb, 0xb9, 0x2e, 0xb3, 0xbb, 0x5b, 0x56,
-       0x33, 0x1e, 0x90, 0xad, 0xcc, 0xc7, 0x04, 0x94, 0x5f, 0x1d, 0x13, 0xa0,
-       0x9f, 0xf5, 0x01, 0xe0, 0xec, 0x16, 0x3c, 0xfb, 0x64, 0x88, 0x71, 0x87,
-       0x4a, 0x68, 0x97, 0x7f, 0xd5, 0xda, 0xe5, 0x21, 0x1c, 0x09, 0xc0, 0x61,
-       0xe4, 0xf3, 0x52, 0x3d, 0xb7, 0x50, 0x7f, 0xe7, 0xe7, 0x6c, 0xda, 0x84,
-       0xec, 0x2a, 0x71, 0xdc, 0x94, 0xc1, 0xc4, 0x4d, 0xb5, 0x0c, 0x8e, 0x5b,
-       0x3b, 0x0a, 0x65, 0xb4, 0xfc, 0x5c, 0x2a, 0x3b, 0x29, 0xf7, 0x18, 0x9f,
-       0x7f, 0x20, 0x45, 0x5a, 0x7f, 0xb7, 0x64, 0xe6, 0xe2, 0xf3, 0x02, 0x7a,
-       0x93, 0x54, 0x24, 0xad, 0xd7, 0xd3, 0xbc, 0x09, 0xd9, 0x21, 0xbd, 0x31,
-       0xc6, 0x3a, 0x19, 0xcf, 0xf3, 0xf3, 0x13, 0xb0, 0x1f, 0x86, 0x4b, 0x0a,
-       0x16, 0x7c, 0xad, 0x0c, 0x79, 0x81, 0x6c, 0x4f, 0x39, 0x3a, 0x76, 0x6c,
-       0x74, 0x6d, 0xa9, 0xce, 0xd8, 0xae, 0x8e, 0x8e, 0xff, 0xce, 0x80, 0xfa,
-       0x66, 0xb4, 0x7d, 0xab, 0xb4, 0xfe, 0x9d, 0xd6, 0x65, 0x46, 0xeb, 0xc2,
-       0x38, 0xe6, 0x8c, 0x17, 0xb1, 0xe5, 0xaa, 0xd3, 0xa7, 0xea, 0x42, 0x5b,
-       0xb0, 0x50, 0x09, 0xd3, 0x9e, 0x5c, 0x26, 0xed, 0x85, 0x65, 0xd2, 0xfe,
-       0x76, 0x99, 0x34, 0x13, 0x17, 0xec, 0x2f, 0x5e, 0x46, 0xde, 0x88, 0xe6,
-       0x55, 0x69, 0x36, 0xf6, 0x75, 0x7e, 0xae, 0xcc, 0x2a, 0xeb, 0x97, 0x31,
-       0x46, 0x6c, 0x62, 0xc3, 0x39, 0x1d, 0x1b, 0xde, 0xe2, 0x6d, 0x53, 0x8c,
-       0x75, 0x11, 0x17, 0x09, 0xd9, 0xab, 0xf1, 0x42, 0x9c, 0x7c, 0x85, 0x31,
-       0xe0, 0x3c, 0xd7, 0x5a, 0x13, 0xea, 0x4a, 0xb4, 0x3d, 0x6f, 0x9b, 0x98,
-       0x79, 0x8b, 0xe9, 0x75, 0xd5, 0x3e, 0xd8, 0x0a, 0xfd, 0xc5, 0x26, 0xd9,
-       0x3e, 0x96, 0x58, 0x41, 0xbd, 0xb5, 0x63, 0xcc, 0xf8, 0x83, 0x7b, 0xc1,
-       0x57, 0x19, 0x21, 0x8c, 0xc9, 0x94, 0x08, 0x6d, 0xe2, 0xa5, 0xb6, 0xf0,
-       0xeb, 0xb7, 0xd7, 0x7b, 0x85, 0xf6, 0x1c, 0xd8, 0x0e, 0x3f, 0x6b, 0x7b,
-       0xf5, 0xd2, 0x37, 0x16, 0xe2, 0x4a, 0xfd, 0x9c, 0xf5, 0x22, 0x57, 0xa8,
-       0xa7, 0xed, 0x12, 0x79, 0x66, 0x4e, 0x16, 0x6f, 0x84, 0xcd, 0x24, 0x41,
-       0xb6, 0x5b, 0x5a, 0x23, 0xa2, 0x63, 0x3c, 0x29, 0x23, 0x9b, 0x3b, 0xb8,
-       0xb6, 0x03, 0xfa, 0x37, 0xb6, 0x8a, 0x89, 0x9b, 0x86, 0x76, 0xca, 0x72,
-       0xb4, 0x7b, 0xbd, 0xa5, 0x5d, 0xae, 0xa9, 0xee, 0xa0, 0xcc, 0xc5, 0x9c,
-       0x18, 0x3a, 0xde, 0x5e, 0x94, 0x44, 0x48, 0xc7, 0x33, 0xf0, 0x8b, 0xab,
-       0xe9, 0x78, 0x46, 0x52, 0x9a, 0x8e, 0x6b, 0x17, 0xd0, 0x71, 0xab, 0xa5,
-       0xe3, 0x77, 0x44, 0x0d, 0x5d, 0x28, 0xad, 0xa7, 0x48, 0xa7, 0x86, 0x8e,
-       0x1d, 0x4d, 0xc7, 0x33, 0x78, 0xbb, 0x7e, 0x8f, 0x2d, 0x13, 0xb1, 0x69,
-       0xfc, 0x1d, 0xa6, 0x51, 0x2e, 0xfe, 0x66, 0xd4, 0xe8, 0xa5, 0x14, 0xe8,
-       0x28, 0x4c, 0xff, 0x60, 0xd4, 0xd0, 0x67, 0x75, 0x9a, 0x89, 0x8f, 0xf4,
-       0x17, 0xdf, 0x13, 0x5d, 0x48, 0x9f, 0x29, 0xd0, 0x67, 0x58, 0xe6, 0xf5,
-       0xe8, 0xb3, 0xde, 0xae, 0x5b, 0x44, 0xf5, 0xba, 0x7b, 0x26, 0x66, 0x68,
-       0xf5, 0x56, 0x3d, 0x76, 0x8e, 0xfb, 0xd9, 0x9f, 0x81, 0x56, 0xcd, 0xdc,
-       0x9c, 0x9f, 0xf7, 0xb7, 0x19, 0x8b, 0x4a, 0x98, 0x18, 0x36, 0xe3, 0xa4,
-       0x57, 0xb2, 0x1d, 0x8d, 0x7c, 0xaa, 0xd1, 0xf2, 0xa9, 0x71, 0x48, 0xa5,
-       0xab, 0x65, 0x76, 0x37, 0x74, 0x05, 0x6d, 0x6c, 0x2d, 0xa7, 0x91, 0xd7,
-       0x9a, 0xc8, 0x16, 0xff, 0xd9, 0xee, 0x5f, 0xe0, 0xba, 0x80, 0x0c, 0x39,
-       0x48, 0x6b, 0x2b, 0x9b, 0x71, 0x29, 0xbf, 0x11, 0xdf, 0xdd, 0xd2, 0x56,
-       0x56, 0x72, 0xfb, 0x58, 0x83, 0xec, 0x2b, 0xba, 0xf2, 0x51, 0xd4, 0xff,
-       0x48, 0xd1, 0x83, 0x3f, 0x3e, 0x1e, 0xa5, 0x5d, 0xb8, 0xb7, 0xc8, 0xf5,
-       0x49, 0xc7, 0xac, 0x19, 0x2d, 0x58, 0xf3, 0x8c, 0x48, 0x5b, 0x47, 0x01,
-       0x9e, 0x8a, 0xb8, 0x3b, 0x01, 0x47, 0x5d, 0x3a, 0x2d, 0xaf, 0x74, 0x0f,
-       0x38, 0xda, 0x97, 0x70, 0x7a, 0xe4, 0xc6, 0x4a, 0x5a, 0x6e, 0xa8, 0x98,
-       0x75, 0xd2, 0xf9, 0x75, 0xd0, 0xa4, 0x37, 0x0d, 0x9d, 0x93, 0xf1, 0x82,
-       0xe0, 0x3c, 0xe4, 0xb7, 0x3a, 0xe2, 0x4a, 0xb4, 0x23, 0x19, 0x9f, 0x16,
-       0xf3, 0x7d, 0xb1, 0xfc, 0xe3, 0x60, 0x28, 0xe6, 0xca, 0x2b, 0x3e, 0xc7,
-       0xd5, 0x23, 0xd7, 0x97, 0xab, 0xfb, 0xe3, 0x5a, 0xe9, 0x13, 0x51, 0xae,
-       0x4d, 0x64, 0x2b, 0xe5, 0x28, 0xe3, 0xe7, 0x22, 0x79, 0x69, 0x7b, 0x2b,
-       0x7c, 0x37, 0x48, 0xeb, 0xb6, 0xb7, 0x82, 0x56, 0x62, 0xd0, 0xf3, 0x5b,
-       0x01, 0xd7, 0x56, 0xc6, 0xbb, 0x18, 0xe7, 0xe2, 0xf7, 0x5f, 0xa2, 0x5f,
-       0xd6, 0xfd, 0x5d, 0xbd, 0x66, 0x25, 0x8a, 0x73, 0x6e, 0xf8, 0x65, 0x79,
-       0x5d, 0xd3, 0x38, 0x14, 0x4d, 0x8b, 0x13, 0x7d, 0x5b, 0x5c, 0x56, 0xf8,
-       0xd5, 0xfd, 0x73, 0xed, 0x57, 0x14, 0x70, 0xe8, 0xee, 0xd8, 0xdc, 0x23,
-       0x7d, 0x18, 0x5f, 0xff, 0x92, 0xf1, 0xed, 0x17, 0xc6, 0x54, 0x2f, 0x16,
-       0x39, 0x86, 0xf9, 0x71, 0xa9, 0x3f, 0x32, 0xe3, 0x8a, 0x76, 0x2c, 0x1e,
-       0x8f, 0xae, 0xaf, 0x4e, 0x01, 0x96, 0xe7, 0xf4, 0x1e, 0x81, 0x20, 0xb8,
-       0xa6, 0xe3, 0x62, 0x90, 0x58, 0x97, 0xec, 0x9c, 0x9e, 0x5f, 0xd3, 0x19,
-       0x8a, 0xa4, 0x33, 0x1a, 0xff, 0xf8, 0x4e, 0xe4, 0xca, 0xdd, 0x98, 0x3b,
-       0x71, 0x73, 0x5d, 0xae, 0xe6, 0x8d, 0x9c, 0xdf, 0x6d, 0xd7, 0xad, 0x42,
-       0xbf, 0x29, 0x08, 0x94, 0xbf, 0x58, 0x56, 0x50, 0x47, 0x61, 0xec, 0xb2,
-       0xdb, 0xee, 0x4b, 0x49, 0x31, 0x6e, 0x38, 0xe4, 0xa6, 0xa3, 0x89, 0x42,
-       0xb9, 0x0b, 0xbf, 0x1b, 0xf0, 0xfe, 0x45, 0xd8, 0x28, 0x3d, 0xb0, 0x61,
-       0x24, 0xa6, 0x8c, 0x3c, 0x00, 0xfd, 0x76, 0xe4, 0x95, 0x22, 0x3f, 0x7a,
-       0x89, 0xe1, 0x72, 0x2c, 0x31, 0x5a, 0xde, 0xcb, 0xfa, 0x28, 0x7b, 0xa5,
-       0xf8, 0x1d, 0xfb, 0x62, 0x1f, 0xf4, 0x79, 0x7f, 0x96, 0x3e, 0x5c, 0xdb,
-       0x36, 0xdb, 0x0c, 0xf1, 0xe2, 0xd2, 0x0d, 0xc7, 0xbf, 0x6e, 0xeb, 0x8f,
-       0x70, 0x7c, 0x7b, 0x2d, 0xdc, 0x8b, 0xfb, 0x7d, 0x49, 0xdb, 0x2c, 0x8f,
-       0x55, 0x68, 0x27, 0x72, 0x4d, 0x27, 0x79, 0x62, 0x5c, 0x08, 0x47, 0x10,
-       0x5c, 0x48, 0x19, 0x7d, 0xfd, 0x74, 0x85, 0xeb, 0x1a, 0x41, 0xf0, 0x5d,
-       0xda, 0xc2, 0x83, 0x25, 0xf4, 0x17, 0xe2, 0x60, 0x63, 0xde, 0x85, 0x2c,
-       0x1c, 0xe9, 0x26, 0x7e, 0x05, 0x5e, 0x69, 0x87, 0xb7, 0x4b, 0xa2, 0x89,
-       0xdf, 0x2e, 0x37, 0x24, 0x3e, 0x51, 0xf6, 0x80, 0x67, 0x8e, 0x3b, 0x96,
-       0xd8, 0x63, 0xc7, 0xcc, 0xfd, 0x20, 0xaf, 0xbf, 0x4f, 0xe3, 0xa5, 0x05,
-       0x3e, 0x12, 0x61, 0x9a, 0x87, 0x85, 0xb0, 0x25, 0x2c, 0x6e, 0x82, 0xe0,
-       0xfb, 0x29, 0xf6, 0xd9, 0xcd, 0xfd, 0x00, 0x23, 0xe8, 0x37, 0xbf, 0x56,
-       0x11, 0x0f, 0xd1, 0xc4, 0x1d, 0xe8, 0xfb, 0xb7, 0xd1, 0xf7, 0xbe, 0x32,
-       0xfb, 0x83, 0x7c, 0xc0, 0xd8, 0x47, 0x2a, 0x21, 0xbc, 0xcb, 0xf5, 0x1d,
-       0xce, 0x79, 0xa7, 0xb5, 0xeb, 0xc2, 0x6f, 0x8d, 0x48, 0x4f, 0xc1, 0x97,
-       0xcb, 0x56, 0x66, 0xd6, 0xb8, 0xf2, 0x2e, 0xc8, 0xda, 0x40, 0x4e, 0x42,
-       0x86, 0xcd, 0x68, 0xba, 0xc9, 0xae, 0xe7, 0xff, 0x11, 0xf9, 0xe4, 0x0a,
-       0xc6, 0x94, 0x7b, 0x7d, 0xda, 0xab, 0xb3, 0xc1, 0x8c, 0x4f, 0x99, 0xbc,
-       0x4a, 0xc6, 0xbd, 0x7c, 0x27, 0xf4, 0x03, 0xd2, 0x1a, 0xe9, 0x63, 0x27,
-       0xb2, 0x91, 0x64, 0x62, 0x58, 0xb8, 0xc7, 0x89, 0xfb, 0x13, 0xb8, 0xef,
-       0x87, 0xf2, 0xc0, 0x85, 0x9c, 0xe3, 0x1c, 0x9a, 0xfe, 0x86, 0xcb, 0xf3,
-       0x65, 0x0f, 0x08, 0xd7, 0x09, 0x93, 0xf1, 0xbd, 0xda, 0x26, 0x01, 0xd5,
-       0x15, 0x59, 0x76, 0x33, 0x2c, 0x12, 0xbf, 0xaa, 0xbc, 0xde, 0x73, 0x05,
-       0x3e, 0x67, 0x1c, 0x21, 0x1a, 0xcd, 0x16, 0xe5, 0xb5, 0x48, 0xb7, 0xbc,
-       0x96, 0x4d, 0xd5, 0x4b, 0xaf, 0x96, 0xf9, 0xcc, 0xd3, 0xe9, 0xb3, 0x26,
-       0xdd, 0x85, 0x2e, 0xe1, 0x9c, 0xf4, 0x40, 0x46, 0x4f, 0x00, 0x6e, 0xe2,
-       0xb0, 0x87, 0x32, 0x89, 0xf3, 0xa7, 0x54, 0x3a, 0x16, 0xcd, 0x95, 0xa5,
-       0x2f, 0x57, 0xb4, 0xb1, 0x9e, 0x01, 0x8e, 0x7f, 0x95, 0xc5, 0x43, 0xa3,
-       0xb8, 0x80, 0xad, 0x2f, 0x92, 0x70, 0xe0, 0x2b, 0x43, 0xd7, 0x3f, 0xba,
-       0x4a, 0x1a, 0x89, 0x9b, 0x1e, 0xf0, 0x52, 0x0d, 0x74, 0xd1, 0xfd, 0xcd,
-       0x5c, 0x37, 0xd5, 0x36, 0x64, 0xec, 0x63, 0xbf, 0xac, 0xd2, 0x7f, 0x1b,
-       0x57, 0xe9, 0x51, 0x2b, 0x2f, 0xa3, 0x7d, 0x94, 0x97, 0x4f, 0x97, 0x08,
-       0x8f, 0x78, 0x11, 0x3f, 0xd1, 0xd7, 0x5b, 0x16, 0x15, 0x49, 0x7b, 0xd1,
-       0xde, 0xf2, 0x42, 0xfa, 0x7f, 0xba, 0xf2, 0x61, 0x6b, 0x0b, 0x56, 0xc7,
-       0x54, 0xab, 0xf3, 0xc8, 0x83, 0xcb, 0xe5, 0x11, 0x26, 0x89, 0xae, 0x48,
-       0x5f, 0xf8, 0x54, 0x7b, 0x47, 0xde, 0xab, 0x15, 0xe2, 0x39, 0x80, 0xdc,
-       0x06, 0xae, 0xcb, 0x5c, 0xaf, 0xde, 0x8f, 0x79, 0xfb, 0x3f, 0x41, 0x26,
-       0xc6, 0x7c, 0x4f, 0xea, 0xe0, 0xdb, 0xbe, 0x0c, 0xdd, 0xf9, 0x8a, 0x7f,
-       0xe1, 0x53, 0x9d, 0x1d, 0x41, 0xf0, 0xac, 0x9f, 0x4f, 0xb8, 0x90, 0x1f,
-       0x87, 0x2d, 0xbe, 0x87, 0x81, 0xef, 0x89, 0x39, 0x7c, 0x27, 0xe4, 0x62,
-       0xd7, 0xf7, 0x03, 0xae, 0xf5, 0x0d, 0x97, 0x6f, 0xbd, 0x55, 0xa5, 0x3f,
-       0xfe, 0xa1, 0x6c, 0x37, 0xfb, 0x1b, 0x91, 0xc3, 0x95, 0x9b, 0x88, 0xbf,
-       0x28, 0xc6, 0x7a, 0x4f, 0x9f, 0x6f, 0xfa, 0xed, 0x5b, 0xd0, 0x2f, 0xe9,
-       0xe5, 0x47, 0xac, 0x8b, 0x32, 0xd5, 0x75, 0x33, 0xa0, 0xcb, 0xbc, 0xad,
-       0x3b, 0x70, 0x85, 0xba, 0xde, 0x15, 0xea, 0x1e, 0x46, 0xdd, 0x3d, 0xb6,
-       0xee, 0x85, 0xcf, 0xbc, 0xb9, 0x7e, 0x07, 0xb8, 0xc7, 0x0e, 0x3e, 0x80,
-       0xb8, 0x11, 0xff, 0x36, 0xfc, 0xbe, 0x85, 0xed, 0x28, 0xda, 0xf7, 0x23,
-       0x95, 0x21, 0x19, 0xae, 0xec, 0xc4, 0x33, 0x88, 0xb4, 0x3e, 0x3c, 0xfb,
-       0xf0, 0x3b, 0x8d, 0x47, 0xa2, 0x6e, 0xfa, 0xc2, 0x5d, 0xc3, 0x7e, 0x88,
-       0x57, 0xae, 0xcd, 0xb3, 0x0f, 0xd8, 0x17, 0x5d, 0x3f, 0x41, 0x1f, 0x61,
-       0xfa, 0x07, 0x50, 0x67, 0x1a, 0x69, 0x2b, 0x69, 0x7b, 0x62, 0xae, 0xab,
-       0xeb, 0x54, 0xc3, 0x36, 0x1d, 0xce, 0x05, 0xf2, 0x0d, 0x8d, 0xf6, 0x16,
-       0x43, 0x18, 0xef, 0x44, 0x1b, 0xe3, 0x57, 0x29, 0xff, 0x1e, 0xc2, 0x15,
-       0x57, 0xfe, 0xc7, 0xf0, 0x7e, 0x2d, 0xd8, 0x9d, 0x62, 0x4c, 0x9e, 0xf3,
-       0x7e, 0xdd, 0xaa, 0xa5, 0x7b, 0x9f, 0x42, 0x1a, 0xe8, 0x84, 0x4e, 0x69,
-       0xb0, 0x74, 0x5a, 0x80, 0xe5, 0x43, 0x1a, 0xe5, 0x98, 0x17, 0x97, 0x4d,
-       0x76, 0xe6, 0xa5, 0x07, 0xba, 0x8c, 0xb2, 0xf6, 0xd3, 0xf5, 0x26, 0x0e,
-       0x03, 0xcb, 0xd1, 0xef, 0x04, 0x3d, 0x37, 0x88, 0x87, 0xfa, 0x03, 0x11,
-       0x0f, 0x34, 0x18, 0xd6, 0x4f, 0x7a, 0x03, 0x11, 0x8e, 0x19, 0x1c, 0x5f,
-       0xe6, 0xba, 0x34, 0x6d, 0x6b, 0xd6, 0x0f, 0x6d, 0x1c, 0xfe, 0x7b, 0x59,
-       0xc4, 0x67, 0x1a, 0xdb, 0x0b, 0xde, 0x55, 0xe3, 0x2f, 0x59, 0x63, 0xc1,
-       0x38, 0xf3, 0x49, 0x68, 0x30, 0xaf, 0x4f, 0xcb, 0xe9, 0xfc, 0x35, 0x35,
-       0xd2, 0xe0, 0xf5, 0xeb, 0xdf, 0x2c, 0xd3, 0xe0, 0x81, 0x4f, 0x17, 0x95,
-       0x61, 0x1a, 0xf3, 0x0a, 0x6b, 0x94, 0xde, 0xab, 0xa4, 0xf7, 0x28, 0xc9,
-       0x83, 0xa9, 0x64, 0x62, 0x48, 0x25, 0xbd, 0x71, 0xd9, 0x0f, 0xb9, 0x43,
-       0x39, 0x39, 0x73, 0x7f, 0x44, 0xb8, 0x9f, 0xef, 0x5d, 0x92, 0xf5, 0x29,
-       0x3f, 0x0b, 0x9f, 0x57, 0x94, 0x75, 0x95, 0x97, 0x1a, 0xcc, 0xd8, 0xb8,
-       0x0f, 0x01, 0x70, 0x36, 0xd1, 0x86, 0xbb, 0xb5, 0x81, 0x3c, 0x94, 0x50,
-       0x11, 0xd9, 0x45, 0x3f, 0x5f, 0x7d, 0xb1, 0x5e, 0xea, 0xa7, 0xd7, 0x78,
-       0x52, 0xd1, 0xe9, 0x66, 0x7f, 0x60, 0xb2, 0x73, 0x48, 0x89, 0x1e, 0x7b,
-       0x46, 0xbd, 0x91, 0xcc, 0x9e, 0xb5, 0xfa, 0x23, 0x90, 0xc7, 0xb4, 0xbe,
-       0x98, 0xf9, 0xbc, 0x2b, 0x17, 0x82, 0xb6, 0x4d, 0x17, 0xda, 0xb3, 0x5d,
-       0xb4, 0x73, 0x57, 0xd9, 0xfd, 0x95, 0x8c, 0x63, 0xbd, 0x4b, 0x9e, 0xf3,
-       0x0b, 0x18, 0xf7, 0x7e, 0xb9, 0xe0, 0xb3, 0xbf, 0x99, 0xcf, 0x79, 0xc2,
-       0x74, 0xc2, 0x6e, 0xfa, 0x13, 0xf5, 0xa7, 0x80, 0x87, 0x7d, 0x52, 0x07,
-       0x5f, 0xc9, 0xee, 0x4b, 0x0e, 0xe4, 0x45, 0xcf, 0x4b, 0x8f, 0xa0, 0xad,
-       0x15, 0x3e, 0xf8, 0x10, 0x76, 0x73, 0xcd, 0x91, 0xab, 0x21, 0x77, 0x1d,
-       0xbd, 0xc7, 0x02, 0x93, 0xe1, 0x4d, 0x61, 0xde, 0x33, 0x03, 0x2c, 0x57,
-       0x2f, 0xd3, 0x31, 0xf2, 0xba, 0xe6, 0x97, 0x4f, 0x65, 0xfd, 0x76, 0x4f,
-       0x39, 0xc3, 0x8c, 0x31, 0x00, 0xaf, 0xa4, 0xcd, 0x54, 0x6c, 0xbb, 0xcf,
-       0xb6, 0x58, 0xe6, 0x2a, 0xf9, 0xf6, 0xc0, 0x85, 0x7f, 0x78, 0xd6, 0xff,
-       0x7b, 0xc0, 0x91, 0x81, 0x4c, 0xe0, 0xf3, 0x6a, 0x90, 0x8f, 0x31, 0xa6,
-       0xf5, 0xbf, 0xeb, 0xad, 0x9d, 0xac, 0x79, 0x7f, 0x58, 0xef, 0x93, 0x79,
-       0xfe, 0x33, 0x59, 0xae, 0x77, 0xc0, 0x36, 0xc9, 0x69, 0xb9, 0x18, 0xfd,
-       0x69, 0x0e, 0xf0, 0x14, 0x2a, 0xb4, 0x43, 0xfe, 0x06, 0x76, 0x88, 0xd6,
-       0x93, 0xf2, 0xed, 0x41, 0xe6, 0xb1, 0xdd, 0xec, 0xd5, 0xae, 0xd6, 0x0b,
-       0x21, 0x2c, 0xc9, 0xce, 0x1c, 0xf2, 0x47, 0xb4, 0x1d, 0xef, 0xc9, 0xac,
-       0xe7, 0xea, 0x7d, 0x27, 0xf9, 0xc1, 0x20, 0x78, 0xc5, 0x77, 0xe5, 0xa4,
-       0x86, 0xf9, 0x05, 0xf4, 0xe1, 0xc8, 0xc4, 0x80, 0xfb, 0xd3, 0x93, 0x3e,
-       0xc7, 0xc7, 0x3c, 0xae, 0x2b, 0x6d, 0x8e, 0x1b, 0xf8, 0x68, 0x9b, 0x7e,
-       0x2f, 0x98, 0x8d, 0x71, 0xdd, 0x02, 0x3c, 0x5d, 0x6a, 0xf7, 0x6e, 0x90,
-       0xdb, 0xe6, 0x6c, 0x9a, 0x69, 0x31, 0x36, 0xa3, 0xd1, 0x69, 0x17, 0xfe,
-       0x61, 0xc4, 0xbf, 0xb0, 0xba, 0x80, 0xb9, 0x81, 0x0e, 0x5b, 0x0c, 0x4b,
-       0x8a, 0xb0, 0x0c, 0x6b, 0x58, 0x62, 0xc0, 0xa5, 0x0b, 0xd9, 0x77, 0x9b,
-       0x1c, 0x02, 0xde, 0x87, 0x06, 0x45, 0x9e, 0x85, 0x4d, 0x76, 0xbe, 0x0a,
-       0x9e, 0x19, 0xc0, 0x73, 0xde, 0xe7, 0x5e, 0x00, 0xe6, 0xf9, 0xde, 0xb0,
-       0x70, 0x2f, 0x00, 0x71, 0xd8, 0x81, 0xdf, 0x22, 0x33, 0xd0, 0xbf, 0x27,
-       0xfd, 0xd7, 0x82, 0xf1, 0x18, 0x75, 0x23, 0xda, 0x99, 0xdb, 0x1b, 0x14,
-       0xc8, 0xe7, 0x53, 0xd4, 0x43, 0xb5, 0xd2, 0xb6, 0x8e, 0x7e, 0x88, 0x91,
-       0x9f, 0x37, 0xf8, 0x19, 0xf4, 0xf5, 0x5b, 0x2b, 0xa5, 0x3e, 0x2f, 0xfd,
-       0x1d, 0x75, 0xc8, 0x73, 0x6d, 0xde, 0x80, 0xce, 0xeb, 0xef, 0x38, 0x8c,
-       0xfc, 0x8f, 0xaf, 0x64, 0xbc, 0xdb, 0xf5, 0xd7, 0x4b, 0xdb, 0x1a, 0xe6,
-       0x55, 0xf3, 0xe0, 0xab, 0xdc, 0x83, 0x69, 0x75, 0x38, 0x64, 0x59, 0x29,
-       0xef, 0x71, 0xa7, 0xdd, 0x21, 0xcc, 0xc5, 0x6e, 0x9f, 0xb2, 0xed, 0xbf,
-       0xa3, 0x6e, 0x4a, 0x6e, 0xf4, 0x07, 0x91, 0x37, 0x8d, 0xbc, 0xc3, 0x36,
-       0x6f, 0xd0, 0xe6, 0x6d, 0x43, 0xde, 0x3e, 0xe0, 0xef, 0x6e, 0x9d, 0x9e,
-       0xe5, 0x6f, 0x53, 0xc7, 0x5b, 0xd9, 0x71, 0xe1, 0x33, 0x37, 0xf8, 0x84,
-       0x0b, 0x79, 0x25, 0xae, 0x8b, 0xde, 0x26, 0x79, 0x2f, 0x79, 0x0b, 0x7b,
-       0xfd, 0x66, 0xb1, 0x0e, 0xb2, 0x89, 0x7b, 0x80, 0x69, 0xb3, 0x6e, 0xf1,
-       0x5e, 0x96, 0xff, 0x40, 0xba, 0xeb, 0xc9, 0x38, 0x5f, 0x5b, 0xc9, 0xb8,
-       0xd8, 0x88, 0x4f, 0xfb, 0x3a, 0x90, 0x9c, 0x5e, 0x3f, 0xa1, 0x7f, 0x5b,
-       0x44, 0x3a, 0xe9, 0x41, 0x35, 0x45, 0xf4, 0x3e, 0x2d, 0x7e, 0x47, 0x61,
-       0xf7, 0x06, 0x42, 0x9f, 0x8f, 0x36, 0x5d, 0xc6, 0xe3, 0xda, 0x50, 0x98,
-       0xe7, 0x21, 0x4f, 0x6d, 0x8a, 0xc0, 0x26, 0xaa, 0xf5, 0x1d, 0x1d, 0xa3,
-       0x2e, 0xe8, 0x75, 0x00, 0xc6, 0xdf, 0x32, 0xf0, 0x63, 0x02, 0xe9, 0x47,
-       0xdf, 0xa4, 0xfd, 0x68, 0x87, 0xef, 0x1d, 0x10, 0xee, 0x67, 0x65, 0x7a,
-       0xbb, 0xf7, 0x6d, 0x99, 0xa7, 0xf3, 0x19, 0x49, 0x66, 0x94, 0x03, 0xff,
-       0x75, 0xab, 0x23, 0xf5, 0xb0, 0x3d, 0x6e, 0x30, 0xfa, 0xcd, 0xe3, 0x9e,
-       0xc4, 0x8b, 0xda, 0x56, 0x6b, 0xb4, 0xf3, 0x91, 0x05, 0x6e, 0xb8, 0x1f,
-       0x7c, 0xe0, 0x9e, 0xdd, 0x7e, 0x21, 0x09, 0x6a, 0xd4, 0xba, 0x71, 0x18,
-       0xb4, 0x91, 0x4d, 0x19, 0xdd, 0x78, 0xc3, 0x9c, 0x6e, 0xfc, 0xf3, 0x95,
-       0xe4, 0x89, 0xe1, 0x72, 0x1c, 0x75, 0xf5, 0x3a, 0x4a, 0x82, 0x75, 0x6b,
-       0x31, 0x9f, 0xe7, 0xfd, 0xec, 0x35, 0xa0, 0x2f, 0xc8, 0xe1, 0x64, 0xe7,
-       0x29, 0xd4, 0x2d, 0xa0, 0xee, 0xe4, 0x5c, 0x5d, 0x47, 0x46, 0x7c, 0xbd,
-       0xef, 0x59, 0x26, 0xcb, 0x21, 0x1d, 0x26, 0xe3, 0xb7, 0x6a, 0x5e, 0xe0,
-       0x7e, 0x30, 0x37, 0x71, 0x9f, 0x6c, 0xd6, 0xb4, 0xdd, 0x27, 0xdc, 0x27,
-       0xc5, 0xb6, 0xef, 0x0b, 0xda, 0xd6, 0x10, 0xbe, 0x12, 0xde, 0xa4, 0x8d,
-       0x31, 0xbc, 0xc3, 0xf9, 0x37, 0xf3, 0x3e, 0xe4, 0x10, 0xdf, 0xbf, 0x1f,
-       0xe4, 0x07, 0x39, 0x2f, 0xfc, 0x9e, 0xa7, 0xb9, 0x11, 0xd0, 0x5c, 0xc4,
-       0x7f, 0xbb, 0x0c, 0xeb, 0x3d, 0x10, 0x29, 0x99, 0xd0, 0xf1, 0xcc, 0x0b,
-       0xc1, 0x23, 0x0b, 0xe4, 0xf8, 0x47, 0x94, 0xa1, 0x21, 0xfe, 0x2e, 0x24,
-       0xea, 0x64, 0x66, 0x4d, 0x9d, 0xde, 0xf1, 0x41, 0x7c, 0x8c, 0xde, 0x73,
-       0x3b, 0xf8, 0xf5, 0xfa, 0xb9, 0xb1, 0x00, 0xdf, 0xc0, 0xe3, 0x4e, 0x63,
-       0xeb, 0x63, 0x1c, 0x19, 0xed, 0xbf, 0x67, 0x8b, 0x4a, 0xef, 0x0b, 0xa2,
-       0x8e, 0x3f, 0x00, 0x9d, 0x6a, 0xf6, 0xa4, 0xe0, 0x5d, 0xe1, 0xbc, 0x29,
-       0xed, 0x73, 0x1c, 0x04, 0x0f, 0x1f, 0xf4, 0xb3, 0x6b, 0x6a, 0x75, 0xdb,
-       0x49, 0xef, 0x7a, 0x6d, 0x13, 0x6e, 0x94, 0x99, 0x14, 0xdb, 0x23, 0x5e,
-       0xfe, 0x47, 0x30, 0xe4, 0xcd, 0xa0, 0x7f, 0x43, 0xff, 0x59, 0x5f, 0xb5,
-       0xd4, 0x49, 0xf5, 0x3e, 0x53, 0xe2, 0xc9, 0x85, 0xbd, 0xd2, 0x01, 0xfc,
-       0x18, 0x78, 0x73, 0xe5, 0xb7, 0x49, 0x21, 0xe6, 0xda, 0xb1, 0x45, 0xb4,
-       0x2f, 0x37, 0x91, 0xaa, 0x83, 0x2d, 0xf8, 0x17, 0xc1, 0xe4, 0x82, 0x31,
-       0x1e, 0xac, 0x1a, 0xe3, 0x4c, 0x02, 0xd8, 0x68, 0x89, 0xcc, 0xc9, 0x01,
-       0xf6, 0x65, 0x64, 0x52, 0x38, 0xc6, 0x3a, 0x8c, 0x71, 0xc7, 0xdc, 0x18,
-       0x0f, 0x2f, 0x1a, 0xe3, 0x61, 0x8c, 0x11, 0xf6, 0x42, 0x29, 0xd3, 0xe9,
-       0xce, 0xcf, 0xfb, 0xd5, 0x35, 0x73, 0xf3, 0x29, 0xdc, 0xeb, 0x84, 0xf1,
-       0xd3, 0xa6, 0xd8, 0x08, 0x78, 0x74, 0x5b, 0x90, 0x71, 0x0e, 0x64, 0x5b,
-       0x76, 0x4d, 0x8d, 0x1d, 0xff, 0x76, 0x96, 0x2b, 0x1b, 0x1c, 0x9c, 0x4c,
-       0xb9, 0x9d, 0x8f, 0xa0, 0xbf, 0xbd, 0x76, 0x5c, 0xbd, 0xe5, 0xab, 0x31,
-       0xae, 0x0b, 0xdf, 0xc1, 0x18, 0xe0, 0xb3, 0x9d, 0xa0, 0x0f, 0x9c, 0x18,
-       0x92, 0x05, 0xb2, 0xeb, 0x33, 0xf3, 0x72, 0xd4, 0xc0, 0x4c, 0xdb, 0xba,
-       0x30, 0x07, 0xf3, 0xdd, 0x8b, 0x60, 0xbe, 0x1b, 0x30, 0xef, 0xb3, 0xf3,
-       0xb2, 0xaf, 0x6a, 0xcf, 0x62, 0x48, 0x47, 0xfc, 0xfd, 0xbc, 0xf5, 0x45,
-       0x3e, 0x20, 0xf7, 0x97, 0x3a, 0xe5, 0xcb, 0x95, 0xe4, 0x59, 0xc6, 0xd1,
-       0xcf, 0x55, 0x92, 0xe3, 0x22, 0x5d, 0xf2, 0xc7, 0xb0, 0x73, 0xae, 0x82,
-       0x6f, 0xf1, 0x34, 0xfc, 0xd7, 0x3f, 0xa9, 0xf8, 0xf2, 0xc4, 0xdc, 0x7e,
-       0x38, 0xea, 0xba, 0xb4, 0x9c, 0x84, 0x4f, 0xbb, 0xed, 0x68, 0x1b, 0xf7,
-       0x2a, 0x11, 0xbe, 0xbb, 0xa8, 0x73, 0xda, 0x94, 0xe6, 0xc5, 0xef, 0x62,
-       0xbc, 0xa7, 0xa9, 0x6b, 0xd6, 0xfa, 0xbe, 0x77, 0xb3, 0x5a, 0x47, 0x99,
-       0x90, 0xff, 0x5a, 0xe4, 0x03, 0xf5, 0x26, 0xc6, 0x92, 0xf1, 0x9a, 0xc9,
-       0x1b, 0xdb, 0x3a, 0x12, 0x7d, 0x42, 0x5b, 0x82, 0xfe, 0x36, 0x6c, 0xa1,
-       0xd2, 0xe6, 0xf8, 0x5a, 0xa1, 0x4c, 0xa2, 0x5d, 0x94, 0x96, 0x09, 0xc0,
-       0x3e, 0x06, 0x89, 0x50, 0x68, 0xf6, 0x47, 0x7b, 0xd5, 0x44, 0x03, 0x79,
-       0x70, 0xdb, 0x19, 0xd0, 0xd7, 0x36, 0x8c, 0xa9, 0x2b, 0x79, 0x76, 0x46,
-       0x65, 0x4e, 0xac, 0x95, 0x57, 0x82, 0xa1, 0x66, 0x47, 0x9e, 0xd8, 0xc4,
-       0x3c, 0x2d, 0xb7, 0x3f, 0xd5, 0x0b, 0xf9, 0xd4, 0xce, 0x73, 0x0b, 0x03,
-       0xf2, 0x2f, 0x77, 0x80, 0x06, 0x7f, 0xb8, 0xe9, 0x6b, 0xc1, 0x6c, 0xb3,
-       0x2b, 0x5b, 0x37, 0x25, 0xbd, 0xbc, 0xc2, 0x78, 0x4a, 0x18, 0x4f, 0x09,
-       0xe3, 0xe3, 0x98, 0x4b, 0x18, 0xd7, 0x15, 0xf7, 0x4a, 0xf5, 0x2c, 0x88,
-       0xcb, 0x1a, 0x3f, 0x2d, 0x93, 0x77, 0x65, 0x83, 0xdd, 0x2b, 0x35, 0x5c,
-       0x1f, 0xae, 0xb1, 0x65, 0x64, 0x3c, 0x28, 0xf8, 0x7f, 0x70, 0x55, 0xb6,
-       0x2b, 0xb6, 0x58, 0xe7, 0xdc, 0x35, 0xaf, 0x73, 0x44, 0x9e, 0x33, 0xf3,
-       0x86, 0x39, 0xf3, 0xbd, 0x49, 0x6e, 0x86, 0x87, 0x0e, 0xdc, 0xaa, 0xf7,
-       0x3c, 0x77, 0xe0, 0x9b, 0x36, 0xd5, 0xa7, 0xf5, 0x3a, 0xe2, 0x4c, 0xf9,
-       0x1e, 0x3b, 0x77, 0xf7, 0x68, 0x3d, 0xbb, 0x75, 0xd3, 0xa5, 0x80, 0xfb,
-       0xdc, 0xbc, 0x4d, 0xcb, 0xc5, 0x22, 0x68, 0xef, 0xd5, 0x69, 0xde, 0xe7,
-       0x7a, 0x76, 0x41, 0x9f, 0x13, 0x01, 0xde, 0xe6, 0xe2, 0x62, 0xf5, 0x48,
-       0xa3, 0xbe, 0xf8, 0x69, 0x83, 0x59, 0x47, 0xa5, 0x6c, 0x58, 0x83, 0x34,
-       0xd7, 0xec, 0x05, 0x5e, 0x90, 0xf7, 0xdf, 0xea, 0xcd, 0x9e, 0x8f, 0xea,
-       0xb2, 0xe0, 0x31, 0xbd, 0x2f, 0x84, 0xfb, 0x03, 0x7f, 0x79, 0xa5, 0xb1,
-       0x4d, 0xc3, 0x7c, 0xa6, 0xff, 0x38, 0x98, 0xd0, 0x31, 0x36, 0xf6, 0xf5,
-       0x43, 0xfc, 0x5e, 0xbc, 0x5f, 0x24, 0xb4, 0x5d, 0xeb, 0x40, 0xf7, 0xda,
-       0x5f, 0x16, 0x94, 0x89, 0xe7, 0x25, 0x22, 0x13, 0x55, 0x30, 0x4e, 0x10,
-       0xee, 0x52, 0xd7, 0xaa, 0xf9, 0xd8, 0xdd, 0x6a, 0xa4, 0x11, 0xc6, 0x75,
-       0x8b, 0xf2, 0xc8, 0x1b, 0xad, 0x2b, 0x49, 0x37, 0xd3, 0xc2, 0xb4, 0xf9,
-       0x31, 0xcd, 0x68, 0xfb, 0xb9, 0x6d, 0x95, 0xde, 0xfb, 0xc4, 0x35, 0x46,
-       0xc6, 0x08, 0x63, 0x26, 0xdf, 0xf5, 0xff, 0x56, 0xd7, 0x19, 0x9a, 0xab,
-       0xa3, 0xe7, 0x02, 0xf9, 0x6e, 0x55, 0x5e, 0x35, 0xdc, 0xd4, 0x5f, 0x43,
-       0x9d, 0x75, 0xd0, 0x89, 0x17, 0x53, 0xab, 0xc3, 0xbd, 0xf0, 0xb0, 0x21,
-       0xb2, 0xd7, 0xd4, 0x5a, 0x99, 0x3f, 0x81, 0x79, 0x7d, 0x26, 0x65, 0x78,
-       0x51, 0xf3, 0x61, 0xf1, 0x36, 0xf8, 0xeb, 0xa1, 0xde, 0xa0, 0x9c, 0x26,
-       0x6f, 0x22, 0xad, 0x42, 0x9f, 0xe0, 0xc2, 0xea, 0x99, 0xae, 0x57, 0x03,
-       0xee, 0xb3, 0x7c, 0x45, 0xdb, 0x51, 0x43, 0xb2, 0xb0, 0xed, 0xd1, 0x7b,
-       0x5e, 0xbf, 0xed, 0xa1, 0x65, 0xda, 0x1e, 0xb2, 0x6d, 0x8b, 0x6b, 0xda,
-       0x8e, 0x5e, 0xa1, 0xed, 0x81, 0x37, 0x68, 0x7b, 0x70, 0x99, 0xb6, 0x07,
-       0xc3, 0xb6, 0x95, 0x69, 0xdb, 0x0b, 0xdb, 0x4e, 0x2c, 0xc2, 0xc9, 0x67,
-       0x5e, 0xbf, 0xed, 0x7d, 0xcb, 0xb4, 0xbd, 0x6f, 0x11, 0xdc, 0xc4, 0x49,
-       0x2d, 0x74, 0xff, 0x3d, 0xda, 0xe6, 0xac, 0x03, 0xdf, 0x5c, 0x84, 0xfc,
-       0x36, 0xfe, 0xc8, 0x85, 0xbb, 0x66, 0xcb, 0xe0, 0x2b, 0xf8, 0xd7, 0x99,
-       0x72, 0x03, 0x9e, 0x71, 0xd8, 0x33, 0x28, 0x07, 0x7b, 0xbc, 0x26, 0x1d,
-       0xc8, 0xc9, 0x6e, 0x96, 0xcd, 0xc7, 0x6b, 0xe7, 0xf4, 0xc6, 0x3d, 0xe8,
-       0x8f, 0x6d, 0xfb, 0x5e, 0xbf, 0xbc, 0xa6, 0xfb, 0xcb, 0x95, 0xe9, 0x8f,
-       0x21, 0xbd, 0x42, 0x1f, 0x97, 0xf5, 0x42, 0x19, 0x58, 0x67, 0xd7, 0x3e,
-       0x68, 0x6b, 0x32, 0x0e, 0xa7, 0xed, 0x51, 0x29, 0x94, 0x7f, 0x12, 0x4c,
-       0x83, 0x2e, 0x46, 0xe6, 0x74, 0xc8, 0x93, 0xab, 0x68, 0xb3, 0x8f, 0x53,
-       0xb3, 0x54, 0xc5, 0xa0, 0x46, 0x7c, 0xa6, 0xfd, 0x98, 0x6d, 0xc2, 0x0e,
-       0x0c, 0xcb, 0x32, 0x6e, 0x6c, 0x62, 0x4e, 0x67, 0x21, 0x33, 0xcd, 0x9e,
-       0x0e, 0xfa, 0x2a, 0x4f, 0x81, 0x97, 0xf7, 0x43, 0x76, 0x24, 0xf3, 0x22,
-       0x3d, 0x8d, 0xe6, 0xac, 0x45, 0x4c, 0x72, 0x5d, 0xbf, 0x69, 0xf1, 0xb8,
-       0xef, 0xce, 0xe5, 0xcf, 0x59, 0x40, 0x3e, 0x38, 0x94, 0x91, 0xd7, 0x37,
-       0x9a, 0x75, 0xbb, 0xb7, 0x36, 0x32, 0x1e, 0xa3, 0x36, 0x75, 0xaf, 0xd6,
-       0xf2, 0xc7, 0x09, 0xbf, 0xbf, 0xb2, 0xe8, 0x3b, 0xac, 0xf7, 0x93, 0xd5,
-       0x0b, 0xeb, 0x85, 0xe9, 0x70, 0x4d, 0x16, 0xa4, 0x1f, 0x58, 0xb3, 0xb0,
-       0x7e, 0xac, 0x69, 0xe1, 0xf7, 0xe0, 0xa2, 0xef, 0xcf, 0x2c, 0xfa, 0x7e,
-       0x61, 0xd1, 0xf7, 0x75, 0x6b, 0x17, 0x95, 0x5f, 0xf4, 0xfd, 0xe5, 0xb5,
-       0xcb, 0xc3, 0xfb, 0x57, 0x6b, 0x17, 0xc2, 0xf5, 0x94, 0x5e, 0x73, 0x1d,
-       0xaf, 0xb8, 0xb2, 0xbd, 0x88, 0x7c, 0xe7, 0xd6, 0x18, 0xf2, 0xe1, 0xcb,
-       0x54, 0xe7, 0x73, 0x8d, 0xe3, 0x1d, 0xb1, 0x85, 0xed, 0xcd, 0xd7, 0xdb,
-       0x31, 0x5f, 0x2f, 0x35, 0x5f, 0xcf, 0xf8, 0x23, 0x13, 0x15, 0xe6, 0x31,
-       0x3d, 0x6c, 0xd7, 0xd4, 0x1d, 0x29, 0x79, 0xfa, 0x3c, 0xc2, 0x80, 0x3e,
-       0x8f, 0x90, 0x80, 0x6f, 0xf4, 0x94, 0x8e, 0xeb, 0xaf, 0x51, 0x48, 0xaf,
-       0x34, 0xea, 0xd8, 0xbe, 0xe8, 0x33, 0x09, 0x03, 0xb0, 0xb9, 0x78, 0x0e,
-       0x21, 0x90, 0x9d, 0x29, 0xf3, 0x36, 0xe7, 0x12, 0x0e, 0x07, 0xbd, 0x5e,
-       0x10, 0x0c, 0xfb, 0x67, 0xad, 0x2c, 0xc7, 0xbb, 0x62, 0xea, 0xd0, 0xd7,
-       0x7c, 0x14, 0xfa, 0x66, 0xde, 0xc7, 0x7c, 0x8a, 0xf6, 0x3a, 0x68, 0xa6,
-       0x1b, 0x7a, 0x37, 0xf9, 0xa4, 0x68, 0xdd, 0xd1, 0x05, 0x9d, 0xeb, 0xdd,
-       0xfb, 0x3e, 0xd8, 0x3a, 0x5f, 0x06, 0xad, 0x1f, 0x4b, 0xf5, 0x68, 0xff,
-       0xff, 0x1c, 0x74, 0x31, 0xe3, 0x84, 0x8f, 0x69, 0xda, 0x22, 0x8d, 0x35,
-       0xe8, 0xb3, 0x50, 0x27, 0x53, 0x4e, 0x34, 0xdb, 0x75, 0xde, 0xc4, 0xcd,
-       0x53, 0xed, 0xde, 0x73, 0xe0, 0xb5, 0x7e, 0x7f, 0x03, 0x6c, 0x66, 0xd1,
-       0x3a, 0xbf, 0x50, 0x5a, 0x6f, 0x6d, 0x83, 0x66, 0x19, 0x77, 0xb9, 0x56,
-       0x93, 0xec, 0x19, 0x32, 0x3e, 0x66, 0x3c, 0xa1, 0x18, 0x23, 0xe6, 0xfa,
-       0x05, 0xcf, 0x39, 0x70, 0x9d, 0x9b, 0xf1, 0x90, 0xf1, 0x7b, 0x47, 0xfc,
-       0xbc, 0x17, 0xb1, 0x67, 0x23, 0xb2, 0x45, 0x43, 0x9b, 0x7b, 0xb4, 0xad,
-       0x1a, 0x05, 0x3f, 0x7d, 0x0f, 0x74, 0xcf, 0xba, 0xa4, 0xfd, 0xef, 0x04,
-       0x93, 0xae, 0x89, 0x4f, 0x29, 0xd4, 0xcb, 0x6a, 0x5c, 0x3d, 0x25, 0x07,
-       0x4a, 0xe4, 0xff, 0xa8, 0x96, 0xe5, 0xbb, 0x53, 0x94, 0x07, 0x51, 0xe0,
-       0x71, 0x0a, 0xf8, 0x6b, 0x90, 0xdd, 0x5d, 0x45, 0x94, 0x89, 0xc8, 0xd0,
-       0x40, 0x03, 0x78, 0x8f, 0x76, 0x09, 0xdf, 0x2e, 0xca, 0x7b, 0x32, 0x55,
-       0x1c, 0xd7, 0x7b, 0x9e, 0x1f, 0x43, 0xdd, 0xc7, 0xf1, 0x4c, 0x14, 0xcb,
-       0xa8, 0xf3, 0xb0, 0x2e, 0x3f, 0x31, 0xca, 0x73, 0x22, 0x02, 0x7b, 0xff,
-       0x49, 0x29, 0x4c, 0xb6, 0xc1, 0x2f, 0x99, 0x1e, 0x77, 0xe7, 0xe2, 0xe4,
-       0xff, 0xa5, 0x91, 0xeb, 0xcc, 0x85, 0xeb, 0xb8, 0x27, 0x47, 0xdc, 0x81,
-       0xcd, 0xaa, 0xb3, 0x49, 0xaf, 0xf9, 0xf4, 0x48, 0x3f, 0x6c, 0x8a, 0x9b,
-       0x2b, 0xcf, 0xc4, 0xcc, 0xda, 0xc0, 0x82, 0xf5, 0x86, 0xc3, 0xc4, 0x8a,
-       0x3a, 0xea, 0xf2, 0xdc, 0xa7, 0x4c, 0x9c, 0x81, 0xf6, 0x39, 0x1a, 0xae,
-       0xe7, 0x30, 0xcd, 0x93, 0xb6, 0xeb, 0x00, 0xd7, 0x99, 0x7f, 0xd2, 0xf2,
-       0xf5, 0x89, 0x4d, 0x61, 0x5f, 0xf9, 0x60, 0x6c, 0x53, 0x5e, 0x3e, 0x81,
-       0x27, 0x77, 0x5d, 0x72, 0x34, 0xab, 0xd8, 0xef, 0x37, 0x02, 0xc6, 0x02,
-       0x54, 0xba, 0x55, 0xf2, 0x4d, 0xd5, 0xfd, 0x33, 0xad, 0xc3, 0x2b, 0xa8,
-       0xd7, 0x83, 0x63, 0x26, 0x11, 0x03, 0x0e, 0xf2, 0x6f, 0x08, 0xcf, 0x16,
-       0xcf, 0x57, 0xcb, 0xc1, 0x73, 0xc2, 0xae, 0xd7, 0x70, 0x0d, 0x66, 0x05,
-       0xf0, 0xd2, 0x80, 0xf4, 0x09, 0x19, 0x39, 0xfe, 0x3b, 0x31, 0xee, 0x17,
-       0xaa, 0xd1, 0x7e, 0xf5, 0x7d, 0xf5, 0x26, 0x06, 0xf2, 0x2c, 0xca, 0x30,
-       0x7f, 0x1c, 0x75, 0x92, 0xf9, 0x6c, 0x64, 0xad, 0x0c, 0xe9, 0x7e, 0x83,
-       0x48, 0xdb, 0xb6, 0x7a, 0xbd, 0x4f, 0x5f, 0xce, 0x30, 0x6e, 0x11, 0xd6,
-       0x7d, 0x56, 0xef, 0x83, 0x73, 0xd3, 0xc9, 0x7c, 0x5f, 0x84, 0xf2, 0xa9,
-       0x53, 0x7a, 0xb9, 0xce, 0x73, 0x66, 0x5c, 0xd3, 0x76, 0xfb, 0x26, 0x9e,
-       0x07, 0xdd, 0x02, 0xfb, 0xef, 0x3b, 0x80, 0x89, 0x30, 0x9e, 0x40, 0x3a,
-       0x7c, 0xc2, 0xd7, 0x85, 0x61, 0xfa, 0x4d, 0xc2, 0x30, 0xfd, 0x26, 0x61,
-       0x20, 0x2e, 0x00, 0x47, 0xa5, 0x7d, 0x75, 0x68, 0x53, 0x5c, 0x85, 0x71,
-       0x1c, 0x2c, 0x4d, 0xc3, 0xbf, 0xd5, 0x31, 0x94, 0xce, 0x69, 0x45, 0x9e,
-       0xf7, 0xc0, 0x73, 0xe0, 0xad, 0x12, 0x78, 0x0f, 0xb6, 0xe1, 0x97, 0x61,
-       0x1b, 0x3e, 0x01, 0xdb, 0xf0, 0x1c, 0x6c, 0xc3, 0xc7, 0x31, 0x37, 0x8f,
-       0x2d, 0xe0, 0xd5, 0x8c, 0xe6, 0xd5, 0x42, 0xe9, 0x02, 0x78, 0xb5, 0xeb,
-       0x0a, 0xfc, 0xe8, 0xc2, 0xc6, 0xa7, 0x0d, 0xed, 0xc0, 0x96, 0xff, 0xb8,
-       0xf6, 0x8b, 0x1f, 0x4c, 0x8d, 0xb1, 0x0e, 0x68, 0x38, 0x49, 0x9f, 0x16,
-       0xf2, 0x3f, 0x99, 0x07, 0xef, 0x61, 0xac, 0x8e, 0xa3, 0xae, 0x5b, 0x23,
-       0xd4, 0x1f, 0xee, 0x36, 0xee, 0xef, 0xe6, 0x58, 0x13, 0x8b, 0xf0, 0x64,
-       0xf8, 0x73, 0x8f, 0x4f, 0x3d, 0x42, 0xbe, 0x4c, 0x7c, 0x76, 0xc4, 0xaf,
-       0xe6, 0xc5, 0x1d, 0x1c, 0x5f, 0xe0, 0x6d, 0x5a, 0xae, 0xee, 0x7c, 0xf9,
-       0x35, 0x73, 0xe5, 0x75, 0xff, 0xa3, 0xe4, 0x37, 0xe8, 0x6e, 0xe2, 0x3e,
-       0x91, 0x8d, 0x6c, 0xb0, 0xb8, 0xdf, 0x2f, 0x6d, 0xdb, 0x60, 0xaf, 0x0f,
-       0x82, 0x7e, 0xa7, 0x02, 0xf1, 0xb7, 0x85, 0x6d, 0xce, 0xb7, 0xe3, 0xd9,
-       0x76, 0x76, 0xc3, 0x96, 0xed, 0xdb, 0xc4, 0xb5, 0x5e, 0xd8, 0xf2, 0xa9,
-       0x70, 0x3e, 0x60, 0xf9, 0xea, 0x39, 0xa7, 0x0c, 0xa5, 0xec, 0x6c, 0xb0,
-       0xf1, 0x7e, 0xb6, 0x77, 0x61, 0xd1, 0x3c, 0x5d, 0x0a, 0x78, 0xce, 0x76,
-       0xc4, 0x1f, 0xab, 0xa2, 0x95, 0xbf, 0xb2, 0xb4, 0xa2, 0x16, 0x8d, 0xe3,
-       0x9c, 0xa5, 0x95, 0x10, 0xde, 0x58, 0x48, 0x2b, 0x75, 0x21, 0xad, 0xe4,
-       0xc7, 0x43, 0x5a, 0x61, 0xdd, 0x73, 0x21, 0xad, 0x24, 0xaa, 0x69, 0x25,
-       0x3f, 0xee, 0xe0, 0x59, 0x0c, 0x07, 0xe9, 0x85, 0xed, 0x90, 0x5e, 0x00,
-       0x4b, 0xa5, 0x32, 0x47, 0x2f, 0x31, 0xb4, 0x73, 0xa8, 0xa4, 0x34, 0xad,
-       0x0c, 0xa9, 0x50, 0x47, 0x78, 0x98, 0x73, 0xcc, 0xfd, 0x15, 0x69, 0x24,
-       0x65, 0x69, 0x64, 0xfe, 0x2c, 0xd1, 0x22, 0xda, 0x00, 0xee, 0x79, 0x5e,
-       0x60, 0xb3, 0xa6, 0x8d, 0xfb, 0x53, 0x2f, 0xa0, 0xec, 0x28, 0x68, 0x23,
-       0xc4, 0xc1, 0x03, 0x16, 0x07, 0x8b, 0xe7, 0xf2, 0xb4, 0xc5, 0xc1, 0xa8,
-       0xc5, 0x81, 0xe6, 0x97, 0x3c, 0xe7, 0x4c, 0x69, 0x1c, 0xd4, 0x69, 0x1c,
-       0x88, 0x0a, 0xeb, 0x9e, 0x5e, 0x06, 0x07, 0x2c, 0x33, 0xaa, 0xc7, 0x1f,
-       0xc1, 0xf8, 0xf7, 0x61, 0xfc, 0x4a, 0x8f, 0x9f, 0xf3, 0xc0, 0xf1, 0x03,
-       0x96, 0xca, 0x77, 0xe6, 0xc6, 0xdf, 0x84, 0x36, 0x0e, 0x6a, 0xdb, 0x99,
-       0xf1, 0x54, 0xea, 0x46, 0x33, 0xfe, 0xc7, 0x2a, 0xe6, 0x8c, 0xc9, 0x63,
-       0x4b, 0xf4, 0xd8, 0x0b, 0x96, 0x37, 0x7c, 0xbd, 0xce, 0xc6, 0x73, 0x6d,
-       0xe7, 0xa0, 0xbb, 0xc6, 0x52, 0x09, 0x7b, 0xe6, 0xd4, 0xd8, 0x43, 0x5f,
-       0x4d, 0x91, 0x77, 0x3e, 0xaa, 0xf7, 0xfa, 0x9d, 0xa5, 0x5d, 0x54, 0x6a,
-       0x92, 0xbe, 0xb1, 0x6a, 0xb8, 0x09, 0x6f, 0x3e, 0x50, 0x3e, 0x63, 0x37,
-       0xfb, 0xa1, 0x3b, 0x4c, 0xdc, 0x1a, 0xb4, 0x84, 0xf4, 0x64, 0xbe, 0x37,
-       0x52, 0x27, 0xea, 0x81, 0x0f, 0x60, 0xcc, 0x2e, 0x7c, 0xcc, 0x76, 0x6f,
-       0x9b, 0xa2, 0xae, 0xbb, 0xba, 0x4a, 0xd7, 0x35, 0x5b, 0x5d, 0xb7, 0x86,
-       0xba, 0x0e, 0x70, 0x3f, 0x25, 0x87, 0x4b, 0x9c, 0xbf, 0x7c, 0xa2, 0x4e,
-       0xc7, 0x40, 0x1d, 0x1b, 0xe7, 0x4b, 0xc6, 0x0f, 0x6b, 0x5a, 0xa6, 0xce,
-       0x4a, 0xea, 0xb8, 0xe4, 0x4c, 0xd7, 0x3f, 0xd9, 0x75, 0x10, 0xea, 0xb5,
-       0xef, 0x07, 0x7f, 0xb0, 0x8c, 0x5e, 0x83, 0xfe, 0xd1, 0xf6, 0x59, 0x0d,
-       0x64, 0xad, 0x9c, 0x6a, 0xc6, 0xb3, 0x9a, 0xe7, 0xc1, 0x3a, 0x3b, 0x54,
-       0xbd, 0xd4, 0x9c, 0x6a, 0x94, 0x3d, 0x63, 0x7a, 0xdd, 0x5c, 0xd4, 0x29,
-       0xe0, 0xff, 0x14, 0xcf, 0x14, 0x88, 0x3e, 0x03, 0x95, 0x1b, 0x85, 0x3f,
-       0x33, 0xf1, 0x94, 0xd9, 0x1b, 0x38, 0x56, 0xa3, 0x7f, 0xd3, 0xc6, 0x28,
-       0xa4, 0x32, 0xfa, 0xec, 0xd0, 0x1e, 0xb4, 0xd9, 0xbe, 0xa9, 0x16, 0x63,
-       0x8e, 0xa1, 0x2e, 0xf7, 0x16, 0xaa, 0x36, 0x57, 0x6a, 0xc5, 0x9d, 0x88,
-       0xea, 0xf3, 0x4b, 0x3c, 0x7f, 0x9f, 0xed, 0x69, 0x42, 0x5e, 0x44, 0xaf,
-       0x15, 0xd4, 0x9c, 0x9a, 0x3f, 0xa7, 0xae, 0x8e, 0x8a, 0x5d, 0xc3, 0x4f,
-       0x6b, 0xbd, 0x12, 0x39, 0x4a, 0x9d, 0xc3, 0xfd, 0x55, 0x3d, 0x98, 0xf7,
-       0xe5, 0xf4, 0x8d, 0x31, 0x62, 0xb3, 0x98, 0x3f, 0x75, 0x86, 0x67, 0x8d,
-       0x5b, 0xf1, 0x0e, 0xdb, 0x0b, 0xf5, 0x08, 0x74, 0xdf, 0xdb, 0x3f, 0xe1,
-       0x49, 0x3d, 0xf0, 0x3d, 0xa1, 0x80, 0x6b, 0x57, 0xd3, 0x42, 0x5e, 0x85,
-       0xb1, 0x69, 0x43, 0x0f, 0x8f, 0xbf, 0x21, 0x3f, 0x90, 0x26, 0x3a, 0x6d,
-       0x6c, 0xc1, 0xb7, 0x31, 0x7e, 0xd2, 0xb6, 0xa1, 0x87, 0x47, 0x53, 0x19,
-       0xc5, 0xbd, 0x51, 0x66, 0x1d, 0x94, 0xb4, 0x41, 0x9a, 0x4f, 0xe8, 0xf5,
-       0xd1, 0x8c, 0xbc, 0x2c, 0x99, 0xa6, 0x76, 0xd8, 0x5d, 0xff, 0xb6, 0x73,
-       0x6c, 0xee, 0x2e, 0xd0, 0x34, 0x07, 0xdd, 0xc4, 0x7d, 0xca, 0x9d, 0xf2,
-       0x5e, 0x9e, 0x57, 0x98, 0x70, 0xa0, 0x94, 0x9f, 0xd2, 0x7b, 0xbf, 0x77,
-       0x14, 0x57, 0xcb, 0xad, 0xa9, 0xa8, 0x5d, 0xe7, 0xac, 0x05, 0x1d, 0x40,
-       0x50, 0x9f, 0xaa, 0xc5, 0x13, 0x75, 0x38, 0x7f, 0x17, 0x53, 0x99, 0xa4,
-       0x22, 0xb3, 0xc3, 0xe7, 0x9f, 0x91, 0x2d, 0xde, 0x1e, 0x7d, 0xce, 0x4e,
-       0x9c, 0xba, 0x53, 0x7f, 0xe9, 0xd1, 0x06, 0x25, 0xfd, 0xcc, 0xf8, 0xb5,
-       0x7a, 0x5d, 0xab, 0x3f, 0x15, 0x04, 0x39, 0xcc, 0x5f, 0x41, 0x4c, 0xfc,
-       0x6c, 0xc2, 0x67, 0x1a, 0xfd, 0xda, 0x06, 0xa7, 0xf6, 0x4c, 0xa3, 0x63,
-       0x68, 0x45, 0x22, 0x2a, 0x5d, 0xef, 0xd4, 0x9c, 0xba, 0x93, 0x73, 0x06,
-       0xba, 0xf2, 0x1c, 0x43, 0x57, 0x31, 0x67, 0x9e, 0xae, 0xd6, 0xd9, 0xdf,
-       0x2a, 0x5d, 0x27, 0x99, 0x64, 0x1d, 0xc6, 0xdb, 0x5b, 0x0c, 0x61, 0x3c,
-       0x0c, 0xb8, 0x08, 0xcf, 0xdd, 0x18, 0xc3, 0x30, 0x9e, 0x3c, 0x60, 0x01,
-       0xb3, 0x9f, 0x2a, 0x00, 0xe6, 0x83, 0x78, 0x18, 0x27, 0x6b, 0x76, 0x22,
-       0x13, 0xd5, 0xf0, 0x12, 0xc6, 0x1f, 0x5b, 0x78, 0x5f, 0x0f, 0x56, 0x4f,
-       0x66, 0xba, 0x8b, 0x80, 0x87, 0x70, 0xde, 0x07, 0x18, 0x69, 0x97, 0x8e,
-       0xe2, 0xdb, 0x03, 0x7c, 0x63, 0x16, 0x26, 0xd0, 0xe3, 0xd8, 0x43, 0xf3,
-       0xbf, 0x8b, 0xb4, 0x93, 0x8f, 0xd9, 0xef, 0xd6, 0x45, 0x32, 0xe0, 0x15,
-       0x87, 0x78, 0x1e, 0x29, 0xbd, 0xe6, 0xc0, 0x0e, 0x00, 0xdf, 0xbf, 0xe4,
-       0x44, 0xce, 0xc4, 0xe5, 0x50, 0x91, 0x31, 0x84, 0xe3, 0x0e, 0xe7, 0x41,
-       0xf9, 0x57, 0xa1, 0x4c, 0x5c, 0xc9, 0xc4, 0xd5, 0x78, 0xde, 0x82, 0x67,
-       0x03, 0x9e, 0x8d, 0x78, 0xd6, 0xe3, 0x69, 0xc5, 0xf3, 0x2d, 0x94, 0x53,
-       0xb1, 0x3a, 0xe1, 0x7e, 0xd5, 0x16, 0xa5, 0x34, 0x1f, 0x71, 0xcf, 0xc2,
-       0x65, 0xc0, 0xe5, 0x2b, 0xd0, 0x3b, 0x1e, 0x9e, 0xf1, 0xf8, 0x3a, 0xfa,
-       0x98, 0xc5, 0xd3, 0xa9, 0xe4, 0x4c, 0x17, 0x9e, 0x14, 0x9e, 0x6e, 0x3c,
-       0x3d, 0x78, 0xd2, 0x78, 0x5e, 0x75, 0x0c, 0xcf, 0x5d, 0x02, 0xbe, 0x42,
-       0x1e, 0x01, 0xce, 0x17, 0xf0, 0x9c, 0xe7, 0xbc, 0x09, 0x9e, 0x73, 0x2c,
-       0xcf, 0x39, 0xf3, 0x3c, 0x57, 0xeb, 0xa8, 0x63, 0xf5, 0x4e, 0xe4, 0x18,
-       0x7d, 0x85, 0x5a, 0xc7, 0xf0, 0x7f, 0x44, 0x7a, 0x07, 0x41, 0x4b, 0xc7,
-       0x30, 0x67, 0xc7, 0x48, 0x57, 0x2e, 0xd2, 0xc7, 0x16, 0xf5, 0x3b, 0xfa,
-       0x26, 0xfa, 0x3d, 0x61, 0xfb, 0x7d, 0xb8, 0xaa, 0xdf, 0x83, 0x68, 0xfb,
-       0x3e, 0xdb, 0xef, 0xc1, 0xaa, 0x7e, 0x41, 0x2b, 0xc7, 0xf2, 0x78, 0x48,
-       0x17, 0x23, 0x48, 0x0f, 0x65, 0xc2, 0xdd, 0x6b, 0xa4, 0xbe, 0x46, 0x9f,
-       0x27, 0x8d, 0xf9, 0x35, 0x73, 0xba, 0x31, 0x53, 0xa5, 0x1f, 0x7e, 0x16,
-       0xfd, 0x38, 0x5c, 0xa2, 0x8d, 0x38, 0x5d, 0x25, 0x17, 0xe8, 0xfb, 0x04,
-       0x72, 0x5c, 0xfb, 0x39, 0xf4, 0x79, 0xe8, 0xff, 0x2c, 0xb6, 0xad, 0x3e,
-       0xae, 0xf7, 0xe7, 0xde, 0x55, 0x6c, 0x95, 0x4f, 0x14, 0x69, 0x13, 0x92,
-       0x5e, 0x82, 0x60, 0xcf, 0x36, 0xda, 0xa7, 0xf9, 0x60, 0x9d, 0x9f, 0xd4,
-       0xb1, 0xb5, 0x4f, 0x2e, 0xd5, 0x19, 0xa3, 0xbd, 0xf0, 0xcd, 0xb3, 0x47,
-       0x3f, 0x08, 0x9d, 0x51, 0x03, 0xb8, 0x9f, 0xd2, 0x77, 0x80, 0xec, 0x1a,
-       0x55, 0x23, 0x6b, 0x25, 0x2e, 0x37, 0x17, 0x6b, 0x61, 0xf7, 0x30, 0x56,
-       0x5e, 0x2f, 0xed, 0xdb, 0xa2, 0xe6, 0x6c, 0x8d, 0x17, 0xc3, 0x6f, 0xcf,
-       0x9c, 0xf5, 0x89, 0xc5, 0x91, 0x1f, 0x69, 0xa2, 0x1c, 0x8c, 0xf9, 0xef,
-       0xd4, 0xfb, 0x26, 0xdb, 0xb6, 0xd1, 0x6e, 0xb9, 0x41, 0xeb, 0x70, 0x77,
-       0x89, 0x9d, 0xa4, 0x5a, 0x3c, 0x99, 0xb7, 0xd1, 0x76, 0x17, 0x93, 0x09,
-       0xc2, 0xf5, 0x90, 0x70, 0x3f, 0xc1, 0x7e, 0x29, 0xa4, 0x1a, 0x25, 0x92,
-       0xe6, 0xba, 0x5c, 0xb2, 0x93, 0xb6, 0xd1, 0xc4, 0x98, 0x67, 0xcf, 0x9e,
-       0xac, 0x96, 0x0b, 0xba, 0x9f, 0x5a, 0x0d, 0xa3, 0x39, 0x8f, 0xc6, 0x35,
-       0x2f, 0x9e, 0x81, 0x72, 0xf1, 0x6e, 0xd0, 0x7a, 0x67, 0xa2, 0xcc, 0xb3,
-       0x4e, 0xf0, 0x97, 0xca, 0x31, 0x7d, 0xc6, 0xd4, 0x7b, 0x3b, 0xfc, 0xd8,
-       0xf2, 0x06, 0xd9, 0x3d, 0xb6, 0x82, 0xeb, 0x28, 0xb1, 0xb5, 0xd0, 0x1f,
-       0xac, 0xd3, 0xb6, 0x0d, 0xfe, 0xdf, 0xf8, 0x46, 0x79, 0x7c, 0x9c, 0x6d,
-       0xb7, 0xc8, 0xe4, 0x94, 0x38, 0xde, 0xdb, 0x57, 0xa2, 0x8c, 0xc7, 0xf1,
-       0x08, 0xf7, 0x3c, 0xb5, 0x6d, 0x13, 0xe5, 0xbd, 0xdd, 0x95, 0xf3, 0xdd,
-       0x11, 0xbd, 0x26, 0xe3, 0x82, 0x4e, 0xd8, 0xde, 0xf9, 0xee, 0x56, 0x39,
-       0x3b, 0x05, 0x9a, 0x80, 0xdc, 0xef, 0x3b, 0x45, 0x98, 0x44, 0xb6, 0x4f,
-       0xc0, 0x5e, 0x90, 0x76, 0x3c, 0xa0, 0x0f, 0xc8, 0xef, 0x5b, 0xbb, 0xd9,
-       0x17, 0xf4, 0x12, 0x74, 0x5c, 0xdb, 0x36, 0x23, 0x0b, 0x32, 0x13, 0x35,
-       0x48, 0x67, 0xbb, 0xf0, 0x0f, 0x07, 0xd9, 0x4e, 0x58, 0x57, 0x61, 0x4c,
-       0xb5, 0x9a, 0x5e, 0x66, 0x17, 0xe9, 0x8f, 0x73, 0x3f, 0x97, 0xfd, 0xcd,
-       0x36, 0x3a, 0x41, 0x2b, 0xbe, 0xde, 0xc3, 0x63, 0x6c, 0x2b, 0xce, 0x09,
-       0x6d, 0x22, 0xda, 0x55, 0xd7, 0x6a, 0xfb, 0x62, 0xb2, 0xc2, 0x19, 0xe4,
-       0xda, 0x48, 0x38, 0x47, 0x71, 0x39, 0x59, 0x9a, 0x9b, 0xa7, 0x0d, 0x35,
-       0x0b, 0xe7, 0x89, 0xb4, 0x92, 0x1a, 0xb2, 0xb6, 0xc7, 0x8c, 0x3c, 0x0f,
-       0xbb, 0xac, 0x53, 0xcf, 0xd9, 0x0c, 0x6c, 0x59, 0x3b, 0x67, 0xda, 0x9e,
-       0x2d, 0x84, 0x73, 0x36, 0x00, 0x8d, 0x53, 0xbe, 0x41, 0xcf, 0x99, 0x07,
-       0xba, 0xc9, 0x03, 0xef, 0x79, 0xcc, 0x53, 0x1e, 0x73, 0x94, 0x2f, 0xb7,
-       0xc8, 0xc4, 0x71, 0xd5, 0x5a, 0x23, 0x92, 0xd8, 0xed, 0xb7, 0xc8, 0xf0,
-       0x14, 0x63, 0x05, 0x1b, 0x60, 0x83, 0x6d, 0xc4, 0xd3, 0x8a, 0x6f, 0xd6,
-       0xe3, 0x1d, 0x1f, 0x0a, 0x75, 0xeb, 0x96, 0xd8, 0x59, 0x67, 0xd1, 0xf7,
-       0xd3, 0xc0, 0xc3, 0xa3, 0xc0, 0xc3, 0x3c, 0xef, 0xbc, 0x50, 0x15, 0x5f,
-       0xe2, 0x58, 0xb5, 0x0e, 0xc5, 0x78, 0x63, 0x7a, 0x3e, 0x75, 0x9c, 0xa9,
-       0x54, 0xfb, 0x66, 0xec, 0xa9, 0x38, 0xed, 0xa9, 0xdc, 0xa8, 0x67, 0xce,
-       0x60, 0x0d, 0xc0, 0x77, 0xf2, 0xf7, 0x69, 0x5a, 0x1f, 0x1a, 0x27, 0x5c,
-       0xd1, 0x10, 0xae, 0x05, 0x73, 0xc6, 0x33, 0xb3, 0x4b, 0xe3, 0x18, 0x2f,
-       0xcc, 0xed, 0x11, 0x87, 0x2e, 0x97, 0xd1, 0x14, 0xe3, 0x24, 0xad, 0xcb,
-       0xc0, 0xf4, 0x94, 0xb6, 0x61, 0x45, 0x9d, 0x96, 0x03, 0x25, 0x9e, 0xb7,
-       0xe5, 0x1a, 0xcc, 0xef, 0x31, 0x7e, 0xd4, 0x39, 0x21, 0xc7, 0xd0, 0x37,
-       0xd7, 0xc5, 0x95, 0x8d, 0xcf, 0xac, 0xb2, 0x7b, 0xf2, 0xaa, 0x63, 0x34,
-       0x66, 0xdd, 0x7c, 0xe1, 0xd9, 0x93, 0xe4, 0xc0, 0xac, 0x5e, 0x77, 0xe5,
-       0x9a, 0xa1, 0x8c, 0x46, 0xa0, 0xfd, 0x76, 0x77, 0x27, 0x7b, 0xcc, 0x59,
-       0xc3, 0x84, 0xf4, 0x97, 0xcc, 0xf8, 0x2f, 0xea, 0x7d, 0x93, 0x66, 0x7f,
-       0xb8, 0xd9, 0x53, 0xb9, 0x5f, 0x2e, 0xa6, 0xa2, 0x55, 0x73, 0x5b, 0x27,
-       0xc3, 0xc0, 0x85, 0x5e, 0xcb, 0x84, 0x5d, 0x9c, 0xeb, 0x7e, 0xbc, 0x89,
-       0x67, 0xd1, 0xa2, 0x98, 0x9f, 0xc2, 0x38, 0xcf, 0xa7, 0xb3, 0xdd, 0x2b,
-       0xb5, 0x45, 0x31, 0xcb, 0xb3, 0x4e, 0x90, 0x95, 0x6f, 0xdd, 0x12, 0xaf,
-       0xd7, 0xf9, 0x2b, 0xec, 0x99, 0x16, 0xd8, 0x0d, 0xbb, 0x02, 0xf9, 0x33,
-       0xe8, 0xc9, 0xd3, 0x76, 0x4c, 0x09, 0x1d, 0x93, 0x92, 0xe0, 0x7c, 0x2a,
-       0x6e, 0xe3, 0xce, 0x1c, 0xcb, 0x98, 0xa5, 0x6f, 0x63, 0xff, 0xcc, 0xdb,
-       0xd0, 0x5d, 0x9a, 0xd6, 0x1f, 0xd7, 0xb2, 0xb0, 0xcb, 0xda, 0xce, 0x3a,
-       0x8e, 0x73, 0x42, 0xf4, 0x1e, 0xac, 0xd0, 0x37, 0xea, 0xa8, 0xf2, 0x0b,
-       0x8c, 0x2f, 0x57, 0x18, 0x5b, 0x4e, 0x46, 0xcd, 0xfb, 0x84, 0xf4, 0xe5,
-       0xf6, 0x6c, 0xe2, 0xdd, 0x30, 0xa1, 0x2f, 0xd7, 0x65, 0x7d, 0xb9, 0x46,
-       0xed, 0xcb, 0x99, 0xd8, 0x43, 0xe3, 0x9c, 0x2f, 0x57, 0x18, 0xcb, 0x83,
-       0x56, 0x6a, 0xed, 0x59, 0x09, 0x63, 0x0b, 0x0d, 0x17, 0x5d, 0xbd, 0x6f,
-       0x24, 0x37, 0xa0, 0xe0, 0x37, 0x18, 0x1f, 0x8b, 0xb1, 0x0a, 0xa5, 0xfe,
-       0xce, 0xfa, 0x17, 0x1b, 0x24, 0xd3, 0xbc, 0x02, 0xe3, 0x7e, 0x4a, 0xcf,
-       0xb9, 0x59, 0xc3, 0x82, 0x5c, 0x1b, 0x64, 0xcc, 0x87, 0x67, 0x47, 0x35,
-       0x7f, 0x25, 0x7a, 0x23, 0x9d, 0xc6, 0x9e, 0xf5, 0x13, 0x6b, 0xa5, 0xfe,
-       0xb8, 0x53, 0x18, 0x8f, 0xda, 0x7e, 0x13, 0x80, 0xa9, 0x06, 0x73, 0xf3,
-       0x4e, 0x2b, 0x93, 0xd9, 0xf7, 0x3b, 0xea, 0x18, 0x1b, 0x98, 0x2a, 0x9a,
-       0x18, 0x60, 0x5f, 0x31, 0x12, 0x9e, 0x5b, 0x57, 0x5c, 0x47, 0xce, 0x0c,
-       0xae, 0x00, 0x2c, 0x2b, 0x96, 0xb5, 0x59, 0x1f, 0x7b, 0x43, 0x1d, 0x45,
-       0x9a, 0x7a, 0x4a, 0xef, 0x2f, 0x5c, 0xd9, 0x9d, 0xdc, 0xa9, 0xcf, 0x23,
-       0xe9, 0x58, 0x62, 0x5e, 0xb8, 0x7f, 0xf7, 0x9b, 0xf2, 0x36, 0x2d, 0xfb,
-       0x0f, 0xa4, 0xa8, 0xc7, 0xb6, 0xe9, 0xdf, 0xb5, 0xe9, 0x20, 0x38, 0xdf,
-       0xfd, 0x2c, 0x6c, 0x16, 0xdf, 0xfb, 0x96, 0xb4, 0xc7, 0x7b, 0xb5, 0x0d,
-       0x85, 0xb9, 0x1a, 0xac, 0x97, 0x15, 0xfe, 0xb8, 0xdd, 0xab, 0x68, 0xd6,
-       0x03, 0x0b, 0xc2, 0xfb, 0x17, 0x3a, 0x6c, 0x5e, 0x3e, 0xa8, 0x07, 0x3d,
-       0x7d, 0x44, 0x8c, 0xac, 0xc9, 0xcd, 0xcb, 0x1a, 0xee, 0xa7, 0xcb, 0x90,
-       0xa0, 0xdd, 0x23, 0x92, 0xe4, 0xdd, 0x49, 0xec, 0xbb, 0x20, 0x57, 0x41,
-       0x3f, 0xb3, 0x1e, 0x6d, 0x56, 0x7e, 0x73, 0x0f, 0x8a, 0xef, 0x1d, 0x84,
-       0x8e, 0xb9, 0x61, 0xa9, 0x8e, 0x89, 0xd3, 0xbf, 0xcf, 0x8d, 0xd2, 0x47,
-       0x5c, 0x89, 0x3a, 0x2d, 0xf2, 0xd1, 0xb1, 0xdf, 0x5a, 0x4b, 0x1e, 0x1b,
-       0x82, 0x7c, 0x57, 0xf7, 0x87, 0xe7, 0x2e, 0x99, 0xc6, 0x7c, 0xb6, 0x5b,
-       0x27, 0x89, 0xf7, 0x79, 0xf2, 0xc5, 0x4a, 0x32, 0x31, 0x0b, 0x1d, 0x35,
-       0xe4, 0x0c, 0xb7, 0x9a, 0xd8, 0xe9, 0xa7, 0xd6, 0x9a, 0x73, 0x5a, 0xf5,
-       0xc0, 0x69, 0x18, 0x4f, 0xad, 0xa6, 0xdd, 0x59, 0x2b, 0x97, 0x83, 0xa0,
-       0xbe, 0x5b, 0xcb, 0xe2, 0x9d, 0x94, 0xc5, 0x07, 0x52, 0x1d, 0x86, 0x07,
-       0xb4, 0xef, 0xc4, 0x3d, 0x00, 0xc0, 0x43, 0xb7, 0xcb, 0xbd, 0xd0, 0x96,
-       0x4f, 0xfd, 0xcc, 0x8c, 0x95, 0x4f, 0xca, 0x59, 0xca, 0x9f, 0x6a, 0x6b,
-       0x74, 0x81, 0xec, 0x3d, 0x34, 0x46, 0xbd, 0x9c, 0x9a, 0xfe, 0x26, 0xe4,
-       0x55, 0x4e, 0xe3, 0xa1, 0x45, 0xee, 0x1b, 0x93, 0xcc, 0x45, 0xe8, 0xac,
-       0xc2, 0xd4, 0x42, 0x1e, 0x5d, 0xda, 0x1e, 0xc7, 0x7a, 0x7a, 0xad, 0xf1,
-       0x71, 0x17, 0x8e, 0x75, 0x9a, 0x7b, 0x8c, 0xf4, 0x58, 0xb9, 0x37, 0xff,
-       0x9c, 0x1d, 0xeb, 0xca, 0x70, 0xac, 0x3d, 0x0b, 0xc7, 0x1a, 0xfa, 0xf8,
-       0xa1, 0xfc, 0x4d, 0xe8, 0xb3, 0x49, 0xfa, 0x4c, 0xcc, 0xd8, 0x4a, 0xe9,
-       0x1d, 0x6d, 0xb4, 0x72, 0xd3, 0x83, 0x0e, 0xe2, 0x79, 0xa1, 0xe9, 0xcf,
-       0x79, 0x62, 0x71, 0xa6, 0x88, 0x07, 0xca, 0xdc, 0x26, 0x7d, 0x9e, 0x71,
-       0x02, 0x7e, 0xd6, 0x87, 0x8b, 0x2c, 0x1b, 0xe6, 0x5f, 0x29, 0x46, 0x1c,
-       0xfa, 0xd6, 0xf4, 0x9f, 0x3a, 0x97, 0xc4, 0x16, 0x4c, 0x1c, 0x98, 0xf1,
-       0x5f, 0x73, 0xcf, 0x02, 0xf7, 0x7d, 0xdf, 0x01, 0xde, 0xfa, 0xed, 0x62,
-       0xb2, 0x27, 0x1b, 0xa1, 0x3c, 0x9d, 0x95, 0x43, 0x95, 0x3e, 0x69, 0xd3,
-       0x67, 0xed, 0xdf, 0x30, 0x46, 0x9c, 0xa9, 0x8e, 0x11, 0x8b, 0x63, 0x62,
-       0xc4, 0x3b, 0x7f, 0x8e, 0x18, 0xb1, 0x38, 0x26, 0x46, 0xbc, 0x9c, 0x9f,
-       0x35, 0x52, 0x9a, 0xc5, 0xb8, 0xea, 0x21, 0x53, 0x94, 0x93, 0x9b, 0x6a,
-       0xc0, 0xbb, 0x16, 0x6f, 0xc0, 0x32, 0x56, 0xc0, 0xdb, 0xc3, 0xfb, 0x20,
-       0xde, 0x31, 0x19, 0x99, 0xd3, 0x1d, 0xb3, 0x90, 0x1f, 0xd4, 0x69, 0xac,
-       0x6b, 0xfc, 0x82, 0xc9, 0x72, 0x33, 0xca, 0x5d, 0x72, 0x26, 0x58, 0xaf,
-       0xd4, 0x28, 0xc3, 0x63, 0x94, 0xdd, 0x4d, 0x32, 0x3a, 0x16, 0xda, 0xb8,
-       0x9f, 0x5d, 0xcf, 0xb5, 0x81, 0x21, 0x09, 0x6d, 0xd8, 0x67, 0xd6, 0x9b,
-       0xb5, 0xdb, 0x2d, 0x31, 0xa9, 0x5f, 0x8d, 0x39, 0x38, 0xee, 0x5c, 0x1c,
-       0x5f, 0xbd, 0xc0, 0x96, 0x4d, 0xd8, 0xd8, 0xe0, 0xb8, 0xd5, 0xc1, 0xcb,
-       0xcb, 0x88, 0xea, 0xf9, 0x8f, 0xdb, 0x73, 0xbc, 0x51, 0x7b, 0xd7, 0x5f,
-       0x42, 0xcf, 0xcf, 0x40, 0x65, 0x16, 0xfd, 0xad, 0x57, 0x99, 0x71, 0x8e,
-       0x73, 0xee, 0x7e, 0x1e, 0xc8, 0xc5, 0x56, 0x35, 0x34, 0xbe, 0x80, 0x2e,
-       0x41, 0xb7, 0x1c, 0x9b, 0x03, 0xda, 0xbd, 0x57, 0x26, 0x46, 0x09, 0x5f,
-       0x47, 0x3c, 0xa2, 0xcf, 0xf5, 0xe2, 0x7b, 0xdc, 0x9c, 0x27, 0xea, 0xad,
-       0x84, 0x67, 0x7a, 0xd7, 0x00, 0xde, 0xc5, 0xe7, 0x7a, 0xad, 0x9e, 0xd6,
-       0x36, 0x04, 0xcf, 0xf7, 0x86, 0x63, 0x58, 0x8e, 0x9e, 0x02, 0x19, 0xd6,
-       0xfb, 0x7d, 0xd7, 0xca, 0xe9, 0x07, 0xe7, 0xce, 0x17, 0x34, 0xc1, 0x56,
-       0x69, 0x85, 0xa9, 0x3c, 0xe0, 0xa6, 0xb9, 0xef, 0x82, 0xfb, 0x0b, 0x3a,
-       0xe2, 0xb7, 0xe9, 0x73, 0x1f, 0xf3, 0x67, 0xac, 0xe7, 0xcf, 0x7e, 0x84,
-       0x67, 0x5a, 0xe3, 0xd2, 0x07, 0x3a, 0xec, 0xd7, 0xe9, 0x31, 0x8c, 0x87,
-       0x6b, 0xbe, 0x1a, 0x0f, 0x90, 0x3d, 0x5c, 0xfb, 0xc5, 0xd8, 0x2b, 0x2d,
-       0x2a, 0xa7, 0xcf, 0x58, 0x47, 0x2d, 0x8d, 0x5d, 0x76, 0xf6, 0x94, 0x13,
-       0x6a, 0x4f, 0xd9, 0x57, 0x7b, 0xcb, 0x36, 0xaf, 0xfb, 0x01, 0xcc, 0x07,
-       0x7e, 0x8f, 0x17, 0x9d, 0x21, 0xe0, 0xab, 0x50, 0x3a, 0xe2, 0x64, 0xf4,
-       0xfb, 0xa8, 0x7d, 0x43, 0x0e, 0x60, 0xae, 0x7a, 0xc7, 0xa3, 0x5a, 0xde,
-       0xcf, 0xdf, 0xd3, 0x17, 0xce, 0xeb, 0x0b, 0x7a, 0x0d, 0x68, 0x5a, 0x88,
-       0x6b, 0xcf, 0xda, 0x10, 0xc7, 0x9d, 0x9c, 0xc6, 0x3d, 0xcb, 0x7c, 0x4b,
-       0xff, 0x06, 0x9d, 0x2b, 0xd3, 0x5e, 0x2b, 0xde, 0x8b, 0xf7, 0x4d, 0x86,
-       0xfa, 0x86, 0x70, 0xdf, 0x09, 0xbd, 0x16, 0xec, 0x37, 0xf2, 0x6a, 0x56,
-       0x46, 0x2a, 0x5c, 0xc3, 0x64, 0x3b, 0x48, 0x2f, 0xd7, 0xc0, 0x1e, 0x58,
-       0x78, 0xbe, 0xba, 0x7f, 0x7e, 0x1e, 0x12, 0xe3, 0x42, 0x58, 0xee, 0xd6,
-       0x67, 0x17, 0xab, 0xef, 0x1e, 0xb9, 0xf2, 0xbf, 0x70, 0xfd, 0xd0, 0xc8,
-       0x50, 0x0b, 0x47, 0x86, 0xf2, 0xce, 0xc8, 0x95, 0xaf, 0xcb, 0x41, 0xe0,
-       0xf1, 0x30, 0x60, 0x52, 0xf7, 0xf3, 0xce, 0xab, 0x57, 0xa5, 0x30, 0x59,
-       0x2f, 0xea, 0xa1, 0x82, 0xe3, 0x3e, 0x54, 0x2b, 0x91, 0x87, 0x94, 0x53,
-       0xf3, 0x50, 0xbb, 0xf6, 0xcf, 0x77, 0xa4, 0xda, 0xe3, 0x7b, 0xe5, 0xb8,
-       0xe3, 0xde, 0xaf, 0xf4, 0x59, 0xdb, 0x82, 0xc7, 0x58, 0xdf, 0x71, 0x27,
-       0x72, 0x7f, 0xd4, 0x9e, 0xd3, 0x37, 0xf1, 0xbd, 0x59, 0xcd, 0xf7, 0xdf,
-       0x58, 0x47, 0x9c, 0xcd, 0x0a, 0xf1, 0xf1, 0x59, 0xc8, 0xad, 0x4f, 0x4b,
-       0x76, 0x34, 0x31, 0x57, 0xc6, 0xec, 0xb3, 0xdf, 0xb0, 0xce, 0xf0, 0x0b,
-       0xcb, 0xbc, 0xe2, 0xf0, 0xce, 0x1c, 0xa3, 0x33, 0x3e, 0xdf, 0x12, 0xee,
-       0xb9, 0x37, 0x73, 0xca, 0xfc, 0xc6, 0x75, 0x52, 0xff, 0x0a, 0xe6, 0x8b,
-       0xfd, 0x11, 0x57, 0xab, 0xf4, 0x3d, 0x05, 0x9e, 0x6c, 0x89, 0xd7, 0xcd,
-       0xd9, 0x43, 0x46, 0xf6, 0xd6, 0x01, 0x6e, 0xc0, 0x6f, 0xec, 0x3b, 0x21,
-       0x9d, 0x0a, 0x24, 0x37, 0x69, 0xb6, 0xa3, 0x67, 0x87, 0x98, 0x39, 0x33,
-       0x34, 0xb3, 0xc2, 0xd8, 0x91, 0xf8, 0x36, 0x74, 0xa1, 0x64, 0xfb, 0xd8,
-       0x4b, 0x4e, 0x3f, 0xcf, 0x3c, 0x8a, 0xb6, 0x1b, 0x97, 0xb3, 0x09, 0xc1,
-       0x4b, 0xcf, 0x5b, 0xff, 0x32, 0x08, 0xc6, 0x52, 0x29, 0xde, 0x2b, 0xb8,
-       0x8c, 0x4f, 0xb9, 0xca, 0x99, 0x1c, 0x6d, 0x70, 0x26, 0x46, 0x03, 0xd9,
-       0x93, 0xe2, 0x9d, 0x49, 0xdc, 0x93, 0xa0, 0xe3, 0xe3, 0x48, 0x6b, 0x87,
-       0x6e, 0x7d, 0xc7, 0x3a, 0xee, 0x71, 0xbb, 0xd9, 0x6f, 0xb4, 0xe5, 0x88,
-       0x63, 0xfa, 0xca, 0xed, 0x27, 0x72, 0xc2, 0xbb, 0x8b, 0xb6, 0xc4, 0x63,
-       0x7a, 0x7f, 0xe2, 0x17, 0x50, 0x0f, 0x7d, 0x94, 0xd8, 0xaf, 0xeb, 0x4c,
-       0x40, 0x9e, 0x4d, 0x8e, 0xf1, 0xbe, 0x14, 0x9e, 0x63, 0x88, 0xb4, 0x2a,
-       0xb9, 0xd6, 0x1b, 0xb6, 0xf7, 0x69, 0xe6, 0xe1, 0x0a, 0x45, 0x74, 0xda,
-       0x16, 0x6f, 0xf7, 0xdc, 0x1d, 0x9b, 0x61, 0x5a, 0x78, 0xd7, 0xa6, 0xd2,
-       0x67, 0x56, 0xe0, 0xd3, 0x9e, 0x1e, 0x92, 0xb8, 0x33, 0x55, 0x6c, 0x75,
-       0x4e, 0x16, 0x33, 0x5b, 0xd7, 0x81, 0x3e, 0xce, 0xa7, 0x3e, 0x46, 0xf9,
-       0x05, 0xdb, 0xef, 0x45, 0xc9, 0x57, 0x3e, 0x24, 0xe3, 0x2d, 0xed, 0xde,
-       0xfd, 0x7a, 0x6e, 0x2e, 0x03, 0x67, 0x2d, 0x2a, 0x3b, 0xfa, 0xc4, 0x3a,
-       0xea, 0xb7, 0xdd, 0x45, 0x05, 0x5e, 0x56, 0xbf, 0x88, 0x07, 0x36, 0x6e,
-       0xad, 0xb6, 0x51, 0xf6, 0xa6, 0x58, 0xae, 0xc1, 0xe9, 0x1d, 0x5d, 0x85,
-       0x79, 0xdc, 0x05, 0xfd, 0xe9, 0xc0, 0x46, 0x22, 0xae, 0x1b, 0x9c, 0x3d,
-       0xa3, 0x79, 0xf4, 0xc8, 0x7d, 0xd6, 0xbc, 0xf7, 0xf0, 0x30, 0xc6, 0xa8,
-       0xe5, 0x2b, 0x78, 0xf7, 0x12, 0xd7, 0xdb, 0x83, 0x49, 0xd8, 0x06, 0xb9,
-       0xae, 0x7f, 0x67, 0xd7, 0xab, 0xa7, 0xaf, 0xb0, 0x5e, 0xed, 0xc9, 0x23,
-       0x15, 0x7d, 0x6f, 0x48, 0xe7, 0xb8, 0xe2, 0x3a, 0x6e, 0xf3, 0x55, 0x7a,
-       0x7e, 0x54, 0x87, 0xdd, 0x1b, 0x78, 0x72, 0x9d, 0xbd, 0xd3, 0x06, 0x70,
-       0x5c, 0x05, 0x18, 0x36, 0x62, 0xfc, 0x84, 0xc1, 0xd4, 0x11, 0x75, 0x4b,
-       0x9c, 0x3a, 0x70, 0x56, 0x4e, 0xaf, 0x0b, 0xf7, 0x7b, 0xa0, 0x1d, 0xc8,
-       0xb5, 0x47, 0xe3, 0x46, 0x37, 0xae, 0x5d, 0xa6, 0x9d, 0x70, 0x3c, 0x8e,
-       0x1d, 0x0f, 0x69, 0x75, 0x43, 0x0b, 0xfd, 0x89, 0x59, 0xa9, 0x5b, 0x54,
-       0x9e, 0xf1, 0xfc, 0x5d, 0xad, 0x66, 0xdf, 0x11, 0xcb, 0x7a, 0xb0, 0x4b,
-       0x69, 0xe3, 0x12, 0x77, 0x7a, 0xae, 0x8a, 0xdc, 0x5b, 0x9c, 0xf3, 0x2f,
-       0x43, 0x9e, 0x5c, 0xeb, 0xbd, 0x4d, 0x91, 0xf6, 0x42, 0xfc, 0x12, 0xb7,
-       0x09, 0xe0, 0x95, 0x71, 0x95, 0xd3, 0x41, 0x66, 0x80, 0x7c, 0xc5, 0x36,
-       0x98, 0xff, 0xa2, 0x8e, 0xe5, 0x0e, 0xa6, 0x18, 0x27, 0x6a, 0x3f, 0x71,
-       0x87, 0x0a, 0x65, 0xd3, 0x2c, 0xd7, 0x10, 0x1c, 0xde, 0x21, 0xba, 0x0b,
-       0x1d, 0x5e, 0x9c, 0x52, 0xce, 0x37, 0xc7, 0x5c, 0x7c, 0xd7, 0xd8, 0xfb,
-       0x42, 0x8d, 0x6e, 0x12, 0xf9, 0xeb, 0x70, 0xbc, 0xf1, 0x3c, 0xe6, 0xfb,
-       0x12, 0xe6, 0x7b, 0xf9, 0xfb, 0x41, 0x91, 0x57, 0x46, 0x5e, 0xf9, 0x43,
-       0x41, 0xa6, 0x89, 0xf4, 0x47, 0x9a, 0x7b, 0x3d, 0x9f, 0x59, 0xef, 0x63,
-       0x02, 0x6c, 0x67, 0xc1, 0x0b, 0x19, 0xae, 0x25, 0x07, 0xc7, 0x52, 0x37,
-       0x81, 0x17, 0x76, 0xca, 0x9f, 0xc0, 0x16, 0xf8, 0xe3, 0x4a, 0x1a, 0x3c,
-       0xd1, 0x03, 0x1e, 0xe9, 0x06, 0x5f, 0xa4, 0xb4, 0x5d, 0xfc, 0x28, 0x74,
-       0xde, 0xd9, 0x4a, 0xc9, 0xd9, 0x3b, 0x5a, 0x74, 0x72, 0xa3, 0x47, 0x41,
-       0x17, 0xdc, 0x03, 0xab, 0xae, 0xa9, 0x11, 0x37, 0x3e, 0x29, 0xa4, 0xff,
-       0x76, 0xee, 0xed, 0x68, 0x06, 0xae, 0xce, 0x10, 0x57, 0x93, 0x95, 0x2d,
-       0xde, 0x3a, 0xf0, 0x41, 0xb3, 0xe6, 0x83, 0x46, 0x27, 0xe3, 0xdd, 0x64,
-       0xf9, 0x60, 0x04, 0x7c, 0x50, 0x58, 0xc2, 0x07, 0xcf, 0x58, 0x9a, 0x9f,
-       0xae, 0xe2, 0x83, 0x49, 0x9b, 0x36, 0x7e, 0x05, 0x3e, 0xb8, 0xca, 0x4f,
-       0x3e, 0x39, 0x24, 0x27, 0xc0, 0x07, 0x0f, 0x6b, 0x3e, 0xb8, 0x4a, 0xf3,
-       0x01, 0xe3, 0x46, 0xe4, 0x85, 0x56, 0xc8, 0x0e, 0xf2, 0xc2, 0xb3, 0x32,
-       0x0b, 0x5e, 0x78, 0x51, 0xb1, 0xef, 0xcb, 0xb4, 0x0f, 0x46, 0xe9, 0x8f,
-       0x9d, 0x2a, 0x15, 0xc1, 0xbb, 0x4a, 0xbe, 0x30, 0x16, 0x04, 0x33, 0xf0,
-       0xd1, 0x1f, 0x84, 0x0d, 0xef, 0xea, 0x3b, 0x69, 0xa7, 0x61, 0xbb, 0x10,
-       0x36, 0xda, 0xe4, 0xe3, 0x0e, 0xe8, 0xfd, 0xf0, 0x04, 0xc6, 0xb0, 0x47,
-       0xfd, 0x3e, 0xfc, 0x60, 0x0f, 0xf3, 0x4a, 0xdb, 0xfe, 0xb8, 0xe6, 0x9b,
-       0x1a, 0xe8, 0x80, 0x93, 0xdd, 0x8c, 0x33, 0xf9, 0xde, 0x5e, 0xd5, 0x9e,
-       0xef, 0x03, 0xcc, 0x11, 0x75, 0xbf, 0x30, 0xc6, 0xd1, 0xb4, 0xc8, 0xb6,
-       0xa7, 0x5c, 0x18, 0x90, 0xfb, 0x6c, 0x5e, 0x3e, 0xa8, 0x83, 0x1d, 0x5a,
-       0xa7, 0x8c, 0x5d, 0xae, 0xb6, 0x25, 0xbd, 0xdf, 0x80, 0xd0, 0xac, 0x4d,
-       0x9b, 0x3d, 0x81, 0x7d, 0xc5, 0x6a, 0xbb, 0xfe, 0x5e, 0xd8, 0xf5, 0xac,
-       0x23, 0xae, 0xb1, 0xeb, 0xef, 0xb2, 0xbc, 0xc6, 0xdf, 0x9e, 0xb6, 0xf1,
-       0x0f, 0x00, 0xbe, 0x1d, 0x73, 0x36, 0x3e, 0xdb, 0xa0, 0xad, 0x21, 0x72,
-       0x03, 0xec, 0xbc, 0x1b, 0xc1, 0x83, 0x37, 0xc1, 0x8f, 0x7a, 0x77, 0xd1,
-       0x93, 0x9d, 0xc5, 0x66, 0xf8, 0xdb, 0xad, 0xf2, 0xab, 0x63, 0x1b, 0xa5,
-       0x7f, 0xf4, 0x77, 0x9a, 0xa1, 0x57, 0x61, 0x97, 0xbe, 0x08, 0x38, 0x23,
-       0x56, 0x56, 0x47, 0xc1, 0x03, 0xed, 0x89, 0x1f, 0xa8, 0x44, 0xab, 0x91,
-       0xed, 0x3c, 0x4b, 0xbe, 0x5c, 0x3b, 0x31, 0xd4, 0x67, 0x1c, 0xa5, 0x45,
-       0xce, 0x1c, 0xa7, 0xe7, 0x95, 0x80, 0x2d, 0x9e, 0x82, 0x1d, 0xb2, 0x01,
-       0xed, 0x31, 0x96, 0xbc, 0x5a, 0x9e, 0xd9, 0xea, 0xde, 0x9d, 0xd3, 0x7c,
-       0x78, 0xc9, 0xc9, 0x8e, 0xdd, 0x24, 0x85, 0xc1, 0x28, 0xc6, 0xa0, 0x9a,
-       0xd7, 0xca, 0xf5, 0xd2, 0xaf, 0xc7, 0x73, 0x59, 0x0e, 0x42, 0x1f, 0xff,
-       0x69, 0xb1, 0x5f, 0x66, 0x07, 0x9a, 0xf0, 0x1d, 0x95, 0x67, 0x8a, 0x5b,
-       0xe0, 0xef, 0xfc, 0x0a, 0x70, 0x54, 0x8b, 0xef, 0x5a, 0xe9, 0x5d, 0x47,
-       0x5e, 0x6d, 0x90, 0x19, 0xa4, 0xdf, 0x28, 0xbf, 0x64, 0xd3, 0x99, 0x46,
-       0xde, 0x68, 0x40, 0xdd, 0xa8, 0x9c, 0x2f, 0xd2, 0x96, 0xd4, 0x3c, 0xd1,
-       0xf3, 0xb2, 0x6c, 0xc9, 0xbc, 0x0c, 0xdb, 0xf4, 0x59, 0x3c, 0xcf, 0x4b,
-       0x72, 0xe7, 0x6e, 0x67, 0x4b, 0xa2, 0xdd, 0x81, 0xbe, 0xc4, 0xe3, 0x3a,
-       0x5b, 0xbc, 0x5a, 0xe7, 0x5a, 0xdb, 0x46, 0x8d, 0x3c, 0x3f, 0xa8, 0xe2,
-       0x0d, 0x98, 0x93, 0xcd, 0x4e, 0x87, 0x4d, 0xe3, 0xb7, 0xbe, 0x2f, 0x51,
-       0xda, 0xcf, 0xa8, 0x0d, 0xab, 0x44, 0xda, 0x1a, 0x60, 0xe7, 0xec, 0x11,
-       0xd5, 0xdc, 0x20, 0xae, 0xb4, 0x4f, 0xa8, 0x56, 0xa4, 0xf9, 0x36, 0x2d,
-       0xd6, 0x00, 0x9d, 0x80, 0xb4, 0x16, 0xa4, 0x6d, 0xb2, 0x69, 0x4d, 0x0d,
-       0x52, 0x8b, 0xb4, 0xcb, 0x9a, 0xe7, 0x2f, 0x76, 0xf8, 0x5e, 0xce, 0xa9,
-       0x97, 0xb6, 0x53, 0x0d, 0x90, 0x0d, 0xab, 0x65, 0x66, 0x6b, 0x9d, 0xb4,
-       0x21, 0x8f, 0x31, 0xee, 0xd4, 0xa9, 0xa8, 0xbc, 0xf3, 0x54, 0x7b, 0xfc,
-       0xa3, 0x18, 0x43, 0xfb, 0x19, 0xc6, 0xbc, 0xff, 0xac, 0x99, 0x31, 0x9f,
-       0xb6, 0x33, 0x7c, 0xd7, 0x69, 0xf9, 0x43, 0x7c, 0x98, 0x3b, 0xdf, 0x60,
-       0x63, 0x94, 0x8e, 0x3b, 0xc3, 0xa3, 0xd4, 0xdb, 0xed, 0xf6, 0x7e, 0xa2,
-       0xff, 0xd9, 0x4c, 0x5f, 0x6d, 0x82, 0x36, 0x54, 0x89, 0xfc, 0x48, 0xdd,
-       0x83, 0xf7, 0xb8, 0x23, 0x85, 0x79, 0x99, 0x35, 0x45, 0xbe, 0x3a, 0xae,
-       0xb8, 0x4f, 0x05, 0x69, 0x95, 0x77, 0x05, 0x66, 0x8e, 0xc9, 0x0b, 0x46,
-       0x2e, 0xfd, 0x9a, 0x91, 0x4b, 0xa7, 0xcf, 0x2d, 0x90, 0x4b, 0x05, 0x2d,
-       0x97, 0x06, 0x05, 0xef, 0xa9, 0x02, 0xe4, 0xd2, 0x08, 0xbe, 0x3d, 0x2d,
-       0x97, 0x62, 0x62, 0x6d, 0x64, 0x89, 0x5e, 0xc5, 0xfe, 0x27, 0x4b, 0xae,
-       0xb6, 0xa5, 0x0a, 0xe3, 0xb0, 0x43, 0x4a, 0x23, 0x56, 0x67, 0x4b, 0xba,
-       0x49, 0x3a, 0x7a, 0x7e, 0x2a, 0xa1, 0x9d, 0x39, 0xdb, 0xcc, 0x3b, 0x8f,
-       0x5f, 0x54, 0x94, 0x61, 0x27, 0x20, 0xc3, 0x1e, 0xbe, 0x82, 0x0c, 0x43,
-       0x5e, 0x19, 0x79, 0x65, 0xb6, 0xfb, 0xdd, 0x9f, 0x0e, 0x79, 0x94, 0x1f,
-       0x94, 0x19, 0x90, 0x49, 0x25, 0xc8, 0xa4, 0x12, 0xe4, 0x54, 0x09, 0x72,
-       0xa9, 0x04, 0xb9, 0x54, 0x82, 0x5c, 0x2a, 0x41, 0x2e, 0x41, 0xc6, 0x3d,
-       0x0a, 0x19, 0x67, 0x64, 0xda, 0x00, 0xed, 0x35, 0xb9, 0xcf, 0xea, 0x77,
-       0x13, 0x27, 0xe9, 0xb2, 0x7e, 0x91, 0xd9, 0xb3, 0x7a, 0xae, 0x2a, 0x2e,
-       0xb8, 0xeb, 0x88, 0xe6, 0x77, 0xcf, 0x57, 0xd7, 0x3a, 0xdc, 0x1f, 0xf3,
-       0x03, 0xed, 0xb3, 0x6f, 0xe6, 0x6f, 0xa9, 0x03, 0x5f, 0xbf, 0x62, 0xf9,
-       0x7a, 0xf3, 0x1c, 0x5f, 0x27, 0x1d, 0xc6, 0x89, 0x97, 0xe7, 0xeb, 0x16,
-       0x9b, 0x97, 0x0f, 0x56, 0x80, 0xaf, 0x57, 0x2c, 0xe2, 0xeb, 0x28, 0xf8,
-       0x7a, 0xe7, 0x12, 0xbe, 0x5e, 0xe5, 0xf4, 0xea, 0x3a, 0x3c, 0x83, 0xc6,
-       0xef, 0x5a, 0x67, 0x9e, 0xaf, 0xf7, 0x6b, 0xbe, 0x3e, 0x04, 0xbe, 0xbe,
-       0xbe, 0x8a, 0xaf, 0x77, 0x4a, 0xf2, 0x96, 0x6c, 0x64, 0xa3, 0xec, 0xbe,
-       0x5f, 0x35, 0xaf, 0x91, 0x7f, 0x11, 0x53, 0xdf, 0xf0, 0x58, 0xef, 0x58,
-       0xb3, 0xe4, 0x1e, 0xfa, 0x11, 0xd7, 0x06, 0xc8, 0x23, 0x43, 0x19, 0xc7,
-       0x93, 0x83, 0x47, 0x7e, 0x20, 0xd3, 0x9a, 0xb7, 0x44, 0xf6, 0x1c, 0x89,
-       0xca, 0xf0, 0x11, 0xc6, 0x1e, 0xbe, 0x63, 0xe9, 0xbd, 0x4e, 0x86, 0x07,
-       0xb9, 0x5f, 0xd2, 0x95, 0xdd, 0x47, 0xe0, 0x63, 0x1d, 0x61, 0xec, 0xe1,
-       0xf2, 0x1c, 0x8f, 0x4d, 0x43, 0xb6, 0xec, 0x3e, 0xa2, 0xe7, 0x1a, 0xed,
-       0x34, 0xc8, 0xa1, 0x23, 0x22, 0xb7, 0x1d, 0x71, 0xe5, 0xf6, 0x23, 0x73,
-       0xbc, 0x36, 0x10, 0xf2, 0xda, 0x9f, 0x83, 0xd7, 0xda, 0x2d, 0xaf, 0xa9,
-       0x39, 0x5e, 0xfb, 0x5a, 0x15, 0xaf, 0xb1, 0x3e, 0x79, 0xed, 0x82, 0x4d,
-       0xe3, 0xb7, 0x2b, 0x7b, 0x8f, 0xb4, 0xca, 0xee, 0x87, 0xde, 0x22, 0x7b,
-       0xee, 0x27, 0xac, 0xe6, 0x9e, 0x3c, 0xda, 0x5f, 0xe3, 0x95, 0x76, 0xb4,
-       0x1f, 0xee, 0x0f, 0xd2, 0x77, 0x65, 0x75, 0x4e, 0x48, 0x32, 0xcf, 0xfe,
-       0x6a, 0xe1, 0x3b, 0x9f, 0x82, 0x4f, 0xb1, 0x17, 0x30, 0xdd, 0x7a, 0x44,
-       0x92, 0xae, 0xbc, 0x26, 0x23, 0xa9, 0x47, 0x5b, 0x8d, 0x3d, 0x71, 0x09,
-       0xbc, 0x42, 0xfa, 0xcf, 0x48, 0xee, 0xed, 0x81, 0xf6, 0x2b, 0x46, 0xcb,
-       0x42, 0xff, 0x9f, 0x31, 0x73, 0xc7, 0xdc, 0x77, 0xc7, 0xf3, 0xbe, 0x35,
-       0xfa, 0xbc, 0x9b, 0x8e, 0xd7, 0x76, 0x33, 0xbf, 0x46, 0xef, 0x37, 0xcd,
-       0xe9, 0xb3, 0xdc, 0xac, 0xcf, 0x76, 0x62, 0x3a, 0x9e, 0x5e, 0x28, 0xf3,
-       0x8e, 0x30, 0xde, 0xbd, 0xcc, 0xbb, 0x06, 0xff, 0xf8, 0x2a, 0x13, 0x9b,
-       0x25, 0xdf, 0x7d, 0xdd, 0xc9, 0x15, 0x2f, 0xe9, 0x7d, 0x85, 0x59, 0x1f,
-       0xbf, 0xcb, 0xfc, 0x66, 0xf9, 0x4b, 0x8c, 0x71, 0x24, 0x12, 0xea, 0x81,
-       0x56, 0xee, 0x3b, 0x18, 0x9c, 0x32, 0x76, 0x94, 0xe1, 0xd1, 0x06, 0xed,
-       0x6b, 0x8c, 0xe0, 0x7b, 0xf7, 0x68, 0xa3, 0x53, 0xa0, 0x6d, 0x32, 0xd0,
-       0xe0, 0xe4, 0xc7, 0xf7, 0xb4, 0x1a, 0x9b, 0x79, 0x20, 0xce, 0x3d, 0x85,
-       0x19, 0xb5, 0x54, 0x26, 0x9f, 0x92, 0x50, 0x26, 0x27, 0x6f, 0xc9, 0xc0,
-       0xb6, 0xce, 0x1d, 0xd1, 0xf7, 0xf7, 0x25, 0xda, 0x15, 0xc7, 0xf4, 0x09,
-       0xc8, 0xd7, 0x90, 0x16, 0xe2, 0xf2, 0xf1, 0x23, 0xa4, 0x07, 0x15, 0x6b,
-       0x94, 0xdf, 0xb2, 0xf4, 0x70, 0x59, 0x8a, 0x90, 0x3b, 0x47, 0x8e, 0xdc,
-       0x2e, 0xe3, 0xbb, 0x16, 0xd3, 0xc3, 0x9e, 0x79, 0x7a, 0x88, 0xc1, 0x3e,
-       0x73, 0xaa, 0xe9, 0xe1, 0x37, 0xe7, 0xe8, 0x61, 0xdc, 0xf9, 0xd7, 0xd2,
-       0xc3, 0x0d, 0x0b, 0xe8, 0x61, 0x44, 0xd3, 0x43, 0xff, 0x1c, 0x3d, 0x8c,
-       0x1c, 0x61, 0xbf, 0x7a, 0x5d, 0xd4, 0x9b, 0x71, 0x38, 0xe7, 0x73, 0xb4,
-       0x90, 0x18, 0xd6, 0xfb, 0x44, 0x93, 0x79, 0x9e, 0x25, 0x5d, 0xa5, 0x18,
-       0x1b, 0x99, 0x9f, 0xff, 0xc6, 0x7f, 0xd3, 0xf9, 0x7f, 0x47, 0xfc, 0xff,
-       0xef, 0xfc, 0x5f, 0x8f, 0xf6, 0x29, 0x8b, 0x43, 0x79, 0x1c, 0xd2, 0xc3,
-       0x7b, 0xe2, 0x46, 0x2f, 0x70, 0x8e, 0xf9, 0x6d, 0xf6, 0xac, 0x9f, 0x83,
-       0xfc, 0x7b, 0x1c, 0xf2, 0xef, 0xb1, 0x05, 0xeb, 0x01, 0x3d, 0x36, 0x06,
-       0x11, 0xc8, 0xc1, 0xd4, 0x3c, 0x3e, 0x66, 0xba, 0x89, 0x0f, 0xb3, 0xf7,
-       0xe4, 0x6c, 0x65, 0x31, 0x4e, 0x5c, 0xbd, 0xdf, 0xe8, 0x64, 0xaa, 0x1a,
-       0x27, 0x84, 0x7b, 0xb6, 0x6a, 0x8c, 0xf8, 0x5d, 0xe6, 0xf7, 0x65, 0xbd,
-       0x87, 0xa4, 0xa0, 0xd7, 0x9f, 0x88, 0x17, 0xae, 0x3f, 0x11, 0x27, 0xae,
-       0xb6, 0xf7, 0x0b, 0xe5, 0x3a, 0xbd, 0x2f, 0xfc, 0xc0, 0x54, 0x4c, 0x66,
-       0x62, 0x8c, 0xeb, 0xf1, 0xde, 0x57, 0xfa, 0xca, 0x7e, 0xbc, 0x20, 0x79,
-       0x7b, 0xd6, 0x67, 0x95, 0xa5, 0x6d, 0xc6, 0x03, 0x79, 0x27, 0x42, 0xb8,
-       0x0e, 0xd1, 0x69, 0x65, 0x5d, 0x43, 0x55, 0x9c, 0x12, 0x78, 0x1f, 0x93,
-       0x44, 0xb6, 0x1b, 0xef, 0x29, 0xf6, 0xfd, 0xa4, 0x8c, 0x3c, 0x58, 0x86,
-       0x2d, 0xf7, 0x30, 0x74, 0x8e, 0x23, 0x10, 0x93, 0xfa, 0x2e, 0x14, 0xc2,
-       0x30, 0xa1, 0xef, 0xf5, 0xa3, 0xdf, 0x47, 0x7a, 0x88, 0xe3, 0xfb, 0xb2,
-       0x8d, 0x25, 0xc5, 0xa5, 0x50, 0xfc, 0x01, 0xe0, 0xe7, 0x1d, 0x94, 0x3f,
-       0xc2, 0xfb, 0x8d, 0xe6, 0xc3, 0xf8, 0x21, 0x03, 0xfa, 0xcd, 0xb9, 0x79,
-       0xcd, 0xc9, 0x94, 0xcd, 0xfe, 0x96, 0xaa, 0xfb, 0xf5, 0xe5, 0xb0, 0xb6,
-       0x9f, 0xd3, 0x76, 0x5f, 0x0b, 0xcf, 0xe7, 0x19, 0x1b, 0xfa, 0xcb, 0xb0,
-       0xa1, 0x9f, 0xa8, 0x64, 0xf4, 0x1a, 0xd6, 0x63, 0xb0, 0xa1, 0x1f, 0x85,
-       0xee, 0xa1, 0xce, 0x89, 0x59, 0x9d, 0x33, 0xa2, 0x76, 0x69, 0x9d, 0xf3,
-       0xd7, 0x5a, 0xe7, 0xfc, 0xea, 0x12, 0x9d, 0x73, 0x48, 0xb5, 0x8f, 0x52,
-       0xe7, 0xf4, 0xaa, 0x9d, 0x0e, 0xed, 0xc5, 0xb5, 0xcb, 0xe8, 0x9c, 0xf7,
-       0xca, 0xaf, 0xd8, 0xbc, 0xfd, 0xf2, 0xbe, 0x6d, 0x7a, 0xdd, 0xc6, 0x9b,
-       0x50, 0xbc, 0xcb, 0xce, 0xe8, 0xa0, 0xeb, 0x55, 0xa7, 0x5e, 0xef, 0xfd,
-       0x6a, 0x95, 0xce, 0x69, 0x53, 0xdd, 0x4e, 0xaf, 0xae, 0xc3, 0x78, 0x04,
-       0xbf, 0x53, 0x4e, 0x66, 0xa0, 0x0e, 0xdf, 0x71, 0x89, 0x1c, 0xc1, 0xd8,
-       0xcd, 0x7d, 0x7b, 0xca, 0xe4, 0x5d, 0x63, 0xf3, 0x54, 0x98, 0xee, 0x9a,
-       0xf4, 0x76, 0x9b, 0x6e, 0x74, 0x55, 0x9b, 0x6a, 0xd5, 0xba, 0x6a, 0x33,
-       0x18, 0x6a, 0x02, 0xfa, 0x75, 0xa2, 0x14, 0xea, 0x2c, 0xfe, 0x66, 0xbc,
-       0x99, 0x71, 0x89, 0x30, 0x6e, 0x9d, 0x40, 0x19, 0x3c, 0xa5, 0xd0, 0xa6,
-       0xe4, 0x6f, 0xf8, 0x0a, 0x78, 0xa6, 0x80, 0xd7, 0x5b, 0xc0, 0x3f, 0xbf,
-       0x5e, 0x64, 0xdc, 0xb3, 0x59, 0x8e, 0x8e, 0x55, 0xe7, 0xb5, 0xca, 0xbb,
-       0xc7, 0x36, 0xc8, 0xbe, 0x51, 0xff, 0x6a, 0xa9, 0xdf, 0x28, 0x23, 0xa3,
-       0x2f, 0xea, 0xfb, 0x40, 0xd6, 0xe8, 0x7b, 0x92, 0x78, 0x7f, 0x98, 0x91,
-       0x91, 0xfd, 0x8e, 0x91, 0x91, 0x19, 0x35, 0x6f, 0xb3, 0x86, 0x6d, 0xf2,
-       0x6e, 0xa6, 0xbe, 0xd1, 0xb8, 0xbe, 0x43, 0x7a, 0xa2, 0x72, 0xad, 0xfc,
-       0xd1, 0x71, 0x75, 0xa7, 0x9a, 0xbf, 0x4b, 0x41, 0xdb, 0xac, 0x93, 0x0b,
-       0x6c, 0xd6, 0xbf, 0x97, 0x99, 0xf7, 0x45, 0x31, 0x4e, 0xd0, 0xf0, 0x75,
-       0x2f, 0x73, 0x1d, 0xb4, 0x39, 0x26, 0x97, 0xa4, 0x4f, 0xe3, 0x8f, 0xf2,
-       0xb4, 0x01, 0x72, 0x70, 0x56, 0xeb, 0xd7, 0xb5, 0xbc, 0xf3, 0xf8, 0x08,
-       0x6d, 0xd7, 0xaf, 0x6b, 0x79, 0xb6, 0xd6, 0xda, 0xae, 0xd3, 0x90, 0xd3,
-       0x94, 0xa3, 0x37, 0xca, 0x5f, 0xdb, 0x74, 0xa6, 0x25, 0xe3, 0xb3, 0x42,
-       0x7d, 0x17, 0x83, 0x0c, 0xa5, 0x3c, 0xfd, 0x59, 0x6d, 0xd7, 0xe7, 0x6c,
-       0x1b, 0x94, 0x9f, 0x46, 0x76, 0x6f, 0x76, 0xa6, 0x6d, 0x1a, 0xbf, 0xc3,
-       0x18, 0xba, 0x9f, 0xc9, 0x59, 0x3e, 0x53, 0xce, 0x93, 0xc8, 0x5f, 0x83,
-       0x7c, 0xf2, 0xd9, 0x63, 0x9a, 0xcf, 0xb4, 0x7d, 0xe2, 0x74, 0xd9, 0x35,
-       0x85, 0xb9, 0xf5, 0x80, 0x3c, 0xf9, 0x4c, 0x1d, 0xf5, 0xa6, 0x8d, 0x3c,
-       0xf0, 0x90, 0xfe, 0x45, 0xe8, 0x0e, 0xd6, 0x45, 0xfa, 0xb1, 0x0c, 0xe6,
-       0xf0, 0x24, 0xfc, 0x9f, 0x46, 0x7c, 0x37, 0xe3, 0x7b, 0x42, 0x7e, 0x75,
-       0x30, 0xaa, 0xc7, 0x3d, 0x82, 0x71, 0x1c, 0x38, 0x82, 0x31, 0x39, 0xc6,
-       0x76, 0x76, 0xcf, 0xb8, 0x52, 0x73, 0x86, 0x7c, 0xc7, 0x33, 0x86, 0x41,
-       0xb0, 0xb7, 0x8b, 0x74, 0x9b, 0xf4, 0xfa, 0xf5, 0xf9, 0xb7, 0xcd, 0xf1,
-       0x08, 0x70, 0x72, 0x00, 0xf3, 0x31, 0x52, 0xf4, 0xbd, 0xac, 0xe3, 0xc7,
-       0x31, 0x4e, 0xd8, 0x80, 0xed, 0xb0, 0x05, 0xdb, 0x61, 0x07, 0xb6, 0xc3,
-       0x0e, 0x5c, 0x2d, 0xa7, 0xb6, 0x72, 0x7f, 0x49, 0xfe, 0x9d, 0xbc, 0x77,
-       0xf9, 0x1b, 0x3a, 0x36, 0x5f, 0x7b, 0x4b, 0x1f, 0x7c, 0x76, 0xf1, 0x92,
-       0x03, 0xdc, 0x63, 0x3f, 0xeb, 0xd5, 0xde, 0xd2, 0x2f, 0xed, 0x3d, 0xc8,
-       0xef, 0xb9, 0x24, 0x1d, 0xb7, 0x7c, 0xd8, 0xa9, 0x1d, 0xe8, 0x03, 0x1e,
-       0x33, 0x4e, 0x32, 0x3e, 0xe4, 0x30, 0x4e, 0x91, 0xdd, 0x1c, 0xd1, 0x67,
-       0xc4, 0xa6, 0x19, 0x8b, 0xb8, 0xa5, 0x3d, 0xb2, 0x25, 0xb1, 0xdb, 0x49,
-       0x0e, 0xa8, 0x48, 0x72, 0xa0, 0xcf, 0x09, 0xcb, 0xf1, 0x0e, 0x6a, 0xc8,
-       0x19, 0xc0, 0x7a, 0xa0, 0xf4, 0x75, 0xd0, 0xd3, 0x79, 0x29, 0x1c, 0x6f,
-       0x90, 0xa9, 0x62, 0xbb, 0x97, 0x55, 0x31, 0xe1, 0xbe, 0x12, 0x75, 0x0a,
-       0x44, 0x7f, 0x26, 0x2a, 0x13, 0xa3, 0x1b, 0x45, 0x69, 0xdb, 0xbd, 0x45,
-       0xb2, 0x63, 0xa3, 0x72, 0xbe, 0x5b, 0x9a, 0x14, 0xda, 0xe7, 0xdd, 0xde,
-       0xea, 0x14, 0xd7, 0x11, 0x43, 0x5e, 0x58, 0x4f, 0x3e, 0x19, 0x05, 0x0e,
-       0x41, 0xb7, 0x8c, 0xeb, 0xd6, 0x09, 0xe5, 0xde, 0xed, 0x3a, 0x66, 0xca,
-       0x38, 0x6d, 0xf5, 0x7a, 0x03, 0xf9, 0x23, 0xba, 0x2c, 0x7f, 0x4c, 0x96,
-       0xb8, 0x36, 0x23, 0x79, 0x97, 0x71, 0x61, 0x1f, 0xbf, 0xc7, 0x59, 0xb6,
-       0x4e, 0x46, 0xba, 0xf3, 0x76, 0x8f, 0xc7, 0x37, 0xc1, 0x07, 0x1c, 0x9f,
-       0x5e, 0x27, 0x01, 0xaf, 0x2f, 0x5e, 0xcf, 0x88, 0x56, 0xc9, 0x03, 0x47,
-       0x66, 0x46, 0xc3, 0xf5, 0x0f, 0xb6, 0x87, 0xef, 0x71, 0x23, 0x6f, 0xb3,
-       0x4b, 0xea, 0x11, 0x2e, 0xae, 0x55, 0x2e, 0x94, 0xb1, 0x4a, 0x9f, 0x13,
-       0xf6, 0xb4, 0x7c, 0x3d, 0x5d, 0x31, 0xb2, 0x75, 0xbc, 0x12, 0xea, 0x96,
-       0xa8, 0xd1, 0xa5, 0x4b, 0xf4, 0x89, 0x89, 0x60, 0xce, 0xeb, 0x93, 0x4b,
-       0x3a, 0x46, 0xf7, 0x6b, 0x53, 0x2d, 0xe2, 0x1e, 0x93, 0xd9, 0x11, 0xff,
-       0x54, 0x2b, 0xf7, 0x69, 0x8c, 0xa4, 0xde, 0x8c, 0x7e, 0x8c, 0xb5, 0x50,
-       0x1f, 0x0e, 0xa9, 0xb5, 0x78, 0xaf, 0xd1, 0xf4, 0x07, 0x9e, 0xc2, 0xb7,
-       0xf1, 0x13, 0xbe, 0x0c, 0x3f, 0xe1, 0x09, 0xe8, 0xba, 0x73, 0xf0, 0x13,
-       0x1e, 0x87, 0x9f, 0xf0, 0x18, 0xfc, 0x84, 0x47, 0xa1, 0x27, 0xab, 0xfd,
-       0x83, 0xe1, 0x05, 0xfe, 0x41, 0xa0, 0xf9, 0x9f, 0x31, 0xc0, 0xc7, 0xab,
-       0x7c, 0x83, 0xbd, 0x46, 0x5f, 0xc1, 0xef, 0x37, 0x7c, 0xd4, 0xa6, 0x6e,
-       0xd6, 0xfa, 0xd1, 0xec, 0xd9, 0x1d, 0x98, 0xd3, 0x57, 0x6d, 0xca, 0xe8,
-       0xab, 0x89, 0x79, 0x7d, 0x65, 0xf8, 0xe8, 0xd8, 0xa8, 0x44, 0xfc, 0xd1,
-       0xe9, 0x6c, 0x6a, 0xbb, 0xe6, 0xa1, 0x26, 0x7f, 0xa3, 0x44, 0x1e, 0x50,
-       0xcd, 0x35, 0x92, 0xb5, 0xdf, 0xa0, 0xaf, 0xa3, 0x5f, 0x47, 0x5b, 0xef,
-       0x94, 0x9c, 0xb6, 0xcf, 0xae, 0x8c, 0xef, 0x47, 0x17, 0xe1, 0xbb, 0x50,
-       0x7a, 0x56, 0xe3, 0xfc, 0x7e, 0x7d, 0x26, 0xbf, 0x41, 0x86, 0xcb, 0x21,
-       0xce, 0x79, 0x06, 0x8e, 0xfb, 0x30, 0x5a, 0x25, 0x72, 0xac, 0x45, 0xfa,
-       0x53, 0xa2, 0x72, 0xa9, 0x95, 0x7a, 0xff, 0xca, 0xa9, 0x6e, 0x89, 0xe7,
-       0xba, 0x49, 0xab, 0xf7, 0xc9, 0x84, 0x9e, 0x8b, 0x16, 0xa9, 0x39, 0x46,
-       0x1b, 0x25, 0x5c, 0xc3, 0xbb, 0xbd, 0xc5, 0xde, 0x41, 0x1d, 0x35, 0xe5,
-       0x44, 0x0e, 0xea, 0xf9, 0x9a, 0xd5, 0x7b, 0x0c, 0x6f, 0x9e, 0x62, 0x2c,
-       0x9e, 0xf7, 0xfd, 0x31, 0x0e, 0xff, 0xaf, 0x99, 0xbf, 0x42, 0x8b, 0xb1,
-       0x67, 0xd6, 0x58, 0x3b, 0xc6, 0xc4, 0xa9, 0x96, 0xb7, 0x61, 0xd8, 0x4e,
-       0xf5, 0x1d, 0xb5, 0xab, 0xe0, 0x03, 0x37, 0xa0, 0x4d, 0xae, 0x63, 0xdb,
-       0xbf, 0x17, 0xe4, 0xfd, 0xb3, 0x73, 0xc0, 0x5f, 0x85, 0xb4, 0x06, 0xe4,
-       0x31, 0x66, 0xf3, 0x85, 0x16, 0xc6, 0x65, 0xb3, 0x7e, 0xa3, 0x4d, 0x5b,
-       0xe5, 0x8c, 0x8c, 0xb6, 0xc3, 0x37, 0xe7, 0x39, 0x76, 0xe6, 0xf7, 0x73,
-       0xee, 0x84, 0x7f, 0xab, 0x69, 0x12, 0xf2, 0x67, 0x8f, 0x5c, 0x6b, 0xe3,
-       0xce, 0xd4, 0xc3, 0xbf, 0xb8, 0x60, 0xbd, 0xf6, 0x10, 0xf4, 0xd8, 0xad,
-       0x90, 0x47, 0xd4, 0xc3, 0x87, 0xe4, 0x17, 0x2c, 0x3d, 0x2f, 0xd4, 0xc3,
-       0x17, 0x85, 0xb1, 0xe1, 0x2e, 0xe4, 0xe5, 0x83, 0x28, 0xe8, 0xe1, 0x70,
-       0x95, 0xaf, 0x46, 0xbf, 0xaf, 0x2e, 0x6d, 0xd6, 0xc0, 0x16, 0xfa, 0x7d,
-       0x90, 0x03, 0xb1, 0xd0, 0xcf, 0xab, 0x9d, 0x5b, 0xa3, 0xdd, 0x69, 0xeb,
-       0x8e, 0xa4, 0x5e, 0x22, 0x8e, 0x12, 0x87, 0xe4, 0xf6, 0xf5, 0xbc, 0x26,
-       0xcf, 0xf5, 0xbf, 0xa5, 0x71, 0x26, 0x8a, 0xb4, 0xb7, 0x46, 0xc3, 0x68,
-       0xe5, 0x7c, 0x22, 0xdc, 0xbf, 0x51, 0xb0, 0x75, 0xf7, 0xd8, 0xf5, 0xf8,
-       0x82, 0x7c, 0x9b, 0x71, 0xce, 0x44, 0x5f, 0x64, 0x25, 0xcf, 0x64, 0xa3,
-       0xee, 0xed, 0xda, 0x6f, 0xcf, 0x48, 0xd8, 0x16, 0xbf, 0x6b, 0xaa, 0xda,
-       0xa6, 0x1d, 0xc5, 0xf7, 0xe2, 0xfb, 0x1b, 0x9e, 0xd7, 0x6b, 0x8b, 0xe6,
-       0x6e, 0x9a, 0x90, 0x4f, 0xc8, 0x3b, 0x09, 0x7d, 0x8e, 0xc9, 0x3f, 0x46,
-       0xbb, 0x87, 0xeb, 0xae, 0xde, 0xf4, 0x70, 0xea, 0x23, 0xfa, 0x0e, 0xd5,
-       0x71, 0x11, 0xa7, 0x90, 0xda, 0xab, 0xf7, 0x9d, 0x14, 0x74, 0x7c, 0x39,
-       0x8f, 0xf7, 0xbc, 0x8f, 0xda, 0x76, 0x8c, 0x7f, 0x0b, 0x88, 0x69, 0x1f,
-       0x04, 0x6c, 0xd4, 0x21, 0x94, 0xbd, 0x31, 0x69, 0x3b, 0xfa, 0x7e, 0xcd,
-       0x0b, 0x6b, 0xe1, 0x0b, 0xf4, 0x1e, 0x85, 0xae, 0x3e, 0x1a, 0x97, 0xfe,
-       0xa3, 0x5a, 0x37, 0x66, 0x96, 0xc6, 0x0a, 0xb6, 0x78, 0x2e, 0xfd, 0x89,
-       0x98, 0x27, 0xd7, 0x1c, 0x8d, 0xc8, 0xe1, 0xd8, 0x16, 0xaf, 0xc3, 0xb9,
-       0xd1, 0xea, 0x42, 0x43, 0x7f, 0xa0, 0x15, 0xd4, 0x37, 0xeb, 0x90, 0xbd,
-       0xf3, 0xb1, 0x6b, 0xd4, 0x7f, 0x49, 0x46, 0xc8, 0x4b, 0x95, 0x88, 0x8c,
-       0x0f, 0xb6, 0x02, 0x9e, 0xb7, 0xae, 0x07, 0x0e, 0x40, 0x53, 0x98, 0x1f,
-       0xfd, 0xf7, 0x3c, 0xdc, 0x38, 0xe5, 0x57, 0x1b, 0xfa, 0xef, 0x3b, 0x4a,
-       0x1d, 0xe6, 0x6b, 0xbe, 0x46, 0xbf, 0x5e, 0x8d, 0xf6, 0x3d, 0xc8, 0x8b,
-       0x6f, 0x11, 0xff, 0x01, 0xc8, 0xb5, 0xa3, 0x51, 0xe9, 0x38, 0xda, 0x20,
-       0x9b, 0x8e, 0xd2, 0xf7, 0xa8, 0xf6, 0x45, 0x69, 0x8b, 0x5e, 0xc2, 0xb8,
-       0x6e, 0x34, 0xf7, 0x0d, 0x4e, 0x45, 0x65, 0x1f, 0xf9, 0x15, 0x65, 0x73,
-       0xb0, 0x93, 0xb3, 0x47, 0x3d, 0xbd, 0x16, 0x9a, 0xc5, 0x38, 0xf9, 0x37,
-       0x2c, 0xfa, 0x8e, 0x1a, 0x39, 0x53, 0xa0, 0x6f, 0x32, 0xd0, 0x02, 0xbc,
-       0x3e, 0x60, 0xf9, 0xe5, 0x3d, 0xeb, 0x2d, 0x5f, 0xfe, 0x9c, 0xfc, 0x96,
-       0x5b, 0x6f, 0xe4, 0xe5, 0x87, 0xd6, 0x73, 0x2f, 0xd2, 0x5a, 0x9f, 0xef,
-       0x3a, 0x6d, 0x43, 0x18, 0xb9, 0xf9, 0x7a, 0xfc, 0x27, 0xc0, 0x51, 0xb8,
-       0xfe, 0x44, 0x3e, 0xe4, 0x1a, 0xb2, 0x3e, 0xb3, 0x92, 0x9a, 0xd1, 0x7f,
-       0x53, 0x89, 0x6b, 0x61, 0xf3, 0xf7, 0x59, 0x6d, 0xaf, 0x30, 0x36, 0xfe,
-       0x4c, 0xf8, 0x37, 0x9c, 0xaa, 0xf6, 0x19, 0x56, 0xaf, 0x75, 0x31, 0xbe,
-       0x34, 0xb7, 0x17, 0x28, 0x18, 0xd5, 0x77, 0xc2, 0xc5, 0x9c, 0x8b, 0xc5,
-       0x5a, 0xe7, 0x9b, 0x63, 0x12, 0xb8, 0x7e, 0xdc, 0xf9, 0x96, 0xcf, 0xb5,
-       0x71, 0xcf, 0x79, 0xb9, 0xe8, 0x83, 0xf7, 0xfe, 0x02, 0xe3, 0x68, 0x75,
-       0x5e, 0xc1, 0x9c, 0x1e, 0x2c, 0x65, 0x92, 0x9e, 0x8d, 0x83, 0x3f, 0x5b,
-       0x6c, 0x75, 0x9e, 0x9b, 0x8f, 0x21, 0xf5, 0x84, 0x74, 0x71, 0x88, 0x79,
-       0x65, 0xe4, 0x95, 0x19, 0xeb, 0xad, 0x77, 0x26, 0xc7, 0xec, 0x7e, 0x12,
-       0xa3, 0x8b, 0xe6, 0xd6, 0x5f, 0x06, 0xf4, 0xfa, 0x84, 0xeb, 0x4c, 0x4e,
-       0x4d, 0xaf, 0x37, 0xfb, 0x8a, 0x6a, 0x91, 0x67, 0xf6, 0x58, 0x4e, 0x4c,
-       0xd5, 0xa2, 0x4c, 0xbd, 0x33, 0xa1, 0x63, 0x5e, 0xda, 0xf6, 0x70, 0xc6,
-       0xa7, 0xea, 0x9d, 0x29, 0xbd, 0xd6, 0x1c, 0x75, 0x4e, 0x8e, 0xb1, 0xed,
-       0x28, 0xca, 0x88, 0x73, 0x0a, 0xed, 0x4d, 0x8d, 0xb5, 0xc7, 0xf7, 0x49,
-       0x3b, 0x6c, 0x01, 0xfe, 0x8d, 0x34, 0xde, 0x17, 0xe0, 0x3a, 0x53, 0x73,
-       0xed, 0x2a, 0xb4, 0xc3, 0xb2, 0xa4, 0x41, 0xf6, 0xeb, 0xa2, 0xfd, 0xa5,
-       0x6b, 0x52, 0x4b, 0x71, 0x32, 0x06, 0x9c, 0x1c, 0xb4, 0x38, 0x39, 0x61,
-       0x71, 0x32, 0x5a, 0x85, 0x93, 0x87, 0x17, 0xe1, 0xe4, 0x04, 0x70, 0xf2,
-       0xf0, 0x15, 0x70, 0x82, 0xbc, 0xf2, 0xc3, 0x16, 0x27, 0xf7, 0x2d, 0xc2,
-       0x49, 0x7e, 0x2e, 0x16, 0x6f, 0x70, 0x32, 0x02, 0x9c, 0xd4, 0xb4, 0x1a,
-       0xd8, 0x0f, 0x5a, 0x9c, 0xe0, 0x3d, 0x75, 0x10, 0x65, 0xee, 0xab, 0xc2,
-       0xc9, 0x41, 0xe0, 0xe4, 0x3e, 0x8b, 0x93, 0xc3, 0x16, 0x27, 0x87, 0x51,
-       0x26, 0x0f, 0x9c, 0x14, 0x96, 0xc1, 0xc9, 0x08, 0x70, 0x12, 0xb6, 0x5b,
-       0x40, 0x3b, 0x87, 0xab, 0x70, 0x32, 0xb2, 0x0c, 0x4e, 0xb8, 0xe6, 0x1a,
-       0xee, 0xe1, 0xbe, 0xfc, 0x06, 0x7b, 0xb8, 0x53, 0x9f, 0x7d, 0xe3, 0x3d,
-       0xdc, 0x2c, 0x73, 0xb9, 0xea, 0xcc, 0xfb, 0xb3, 0x76, 0x4f, 0x9a, 0xd9,
-       0xfb, 0x37, 0x7f, 0x0f, 0x5e, 0x3b, 0xf8, 0xbc, 0x90, 0xf7, 0xc4, 0xec,
-       0x21, 0x75, 0xb7, 0x4d, 0x81, 0xd7, 0x8e, 0xca, 0x81, 0xe3, 0xb5, 0x87,
-       0x73, 0x36, 0xcd, 0xdf, 0xd6, 0x9e, 0x57, 0x8a, 0x79, 0xe1, 0xde, 0x83,
-       0x17, 0xcd, 0x5d, 0x50, 0x31, 0x9e, 0xc7, 0xa8, 0x5e, 0x7b, 0x7e, 0xd1,
-       0xde, 0x55, 0xe4, 0xdd, 0x9b, 0xf5, 0xa7, 0x13, 0xdc, 0x57, 0x55, 0xd0,
-       0xf0, 0x72, 0x2d, 0xad, 0x47, 0xef, 0xa5, 0xca, 0x16, 0x69, 0x67, 0x27,
-       0xb8, 0x27, 0x0d, 0xf6, 0x31, 0xf7, 0xed, 0x9a, 0x7d, 0xba, 0xbd, 0x0b,
-       0xf6, 0xe9, 0x56, 0x9f, 0xef, 0x26, 0xdf, 0xcd, 0xd3, 0xcd, 0xc1, 0xb9,
-       0xbb, 0x57, 0x8f, 0x3b, 0xcf, 0xe8, 0xf8, 0x70, 0x3d, 0xe6, 0x27, 0x08,
-       0x4e, 0xa7, 0x4c, 0x5c, 0x76, 0x46, 0xc7, 0x65, 0x05, 0x1e, 0xf8, 0xb0,
-       0x8d, 0xcd, 0x76, 0xf4, 0x5c, 0x9e, 0x8b, 0xcb, 0x2e, 0xd8, 0xa3, 0xa3,
-       0xef, 0xff, 0xc8, 0x8e, 0x5e, 0xd2, 0x7b, 0x71, 0xfa, 0x52, 0x8e, 0x14,
-       0x20, 0x23, 0xf6, 0x8c, 0xbf, 0x2a, 0xc3, 0x0f, 0xf2, 0x9b, 0x3a, 0x2d,
-       0x02, 0xbd, 0x45, 0xb9, 0x9d, 0x97, 0x6c, 0x0f, 0xd3, 0x4c, 0x9d, 0x3e,
-       0xed, 0x23, 0x1f, 0x77, 0x7a, 0xe7, 0xfa, 0x27, 0x7e, 0xc3, 0x35, 0x70,
-       0xfe, 0xa6, 0x9d, 0x93, 0x71, 0xb2, 0x15, 0xe6, 0x87, 0x6b, 0xe1, 0x77,
-       0xdb, 0xfb, 0x08, 0x99, 0x5f, 0x7d, 0xff, 0xb5, 0xe1, 0xd3, 0xac, 0xfe,
-       0x3b, 0x22, 0x23, 0x4e, 0x1f, 0xea, 0x4c, 0x7b, 0x0d, 0x03, 0x2a, 0x7d,
-       0xd3, 0x00, 0xcf, 0xca, 0x4d, 0x2c, 0xf9, 0xfb, 0x01, 0xf3, 0xba, 0xb0,
-       0xa0, 0xe7, 0x94, 0xfb, 0xb0, 0xa6, 0x41, 0x8b, 0x9a, 0xb6, 0x34, 0xfd,
-       0x1f, 0x98, 0xd3, 0x91, 0xd4, 0xad, 0xd4, 0x93, 0xa1, 0x8e, 0x4c, 0xc6,
-       0xfb, 0x78, 0x7f, 0x84, 0xa6, 0x71, 0x7b, 0x97, 0xc4, 0xd4, 0x39, 0xad,
-       0xdf, 0x47, 0x52, 0xbc, 0x5f, 0x66, 0x99, 0xb2, 0xa3, 0x55, 0x65, 0xf5,
-       0xb8, 0x3d, 0xf9, 0x43, 0xcc, 0xcd, 0x17, 0x61, 0x6f, 0xf6, 0x8e, 0xbd,
-       0x0a, 0x9f, 0x31, 0x2e, 0x5f, 0x2a, 0xbd, 0x04, 0x7a, 0xcd, 0xaf, 0xb5,
-       0x77, 0xe1, 0x65, 0x01, 0x37, 0xcf, 0x38, 0xeb, 0xfd, 0xc3, 0x91, 0x3f,
-       0x02, 0x5d, 0xfc, 0xc1, 0x4b, 0xec, 0x03, 0xb0, 0x44, 0x60, 0xcf, 0xc3,
-       0x36, 0x18, 0x7f, 0x49, 0xef, 0x95, 0xbb, 0xbe, 0xfc, 0x92, 0x8e, 0x53,
-       0xf4, 0x97, 0x5b, 0x65, 0x7b, 0xb9, 0x41, 0x76, 0x40, 0x2f, 0xec, 0x28,
-       0xfb, 0x78, 0xa2, 0x72, 0x63, 0xd9, 0xcc, 0xd3, 0x47, 0xca, 0x9c, 0xef,
-       0x6d, 0x32, 0x71, 0xbc, 0x9a, 0x66, 0xa7, 0xed, 0xde, 0x31, 0xd2, 0x0f,
-       0x9e, 0x52, 0x32, 0x3f, 0xad, 0xc7, 0xce, 0x5d, 0xac, 0xc9, 0xc3, 0xb3,
-       0xc2, 0xbd, 0xf8, 0xfc, 0x1b, 0x74, 0xdf, 0x68, 0xe5, 0x19, 0x77, 0xde,
-       0x8f, 0xd8, 0x5f, 0x09, 0xf7, 0x86, 0xbf, 0xfe, 0x19, 0x10, 0xfd, 0x77,
-       0x5d, 0xf4, 0xde, 0x70, 0x4d, 0x7b, 0xd2, 0x76, 0x26, 0xa6, 0x75, 0x84,
-       0xa1, 0xf1, 0xf9, 0xbf, 0xe7, 0x22, 0xf2, 0x7f, 0x01, 0x95, 0xf6, 0x2d,
-       0x58, 0xd0, 0x73, 0x00, 0x00, 0x00 };
-static u32 bnx2_CP_b09FwData[(0x50/4) + 1] = {
-       0x00010030, 0x00000030, 0x00000000, 0x00000001, 0x00010fd0, 0x00000fd0,
-       0x00001430, 0x0000007f, 0x00030400, 0x00001000, 0x00000030, 0x00000020,
-       0x00050200, 0x00001000, 0x00000030, 0x00000010, 0x00010400, 0x00000400,
-       0x00001030, 0x00000020, 0x00000000 };
-static u32 bnx2_CP_b09FwRodata[(0x118/4) + 1] = {
-       0x080005d8, 0x080007f8, 0x0800073c, 0x08000764, 0x0800078c, 0x080007b4,
-       0x08000610, 0x080005fc, 0x08000820, 0x08000820, 0x0800062c, 0x08000648,
-       0x08000648, 0x08000820, 0x08000660, 0x08000674, 0x08000820, 0x08000688,
-       0x08000820, 0x08000820, 0x0800069c, 0x08000820, 0x08000820, 0x08000820,
-       0x08000820, 0x08000820, 0x08000820, 0x08000820, 0x08000820, 0x08000820,
-       0x08000820, 0x080006b0, 0x08000820, 0x080006c4, 0x080006d8, 0x080006ec,
-       0x08000820, 0x08000700, 0x08000714, 0x08000728, 0x08003740, 0x08003758,
-       0x08003768, 0x08003778, 0x08003790, 0x080037a8, 0x080037b8, 0x080037c8,
-       0x080037e8, 0x080037f8, 0x08003808, 0x08003898, 0x080037d8, 0x08003818,
-       0x08003828, 0x08003840, 0x08003860, 0x08003898, 0x08003878, 0x08003878,
-       0x080055f0, 0x080055f0, 0x080055f0, 0x080055f0, 0x080055f0, 0x08005618,
-       0x08005618, 0x08005640, 0x08005690, 0x08005660, 0x00000000 };
-static u32 bnx2_CP_b09FwBss[(0x870/4) + 1] = { 0x0 };
-static u32 bnx2_CP_b09FwSbss[(0xe9/4) + 1] = { 0x0 };
+       0x1f, 0x8b, 0x08, 0x00, 0x0f, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xbd, 0x7d,
+       0x0d, 0x74, 0x5c, 0x57, 0x7d, 0xe7, 0xff, 0xdd, 0x19, 0x49, 0x63, 0x59,
+       0x96, 0x9f, 0xe5, 0x89, 0x32, 0x51, 0x84, 0x3d, 0x23, 0x3d, 0xd9, 0x22,
+       0x12, 0xe1, 0xc5, 0x11, 0xac, 0xda, 0x2a, 0xe9, 0x30, 0x92, 0x3f, 0x12,
+       0x02, 0xab, 0x10, 0x43, 0xb3, 0x1c, 0x4a, 0xc5, 0x48, 0x4e, 0x02, 0x04,
+       0xea, 0x40, 0xe8, 0x86, 0xdd, 0xec, 0x66, 0x32, 0x92, 0x3f, 0x9a, 0x8e,
+       0x3d, 0x93, 0x44, 0x89, 0xbd, 0xdd, 0x9c, 0xad, 0x90, 0x14, 0x3b, 0x74,
+       0x07, 0x4f, 0xe2, 0x98, 0x96, 0x73, 0x0a, 0x8d, 0x50, 0x8c, 0x9b, 0xe6,
+       0xb0, 0xdd, 0xd0, 0xa6, 0x34, 0xdb, 0x86, 0x22, 0x8c, 0x81, 0xf4, 0x2c,
+       0xdd, 0x86, 0x42, 0x77, 0xd3, 0x36, 0xe5, 0xed, 0xef, 0x77, 0xef, 0x7d,
+       0x9a, 0x91, 0x34, 0xce, 0x07, 0xdd, 0xad, 0xcf, 0x79, 0x7e, 0xf3, 0xee,
+       0xbb, 0x1f, 0xff, 0xfb, 0xbf, 0xff, 0xef, 0xfb, 0xbf, 0x4f, 0x97, 0x8b,
+       0x34, 0x8b, 0xfd, 0xb7, 0x01, 0xd7, 0xd5, 0xc9, 0xfd, 0xe3, 0x57, 0x5f,
+       0x39, 0x70, 0x25, 0x9f, 0xa3, 0x91, 0x68, 0x44, 0xde, 0xc4, 0xbf, 0xe4,
+       0x1b, 0xa8, 0x83, 0x0e, 0xdd, 0x70, 0x2c, 0x5e, 0x12, 0x53, 0x43, 0xde,
+       0xfe, 0x8c, 0x27, 0xb1, 0xc8, 0x50, 0xee, 0xce, 0x71, 0x4f, 0x24, 0x5d,
+       0xee, 0x4b, 0x0e, 0xcb, 0x3f, 0x05, 0xb9, 0x78, 0x54, 0x58, 0xfe, 0x96,
+       0xa1, 0x57, 0x7f, 0xeb, 0x2b, 0xff, 0x2a, 0xf5, 0xf2, 0x4c, 0x44, 0x62,
+       0xee, 0xd0, 0xed, 0xe2, 0x6e, 0x93, 0x58, 0xe7, 0x50, 0x72, 0xff, 0x23,
+       0xdb, 0x97, 0x44, 0x5a, 0xc3, 0xbe, 0x5e, 0x0a, 0xbe, 0xb2, 0x5d, 0x72,
+       0x1d, 0x43, 0x89, 0xb1, 0x86, 0x21, 0x57, 0x9e, 0xaa, 0xc8, 0xe8, 0x89,
+       0xc2, 0xcb, 0x41, 0x74, 0x28, 0x88, 0x4c, 0x0d, 0x38, 0x12, 0x19, 0x92,
+       0xb3, 0xe3, 0x03, 0xf7, 0x04, 0xca, 0xf3, 0xfc, 0x45, 0x69, 0x19, 0x3c,
+       0x37, 0x80, 0xf7, 0x65, 0x41, 0xdd, 0xbd, 0xd7, 0x9c, 0x28, 0xc4, 0x44,
+       0x0d, 0xf5, 0xbc, 0x90, 0x89, 0x5c, 0x25, 0x7c, 0x7f, 0x56, 0x7a, 0xfc,
+       0xa7, 0x05, 0xe5, 0xe5, 0x98, 0x64, 0x2a, 0xd2, 0x82, 0x32, 0xdc, 0x9b,
+       0x51, 0x27, 0xe5, 0x66, 0x22, 0xae, 0xe4, 0x2b, 0x3f, 0x5e, 0x67, 0xc6,
+       0x9d, 0xb3, 0xf7, 0xbf, 0x8e, 0x99, 0x3b, 0xc6, 0x2d, 0xc6, 0x64, 0x29,
+       0x92, 0x10, 0xc0, 0x82, 0x79, 0x25, 0x64, 0xb2, 0x98, 0x94, 0x4c, 0x81,
+       0xb0, 0x45, 0x25, 0xeb, 0x12, 0xae, 0x04, 0xda, 0xb7, 0x39, 0xf5, 0xeb,
+       0xb3, 0xee, 0x0b, 0xa8, 0x9b, 0x44, 0xbd, 0x4e, 0x79, 0x12, 0x75, 0x4f,
+       0x57, 0xe2, 0xf2, 0x44, 0xe5, 0x57, 0x25, 0x8d, 0xb6, 0x8f, 0x57, 0x30,
+       0x76, 0xb1, 0x51, 0x86, 0xa7, 0x9b, 0x25, 0x33, 0xdd, 0x9d, 0xc8, 0x4a,
+       0x10, 0x7c, 0xda, 0xff, 0xa8, 0x8c, 0xb5, 0xa1, 0x7e, 0x91, 0xef, 0x12,
+       0x2b, 0xde, 0x65, 0xfd, 0x3e, 0x37, 0xab, 0x1c, 0x49, 0xef, 0x4d, 0x25,
+       0xc6, 0x14, 0x9f, 0x1b, 0x24, 0xd3, 0x8f, 0xe7, 0xd1, 0xa8, 0x44, 0xbc,
+       0x20, 0xb8, 0xc3, 0xbf, 0x0c, 0x70, 0xa4, 0x92, 0x49, 0xc5, 0xb6, 0x6c,
+       0x97, 0xca, 0x25, 0x55, 0x5c, 0x72, 0x95, 0x2b, 0x25, 0xd9, 0x16, 0x04,
+       0xef, 0xf3, 0x3b, 0x51, 0x2e, 0x32, 0x5c, 0x90, 0xfd, 0x58, 0x23, 0xf4,
+       0x29, 0xbe, 0x1a, 0xda, 0x8c, 0x79, 0xf4, 0xb9, 0xc3, 0xd2, 0x28, 0xe9,
+       0xb8, 0xa4, 0xd5, 0x90, 0x24, 0xd5, 0xd0, 0x3a, 0x94, 0x39, 0xd2, 0xe0,
+       0x7d, 0xc1, 0xd2, 0xd2, 0x46, 0x3c, 0xcb, 0xa8, 0x1a, 0x6a, 0x5b, 0x55,
+       0x9e, 0x4a, 0x8a, 0x5a, 0x07, 0x5c, 0xa5, 0x7a, 0xd3, 0x8a, 0x65, 0xb8,
+       0xeb, 0xb2, 0x0f, 0x36, 0xad, 0x2d, 0xdb, 0xef, 0xac, 0x2c, 0xbb, 0xbd,
+       0x85, 0xb0, 0x8a, 0xe2, 0xef, 0xb8, 0x9e, 0x6b, 0x3a, 0xde, 0xed, 0x36,
+       0x60, 0x5e, 0xa3, 0x7e, 0xca, 0xdd, 0xa9, 0x9e, 0x0f, 0xa4, 0x9d, 0x30,
+       0xf3, 0x9d, 0xc2, 0x3b, 0x54, 0x1d, 0xf2, 0xb1, 0x6e, 0xae, 0x1c, 0xc2,
+       0xdc, 0xce, 0x4f, 0xa7, 0xdc, 0x2e, 0x85, 0xfb, 0x3c, 0x7f, 0x07, 0x41,
+       0xc6, 0xcf, 0xe9, 0x35, 0xfd, 0xee, 0x74, 0x02, 0xcf, 0x80, 0x3f, 0x9e,
+       0x4e, 0x6d, 0x92, 0xab, 0xed, 0xba, 0x7c, 0x13, 0x63, 0x76, 0xbb, 0x77,
+       0xa8, 0x6e, 0xd7, 0x57, 0x29, 0x77, 0x56, 0xce, 0xe0, 0x39, 0x08, 0x6e,
+       0xf4, 0x53, 0x89, 0x1c, 0xd6, 0xec, 0x42, 0x21, 0x2e, 0xdf, 0x2b, 0xa4,
+       0x40, 0xc5, 0xa9, 0xde, 0x39, 0xe9, 0xf3, 0xe7, 0x00, 0x6f, 0x1e, 0xd7,
+       0x41, 0xbe, 0x2b, 0xe3, 0x5d, 0x99, 0x6d, 0x83, 0xe0, 0x26, 0xff, 0x37,
+       0x83, 0xb1, 0x76, 0xc3, 0x17, 0x4f, 0x15, 0xb1, 0x9e, 0x80, 0xf9, 0x74,
+       0x11, 0xeb, 0x89, 0xb5, 0x7a, 0x5c, 0xaf, 0x7b, 0x2f, 0xd6, 0x9d, 0xb4,
+       0x41, 0xba, 0xd8, 0x61, 0x69, 0xf9, 0x03, 0xf6, 0x2e, 0x92, 0x29, 0x3a,
+       0x92, 0xf1, 0xff, 0x31, 0x48, 0x6b, 0x7e, 0x11, 0x67, 0xb8, 0x48, 0x5a,
+       0x6c, 0x00, 0xac, 0x7c, 0xcc, 0xda, 0x7a, 0x1b, 0x1d, 0xe0, 0x96, 0xeb,
+       0xc0, 0xf7, 0x31, 0xe5, 0x35, 0xd9, 0xf7, 0x21, 0x5f, 0xf0, 0xdf, 0x26,
+       0x47, 0xbc, 0x6a, 0xbd, 0x0c, 0x69, 0xb2, 0x92, 0x93, 0xec, 0x83, 0x81,
+       0x0c, 0xfb, 0xc0, 0x13, 0xfb, 0x74, 0x7d, 0xd1, 0x6d, 0x5d, 0xd6, 0xd1,
+       0x75, 0xf1, 0x6f, 0x7d, 0x23, 0xc6, 0x70, 0x46, 0x8a, 0xd5, 0xb6, 0x23,
+       0xc5, 0xfc, 0x66, 0x0b, 0x1f, 0x9e, 0x07, 0x9d, 0x4c, 0xe5, 0x82, 0x5d,
+       0xdb, 0x70, 0x1e, 0x57, 0xd7, 0xa1, 0x6d, 0x17, 0x7c, 0xe0, 0x4a, 0xb6,
+       0x30, 0x88, 0x71, 0xe3, 0xb8, 0x07, 0xc1, 0x94, 0x9f, 0x4e, 0x45, 0x65,
+       0x08, 0xcf, 0xa3, 0xe4, 0x3d, 0xe0, 0x4f, 0xa2, 0x99, 0xed, 0xbe, 0x8c,
+       0x80, 0xee, 0xf3, 0x95, 0xd7, 0x97, 0x22, 0x7a, 0x0e, 0xfe, 0x3f, 0x59,
+       0xdc, 0x70, 0x1c, 0x33, 0xe6, 0x54, 0xb1, 0x43, 0xf2, 0xd3, 0x9e, 0x4c,
+       0x16, 0x16, 0x7a, 0x95, 0xbc, 0x4c, 0x7e, 0xc7, 0xfa, 0xa5, 0x40, 0xbb,
+       0x43, 0x32, 0x5c, 0xf1, 0x24, 0x5f, 0xc0, 0xbd, 0xd8, 0x0d, 0xfa, 0x8d,
+       0x4a, 0x3a, 0x61, 0xd6, 0x26, 0x5f, 0x18, 0xc1, 0xfc, 0x80, 0x6b, 0x8f,
+       0xbf, 0x07, 0x2d, 0x4c, 0xae, 0x64, 0x06, 0x48, 0x3f, 0x6f, 0x06, 0x96,
+       0x98, 0xcc, 0xfa, 0xe0, 0x0b, 0xd7, 0xc0, 0x92, 0x2f, 0xc6, 0xa2, 0xc3,
+       0x98, 0xf7, 0x70, 0xf9, 0x57, 0xd0, 0x7f, 0x8b, 0xfe, 0x0d, 0x7e, 0xb2,
+       0x65, 0x51, 0xdc, 0xe3, 0xb8, 0x13, 0xe6, 0x90, 0x56, 0x21, 0x1b, 0xa6,
+       0x3b, 0x65, 0x12, 0xb4, 0x3a, 0x2c, 0xf8, 0x3d, 0xcf, 0xb9, 0x10, 0xae,
+       0x0e, 0xfd, 0x7b, 0x72, 0x7a, 0x8b, 0x7e, 0xce, 0x8e, 0x76, 0x48, 0x6e,
+       0x3e, 0x9c, 0x33, 0xe5, 0x05, 0x65, 0x44, 0xea, 0xb0, 0x08, 0x65, 0x46,
+       0x10, 0x3c, 0xe8, 0x53, 0x6e, 0x04, 0xc1, 0x69, 0x9f, 0x72, 0xe4, 0x0c,
+       0xe4, 0x03, 0x65, 0x07, 0x79, 0xd9, 0x53, 0x5c, 0xab, 0x4c, 0xa1, 0x17,
+       0xeb, 0xd1, 0x28, 0xd9, 0xfe, 0xe3, 0x84, 0x15, 0x72, 0xe7, 0xa5, 0x4f,
+       0x66, 0xbc, 0x5c, 0x22, 0xa2, 0xf1, 0x04, 0xca, 0x82, 0x3c, 0x4c, 0xeb,
+       0x99, 0x75, 0x49, 0xbe, 0xbf, 0x64, 0xeb, 0xc8, 0xaf, 0xb2, 0x4e, 0x74,
+       0x4d, 0x9d, 0x7f, 0xa7, 0x0c, 0x5f, 0xf6, 0x62, 0xdd, 0x3a, 0x14, 0xf1,
+       0xd8, 0xb5, 0x8d, 0xcf, 0x12, 0x6b, 0x18, 0xfa, 0x3d, 0xbc, 0x7b, 0xee,
+       0x53, 0x8f, 0x7a, 0xf5, 0xde, 0xfd, 0x28, 0xba, 0xf6, 0xdd, 0x94, 0x44,
+       0xbd, 0x54, 0xef, 0x8d, 0xea, 0x4f, 0x1a, 0xa4, 0x35, 0x08, 0x1e, 0xf5,
+       0xc3, 0xf2, 0xc6, 0x86, 0xb5, 0x63, 0x5c, 0x55, 0xa7, 0xec, 0x68, 0x9d,
+       0xb2, 0xcf, 0xd7, 0x29, 0x7b, 0x7b, 0xe3, 0xda, 0xb2, 0xdb, 0xeb, 0x94,
+       0xcd, 0xd6, 0x29, 0xfb, 0x69, 0x9d, 0x32, 0x69, 0x5a, 0x5b, 0x16, 0xa9,
+       0x53, 0xd6, 0x57, 0xa7, 0x2c, 0x0a, 0xbe, 0xdb, 0x26, 0xf9, 0xf8, 0xbd,
+       0x9c, 0xbb, 0xc5, 0x4d, 0x29, 0xb2, 0x16, 0x37, 0x0d, 0xa8, 0xd7, 0xb9,
+       0xaa, 0xde, 0x17, 0xeb, 0xd4, 0x6b, 0x44, 0xbd, 0xb6, 0x55, 0xf5, 0x76,
+       0xd4, 0xc1, 0x75, 0x13, 0xea, 0xc5, 0x56, 0xd5, 0x7b, 0xb0, 0x4e, 0x3d,
+       0x96, 0x7f, 0xc6, 0x8e, 0xd3, 0x07, 0x2d, 0xf4, 0x5a, 0xeb, 0xd5, 0x28,
+       0xd2, 0xce, 0xf2, 0x5e, 0xe8, 0x90, 0x0e, 0x65, 0xe4, 0x02, 0x65, 0x10,
+       0xcb, 0x3a, 0x41, 0xe7, 0x71, 0xd0, 0x1d, 0xe5, 0x28, 0xf8, 0x8c, 0x73,
+       0xa9, 0x6c, 0x90, 0xb1, 0x78, 0x9f, 0x7b, 0xb5, 0x6a, 0x01, 0x8d, 0xa5,
+       0xdc, 0xa4, 0x22, 0xff, 0x49, 0x2e, 0x32, 0xe4, 0xe5, 0x86, 0x45, 0xc5,
+       0x95, 0x04, 0x32, 0xe2, 0xab, 0x36, 0x25, 0xf7, 0x80, 0xbf, 0xd2, 0xd0,
+       0x59, 0x37, 0x06, 0xc3, 0x9a, 0xb7, 0x4c, 0xdd, 0x8b, 0xcb, 0x54, 0x5f,
+       0x0e, 0x52, 0x16, 0x0e, 0x8d, 0x7e, 0x2a, 0xe3, 0x2d, 0x0c, 0x36, 0x82,
+       0x66, 0xcf, 0xa3, 0xcd, 0x6e, 0xb4, 0xdc, 0x57, 0x8e, 0xca, 0x48, 0x79,
+       0x00, 0xbc, 0xe0, 0xc8, 0x39, 0x6f, 0xa3, 0x9c, 0xf3, 0x51, 0xb7, 0x12,
+       0x91, 0xc5, 0xb8, 0x23, 0x8b, 0x78, 0xce, 0xf8, 0x78, 0x57, 0x09, 0x79,
+       0x6b, 0x40, 0x0e, 0x14, 0x7d, 0x39, 0x5c, 0xbc, 0x41, 0x85, 0x7a, 0x6d,
+       0xa7, 0xbf, 0x5e, 0x1e, 0x73, 0x4d, 0xdf, 0xbb, 0xbd, 0x05, 0x68, 0xd4,
+       0xa8, 0x9c, 0xf7, 0x52, 0x89, 0x45, 0xcd, 0x13, 0xff, 0x27, 0x18, 0x41,
+       0x3f, 0xb3, 0x5e, 0xca, 0xfd, 0x03, 0x3c, 0x8f, 0x95, 0x69, 0xcb, 0x54,
+       0xfb, 0x9a, 0x44, 0x5f, 0x87, 0x8a, 0x1b, 0xe4, 0x56, 0xdb, 0x7e, 0x97,
+       0xb7, 0xd0, 0x0b, 0x9e, 0x73, 0x4f, 0x50, 0x86, 0x14, 0x00, 0xd7, 0x5e,
+       0xf0, 0x36, 0xda, 0x7e, 0x4d, 0xcb, 0x33, 0xd8, 0x3e, 0x85, 0x8d, 0x90,
+       0xcf, 0x7f, 0x17, 0xdc, 0x1a, 0x67, 0x7d, 0x96, 0x51, 0xe7, 0x48, 0x49,
+       0x0d, 0x41, 0x26, 0x0c, 0x50, 0x66, 0x26, 0x21, 0x2f, 0x21, 0x7b, 0x8a,
+       0x3f, 0x0d, 0xd2, 0xd1, 0x5a, 0x39, 0x28, 0xb9, 0x6a, 0x1d, 0x96, 0x25,
+       0x8d, 0x5c, 0x2d, 0x2e, 0x2d, 0xcb, 0x8a, 0x1c, 0xe4, 0xcb, 0x53, 0x15,
+       0xca, 0x85, 0x0f, 0x82, 0x47, 0x3b, 0x65, 0xa4, 0x90, 0xca, 0xa5, 0x65,
+       0x1b, 0xd6, 0xef, 0xd7, 0xb1, 0xa6, 0x51, 0x5c, 0x0f, 0xad, 0x97, 0x56,
+       0x1f, 0xba, 0x9b, 0xe5, 0xe8, 0xb4, 0x9d, 0x36, 0xd2, 0x6f, 0x03, 0x0f,
+       0x93, 0x5c, 0xf3, 0x44, 0x26, 0xe2, 0x8c, 0xd2, 0x5e, 0x19, 0x85, 0x7c,
+       0xcc, 0x96, 0xd9, 0x37, 0xe1, 0x4d, 0xd8, 0xdf, 0xb0, 0x9b, 0x0a, 0x9d,
+       0xf6, 0x77, 0x0b, 0x7e, 0x27, 0xed, 0x6f, 0xc8, 0xd4, 0x82, 0x67, 0x7f,
+       0xc7, 0xb5, 0x1c, 0x32, 0xbf, 0x13, 0xf8, 0xdd, 0xaf, 0x7f, 0x4f, 0x15,
+       0x77, 0xed, 0x52, 0xde, 0x95, 0x92, 0x9d, 0xef, 0x94, 0x03, 0x85, 0x77,
+       0x58, 0xd9, 0x82, 0x4b, 0xbe, 0xe4, 0x98, 0x79, 0x26, 0xf4, 0xba, 0xe7,
+       0x8b, 0x39, 0x67, 0x94, 0xf0, 0xe3, 0xf7, 0x70, 0xa1, 0xcf, 0xdd, 0x24,
+       0xa4, 0x81, 0x29, 0x67, 0xb8, 0xe2, 0xa4, 0x23, 0x43, 0x3d, 0x89, 0x49,
+       0x39, 0x8c, 0xdf, 0xe2, 0x46, 0x86, 0xbe, 0x84, 0xbb, 0xc1, 0xc1, 0x57,
+       0xb6, 0x43, 0xb6, 0x16, 0x29, 0x2f, 0x3d, 0xcc, 0x3d, 0x29, 0x67, 0x56,
+       0xd8, 0x58, 0xc4, 0x85, 0x92, 0xec, 0x74, 0xea, 0x78, 0x4e, 0x52, 0xb9,
+       0x19, 0x30, 0xc4, 0x8d, 0x7e, 0x54, 0xde, 0xe7, 0x83, 0x76, 0xaf, 0x74,
+       0x64, 0xd7, 0x95, 0x51, 0xd8, 0x44, 0xde, 0xcc, 0x2e, 0xc8, 0x58, 0xc8,
+       0xbe, 0x08, 0xe9, 0x41, 0x9d, 0x92, 0xb1, 0xe8, 0x10, 0xb0, 0x7d, 0xaa,
+       0x7f, 0x64, 0xb2, 0x90, 0xbd, 0x5d, 0x0d, 0xed, 0xff, 0x6c, 0x66, 0xe0,
+       0xad, 0x92, 0xdd, 0xab, 0x80, 0xa3, 0xf6, 0x31, 0xc8, 0x4c, 0xcc, 0x2b,
+       0x08, 0x40, 0xcf, 0x90, 0xe7, 0x37, 0xdd, 0x14, 0x19, 0x6a, 0x90, 0xe1,
+       0xbd, 0xed, 0x68, 0xc3, 0x77, 0xc4, 0xd7, 0x79, 0xe0, 0x33, 0x95, 0x1c,
+       0x11, 0xb9, 0x7b, 0x6a, 0x60, 0xc9, 0x99, 0x2c, 0x7d, 0x10, 0x3c, 0x79,
+       0x15, 0xda, 0x3f, 0x80, 0xf6, 0x2f, 0x3b, 0xf9, 0xe9, 0x57, 0x9c, 0xc9,
+       0xe9, 0xbf, 0x75, 0xa6, 0xa6, 0xb7, 0x6c, 0xd9, 0x39, 0xb8, 0x65, 0xcb,
+       0xf8, 0x60, 0xd4, 0xea, 0x97, 0x2d, 0x5b, 0xa6, 0x06, 0x07, 0x81, 0x83,
+       0x3e, 0x77, 0x44, 0x3c, 0x77, 0x97, 0x80, 0x7f, 0xe2, 0x1c, 0x93, 0xfa,
+       0x27, 0x85, 0xf7, 0x6c, 0xef, 0xe9, 0xf7, 0xc3, 0xd2, 0x97, 0x68, 0x13,
+       0x8e, 0x1f, 0xb1, 0x75, 0xda, 0x01, 0xfb, 0x03, 0x76, 0x7d, 0x0b, 0xaa,
+       0xc1, 0x63, 0x39, 0xe7, 0xc2, 0x72, 0xae, 0xed, 0x8f, 0xac, 0x2d, 0xbb,
+       0x11, 0xe5, 0x7c, 0x26, 0xce, 0x88, 0x17, 0xda, 0x22, 0x0d, 0xda, 0x76,
+       0xcc, 0x16, 0x48, 0x33, 0x51, 0x99, 0x28, 0xb4, 0xa1, 0x0d, 0xe8, 0xe2,
+       0x94, 0xbd, 0x8e, 0x02, 0xb6, 0xbd, 0xe8, 0xeb, 0xe8, 0x21, 0xb4, 0xa3,
+       0xcc, 0x48, 0xf5, 0x8a, 0xfa, 0x04, 0xea, 0xf4, 0xb9, 0x9b, 0x85, 0x36,
+       0xc7, 0x71, 0xc9, 0x16, 0xc9, 0xdf, 0x3d, 0x80, 0x27, 0x26, 0xc9, 0x76,
+       0x3c, 0x57, 0x0e, 0xc0, 0x0e, 0x69, 0xb0, 0x3a, 0x33, 0x94, 0x17, 0xfc,
+       0x77, 0x87, 0x12, 0xef, 0x80, 0x8c, 0xcd, 0x5d, 0x8e, 0x7a, 0x0e, 0xf0,
+       0x42, 0x3b, 0x05, 0x36, 0xcb, 0x5c, 0x5a, 0x32, 0xdb, 0xee, 0xc5, 0xdd,
+       0xc5, 0x73, 0x1e, 0xf7, 0xb7, 0xe0, 0x3e, 0x89, 0x7b, 0x08, 0x27, 0xf0,
+       0xea, 0x47, 0xac, 0xce, 0xba, 0x06, 0x63, 0xff, 0x6b, 0xc9, 0x94, 0x12,
+       0xb4, 0x39, 0x36, 0x66, 0xbc, 0xb4, 0xab, 0x44, 0x6d, 0x56, 0x32, 0x85,
+       0xfa, 0xf0, 0x09, 0xbc, 0x83, 0x32, 0x7e, 0x12, 0xbf, 0x1f, 0xa4, 0x4d,
+       0x3c, 0x25, 0xe3, 0x73, 0x1c, 0xa7, 0x00, 0x98, 0x4a, 0x92, 0x3d, 0xf9,
+       0x00, 0xae, 0x69, 0x5c, 0x0f, 0xe3, 0xe2, 0xdc, 0xd8, 0xff, 0xe2, 0x26,
+       0x05, 0x5c, 0xf3, 0x39, 0x4b, 0x3a, 0xae, 0xe0, 0x37, 0x69, 0xb8, 0x42,
+       0xdb, 0x06, 0xf4, 0x5b, 0x09, 0xe9, 0xda, 0xb7, 0xbf, 0x13, 0x9a, 0xaf,
+       0x73, 0x6d, 0xa0, 0x99, 0xca, 0xa0, 0x96, 0x39, 0x19, 0x0f, 0xf7, 0x0a,
+       0x6c, 0x8f, 0x36, 0xce, 0xd1, 0xb3, 0x65, 0x9e, 0x2e, 0x4b, 0xea, 0xb2,
+       0x7e, 0x5b, 0x86, 0x7b, 0xa5, 0x41, 0xc6, 0xda, 0x01, 0x31, 0xe5, 0xb3,
+       0x84, 0xf8, 0xa4, 0x0c, 0x00, 0xfd, 0xc2, 0x66, 0x38, 0x73, 0x51, 0xf9,
+       0xb7, 0xa4, 0x6d, 0xb1, 0xc7, 0x2b, 0xa4, 0x63, 0xd2, 0x76, 0x10, 0xdc,
+       0xef, 0x37, 0xa1, 0x7f, 0xf2, 0xbc, 0x48, 0xc3, 0xd1, 0xa8, 0xcc, 0xb8,
+       0xa4, 0x85, 0x77, 0xb4, 0x90, 0x06, 0x1a, 0x3d, 0xd2, 0x70, 0x2d, 0x7f,
+       0x71, 0x0d, 0xd9, 0x5f, 0x0e, 0xf6, 0x1d, 0xed, 0xbc, 0x1e, 0xd8, 0xce,
+       0x1c, 0xe3, 0x30, 0x9f, 0x5d, 0x05, 0x9e, 0xca, 0x2c, 0xf3, 0x94, 0xc8,
+       0x6c, 0x81, 0xb8, 0x09, 0xed, 0x3f, 0xae, 0x33, 0xf1, 0xf3, 0x38, 0xe6,
+       0xcc, 0xfb, 0x19, 0x8b, 0xa7, 0x2f, 0x59, 0x3c, 0x7d, 0xd9, 0xde, 0x5d,
+       0x27, 0xab, 0x6d, 0xc1, 0x05, 0x3c, 0x73, 0x7d, 0xa2, 0x1a, 0x67, 0xd9,
+       0xc2, 0x0c, 0xee, 0xa8, 0x5b, 0x7c, 0x5c, 0xc6, 0xb5, 0x9d, 0x16, 0x91,
+       0x77, 0x69, 0xd9, 0x06, 0x21, 0xdd, 0x5c, 0x00, 0xcc, 0x0d, 0x92, 0x8b,
+       0x47, 0xf4, 0xda, 0x47, 0xbd, 0x03, 0x51, 0x43, 0xab, 0xc4, 0xc9, 0x0a,
+       0x5f, 0xaa, 0x06, 0xa6, 0xb8, 0x95, 0x73, 0x84, 0x8b, 0xb4, 0xfb, 0x88,
+       0x86, 0xeb, 0x16, 0xc8, 0xbb, 0x9c, 0xa8, 0xf6, 0x46, 0xb9, 0x0c, 0xb4,
+       0xa0, 0xe2, 0xd0, 0x5c, 0xc1, 0xd3, 0xb0, 0x9b, 0xb2, 0x73, 0xb4, 0xa1,
+       0xbb, 0xe8, 0xb7, 0xc4, 0xb2, 0xfd, 0xad, 0xa4, 0x23, 0xa5, 0x60, 0x7f,
+       0xe1, 0x59, 0x65, 0xfb, 0x35, 0x9d, 0x3a, 0xca, 0x8b, 0x6b, 0x3b, 0x19,
+       0xbc, 0x12, 0xb1, 0xbe, 0x73, 0x54, 0x79, 0x9b, 0x57, 0x97, 0x25, 0xa9,
+       0x87, 0xd1, 0x2e, 0x99, 0xed, 0x6f, 0x27, 0x8f, 0xb9, 0xca, 0x03, 0x2e,
+       0x3d, 0xed, 0x1b, 0xe5, 0xd4, 0xc0, 0xc6, 0x55, 0xf5, 0xf5, 0xdd, 0xb1,
+       0xcf, 0x51, 0x7b, 0x77, 0xed, 0x3d, 0x69, 0xef, 0xb9, 0xe8, 0x00, 0xef,
+       0x8e, 0x44, 0x87, 0x78, 0xc7, 0x1a, 0x0e, 0xb1, 0x0f, 0xcd, 0x57, 0x56,
+       0xce, 0xf4, 0xb8, 0x79, 0x21, 0x5f, 0xfd, 0xa9, 0xdc, 0x32, 0x67, 0xe4,
+       0xef, 0x2e, 0xc8, 0x20, 0xf8, 0x6f, 0xee, 0xa2, 0x00, 0xfe, 0xbd, 0x65,
+       0xb9, 0xa5, 0x42, 0xbc, 0xfd, 0x06, 0xf0, 0xb7, 0x35, 0x4a, 0xde, 0x74,
+       0x85, 0x72, 0xf7, 0x4e, 0xd1, 0xf6, 0x69, 0x81, 0x38, 0x3f, 0x2b, 0x5c,
+       0x9b, 0x7c, 0xe1, 0x19, 0xbd, 0x36, 0x07, 0x0b, 0x8b, 0xc0, 0xcf, 0xd7,
+       0x41, 0xf7, 0x41, 0xb0, 0xe8, 0xe7, 0x41, 0x39, 0x7f, 0x84, 0xdf, 0xe8,
+       0xbb, 0xf0, 0x1c, 0xde, 0xb7, 0x4a, 0xbe, 0x44, 0x9e, 0x8b, 0x5a, 0x1e,
+       0x3e, 0x05, 0x7e, 0xba, 0x0c, 0xfd, 0xa2, 0x6c, 0x80, 0xbf, 0xff, 0x11,
+       0xef, 0x70, 0x9f, 0xc3, 0x22, 0xb6, 0xd3, 0xd6, 0xe1, 0xd8, 0x5c, 0x3b,
+       0xae, 0x59, 0x5c, 0xfb, 0xad, 0x8f, 0x2f, 0xaf, 0x1b, 0xd7, 0x2b, 0xd5,
+       0x9b, 0x93, 0x70, 0xcd, 0x44, 0x1e, 0x2f, 0xb0, 0x3e, 0xe9, 0xff, 0x1f,
+       0x62, 0x46, 0x17, 0xfc, 0xc9, 0x3a, 0x73, 0x5f, 0xdd, 0x96, 0x6b, 0x5e,
+       0x4b, 0x83, 0xf4, 0x6f, 0x52, 0x83, 0x39, 0xc8, 0x9d, 0xa8, 0xd7, 0x2a,
+       0x23, 0xda, 0x27, 0x22, 0x4d, 0x90, 0x06, 0x6e, 0x56, 0x86, 0x36, 0x3f,
+       0xa4, 0x0c, 0x6d, 0x3e, 0x03, 0x5a, 0xc4, 0x55, 0x5c, 0x72, 0x0c, 0x6d,
+       0x7e, 0x1d, 0x77, 0x5c, 0xc5, 0x0b, 0x4e, 0xc8, 0xc7, 0xc3, 0xf0, 0xf9,
+       0x76, 0x15, 0xa2, 0xce, 0x78, 0x05, 0xf4, 0x5b, 0x8c, 0xa1, 0x7c, 0x81,
+       0x38, 0xc7, 0xfc, 0x39, 0xce, 0x56, 0xdb, 0xff, 0xe3, 0x32, 0x51, 0x0c,
+       0xb4, 0x5d, 0x95, 0x9d, 0xbb, 0x17, 0xf7, 0xf5, 0x5a, 0xce, 0x28, 0x2f,
+       0xad, 0x8c, 0xbc, 0x7a, 0x17, 0xee, 0xdd, 0x89, 0x83, 0xd2, 0xed, 0x46,
+       0xe4, 0x39, 0xf4, 0xf5, 0x43, 0x67, 0xa2, 0xf2, 0x32, 0xae, 0x9f, 0xe0,
+       0x7a, 0x15, 0xd7, 0x2b, 0xe8, 0xf7, 0x45, 0x94, 0xaf, 0x97, 0x05, 0xb7,
+       0x19, 0xf5, 0x45, 0x8d, 0x57, 0x5e, 0x70, 0xc6, 0x4e, 0xbe, 0x84, 0x2b,
+       0xaa, 0x26, 0x2a, 0xcf, 0x3b, 0xd9, 0xb9, 0x60, 0xe3, 0xa2, 0x47, 0x19,
+       0xf6, 0xa7, 0x8e, 0xe9, 0x7b, 0x08, 0x73, 0x00, 0x4d, 0x17, 0x17, 0x30,
+       0xf6, 0x33, 0x9a, 0x67, 0x46, 0x20, 0xf3, 0xb3, 0xb0, 0x4b, 0xc6, 0x34,
+       0x4c, 0x97, 0x03, 0x3e, 0xf8, 0xba, 0x03, 0xb8, 0xcf, 0x35, 0xca, 0x52,
+       0x9c, 0x76, 0xe4, 0x97, 0x75, 0xfd, 0x6c, 0xb1, 0x5b, 0xe3, 0x76, 0x66,
+       0x0d, 0xff, 0xd0, 0x3f, 0x0b, 0xe5, 0x81, 0x91, 0xc6, 0xb3, 0x05, 0xca,
+       0x02, 0xe8, 0x9f, 0xc2, 0x14, 0xee, 0x8d, 0x5a, 0x26, 0xe4, 0x25, 0x94,
+       0x07, 0x6c, 0x47, 0x99, 0x50, 0x2b, 0x77, 0x28, 0x6b, 0x28, 0x7b, 0x28,
+       0x4b, 0xcc, 0x7a, 0x8c, 0x3f, 0x48, 0x19, 0x7e, 0x2d, 0xfc, 0x53, 0xda,
+       0x1f, 0x9d, 0xc6, 0x07, 0x99, 0xce, 0x28, 0x23, 0x4f, 0xf7, 0xe8, 0xb5,
+       0x98, 0x28, 0xa8, 0x38, 0x20, 0x47, 0x19, 0xae, 0x63, 0x7b, 0x71, 0xcf,
+       0xaa, 0x09, 0x5c, 0xd9, 0x63, 0x1f, 0xc0, 0x6f, 0xae, 0xcd, 0x04, 0xea,
+       0xe1, 0x2a, 0x8e, 0xe2, 0x8e, 0x0b, 0xb6, 0x99, 0x91, 0x23, 0x5c, 0xd3,
+       0x84, 0x5d, 0xd3, 0x2f, 0x03, 0x0f, 0x9c, 0x9f, 0xd2, 0xf1, 0x07, 0xe5,
+       0xed, 0x00, 0xde, 0x2b, 0xd6, 0xdf, 0x6d, 0x15, 0xc3, 0x83, 0xb8, 0x7a,
+       0xc9, 0xcf, 0x2d, 0x66, 0xbd, 0x34, 0xed, 0x7e, 0x37, 0x6a, 0x78, 0x31,
+       0x8e, 0xb2, 0x08, 0xca, 0xda, 0x45, 0xf3, 0xfe, 0x32, 0x1e, 0xd3, 0x16,
+       0x8f, 0xfc, 0xad, 0xec, 0x6f, 0xd0, 0x13, 0x6c, 0xda, 0x8c, 0x37, 0x80,
+       0x71, 0x31, 0x97, 0x63, 0x7b, 0xd4, 0x38, 0xe4, 0xf7, 0xb8, 0x47, 0x19,
+       0xce, 0x38, 0x03, 0xe7, 0xc7, 0x7e, 0x51, 0xae, 0x71, 0xe0, 0x4b, 0xd5,
+       0x87, 0xff, 0x32, 0xd6, 0xec, 0x71, 0xd9, 0x57, 0xbc, 0x5a, 0xfb, 0xd4,
+       0x8d, 0x47, 0xcd, 0x7a, 0x88, 0x0a, 0xeb, 0xa1, 0xef, 0x38, 0x6d, 0x9b,
+       0x31, 0xfd, 0x3e, 0x7a, 0x94, 0xbf, 0x29, 0x9f, 0x6b, 0xe5, 0xbd, 0xb1,
+       0x6b, 0xf2, 0x2b, 0x64, 0x1d, 0x6d, 0x0b, 0xac, 0x59, 0xb9, 0x16, 0xef,
+       0xf4, 0xf1, 0x29, 0xf3, 0xc8, 0x4f, 0x07, 0xc1, 0x13, 0xaa, 0xc1, 0xf0,
+       0x3e, 0x7d, 0x8d, 0x7a, 0xfc, 0x04, 0xfb, 0x0b, 0xbc, 0x72, 0x02, 0xb6,
+       0xdb, 0xae, 0xe5, 0x3e, 0x20, 0x2b, 0xe3, 0x31, 0x39, 0x59, 0x68, 0x91,
+       0xb9, 0x82, 0x82, 0xc1, 0x60, 0x64, 0x67, 0x44, 0x12, 0x5a, 0xff, 0xd2,
+       0xbe, 0x1b, 0x9e, 0x8e, 0x58, 0xba, 0x83, 0xc3, 0xd2, 0xfc, 0x1b, 0xd0,
+       0xb1, 0x65, 0xe8, 0xd8, 0x56, 0xe8, 0xe0, 0xd5, 0x32, 0xa2, 0xab, 0x61,
+       0xad, 0x8c, 0x60, 0x9b, 0x14, 0xbc, 0xf2, 0x83, 0x68, 0x17, 0xd2, 0x5f,
+       0x4c, 0xd3, 0x5a, 0x56, 0x72, 0xce, 0xae, 0xca, 0x94, 0xb3, 0xbb, 0xb2,
+       0x5a, 0x07, 0xf5, 0xb9, 0x51, 0x31, 0xb0, 0x9e, 0xd4, 0x71, 0xbc, 0x94,
+       0x9f, 0x01, 0x4e, 0x76, 0x83, 0xee, 0x9e, 0x2e, 0xc1, 0x8f, 0xa7, 0x5c,
+       0x06, 0xcc, 0x8f, 0x01, 0xe6, 0xd9, 0x92, 0x13, 0xda, 0x06, 0xc2, 0xe0,
+       0xc9, 0xec, 0x74, 0xbf, 0x2c, 0xce, 0x93, 0x0e, 0x21, 0x03, 0x4a, 0x58,
+       0x4f, 0x7f, 0x1d, 0xec, 0x00, 0x8e, 0x0f, 0xb9, 0x3d, 0xdd, 0xa1, 0xdf,
+       0x19, 0x7d, 0xde, 0x29, 0x8b, 0xe5, 0xf7, 0x58, 0xd8, 0x0e, 0xd7, 0xc0,
+       0xb6, 0x6e, 0x19, 0xb6, 0xdd, 0x80, 0x6d, 0x4f, 0x5d, 0xd8, 0xea, 0xe9,
+       0xe2, 0x2e, 0xd8, 0x34, 0xe4, 0x8f, 0x10, 0xaf, 0xed, 0x96, 0x1e, 0x6e,
+       0xb7, 0xf6, 0x2e, 0x6d, 0xa2, 0x9f, 0x02, 0x1e, 0xd2, 0x18, 0x7e, 0xcf,
+       0x3d, 0x4a, 0x59, 0x86, 0x72, 0x3e, 0x7f, 0x06, 0x75, 0xf0, 0x3c, 0xf7,
+       0xe7, 0x56, 0x0e, 0xde, 0x65, 0x61, 0xa1, 0x9d, 0x90, 0x86, 0x4d, 0x3c,
+       0xe2, 0x64, 0xe6, 0x08, 0x43, 0x0e, 0xf0, 0xe2, 0x5d, 0xa5, 0xb6, 0x4f,
+       0xde, 0xd9, 0xef, 0x15, 0xb6, 0x1f, 0xf6, 0x1d, 0xce, 0x65, 0xbd, 0xd5,
+       0xf3, 0x21, 0x7d, 0x85, 0xf6, 0xf5, 0x94, 0x93, 0x5e, 0x33, 0xaf, 0x5a,
+       0x9a, 0xa3, 0xbc, 0x8d, 0xca, 0x4e, 0xd0, 0xc9, 0xce, 0x15, 0xb4, 0xa6,
+       0xdd, 0x10, 0x4b, 0xc7, 0xeb, 0xec, 0xfc, 0x0e, 0x18, 0xbe, 0xf1, 0x63,
+       0xd0, 0x87, 0x94, 0x37, 0x37, 0x1b, 0xdf, 0x5c, 0x4e, 0x00, 0xd6, 0xf0,
+       0x99, 0xb4, 0xc9, 0xdf, 0x94, 0x49, 0x55, 0x5a, 0x34, 0xbe, 0x4b, 0xa7,
+       0x8e, 0x9f, 0x56, 0xed, 0xf5, 0xa8, 0x8c, 0x9a, 0x35, 0x3f, 0xcc, 0x35,
+       0xa7, 0x2f, 0xd2, 0xfd, 0xc0, 0xa8, 0xe5, 0xaf, 0x54, 0x29, 0x27, 0xbb,
+       0xed, 0xdc, 0xbf, 0x5c, 0x67, 0xed, 0x5a, 0x97, 0xd7, 0x6e, 0xb4, 0xb2,
+       0x7a, 0x8e, 0x22, 0x5d, 0x0f, 0x44, 0xb5, 0x6f, 0x2b, 0xca, 0x97, 0x46,
+       0x8f, 0xf2, 0x93, 0xb6, 0x12, 0xca, 0x67, 0xfb, 0xdc, 0x36, 0xd0, 0xdb,
+       0x53, 0x6b, 0xec, 0xae, 0xa4, 0x95, 0x9b, 0xf4, 0x83, 0xc3, 0x31, 0x72,
+       0x56, 0x4e, 0xe6, 0xd0, 0xff, 0x94, 0xb3, 0xb3, 0x52, 0x4f, 0x5e, 0x86,
+       0x72, 0x92, 0xf3, 0xb9, 0x57, 0xee, 0x78, 0x90, 0x3c, 0x7a, 0xbb, 0xb6,
+       0xaf, 0xaf, 0xda, 0x71, 0x00, 0xf8, 0x23, 0xfc, 0x8b, 0x9b, 0x60, 0x32,
+       0x40, 0xe7, 0xa6, 0x65, 0xdc, 0xae, 0xdb, 0xf8, 0xf2, 0xfa, 0xf3, 0x6a,
+       0xc7, 0x6f, 0xc6, 0x59, 0x95, 0x85, 0x59, 0xdb, 0xb1, 0xb0, 0xeb, 0x56,
+       0xdb, 0xb2, 0x9c, 0x03, 0xed, 0xd9, 0x46, 0x63, 0x0b, 0x16, 0x69, 0x7f,
+       0x52, 0x76, 0xd1, 0xfe, 0x8c, 0x35, 0x4a, 0x33, 0xe7, 0x33, 0x68, 0xcb,
+       0x68, 0xa7, 0xae, 0x9e, 0xdf, 0x6a, 0xff, 0x91, 0x70, 0x12, 0x6e, 0x43,
+       0x5b, 0x49, 0x45, 0xd8, 0x02, 0x19, 0xf5, 0xaf, 0xd5, 0x6b, 0xa0, 0x68,
+       0xbb, 0xee, 0xf8, 0x76, 0x83, 0x89, 0x31, 0x27, 0xd1, 0x3f, 0xc7, 0x24,
+       0xff, 0xf1, 0x4e, 0x3b, 0xbf, 0x9e, 0x2c, 0xab, 0xd5, 0x3d, 0x97, 0x2d,
+       0xe3, 0x6f, 0xe7, 0x8a, 0x35, 0x0a, 0xf1, 0x17, 0xd2, 0x45, 0x2d, 0x0e,
+       0x49, 0x13, 0xa4, 0x85, 0x90, 0x16, 0xb7, 0x5a, 0x7d, 0x13, 0xd2, 0xde,
+       0xa5, 0xa0, 0xbd, 0xfb, 0x80, 0x27, 0xca, 0x70, 0xc6, 0xed, 0x36, 0xe3,
+       0xf9, 0x08, 0x9e, 0x43, 0x3e, 0xb9, 0x98, 0x0c, 0xa7, 0xfc, 0x66, 0x9b,
+       0x8c, 0x95, 0xfb, 0xa1, 0x9f, 0xcb, 0x36, 0x9c, 0x37, 0xe5, 0xff, 0x57,
+       0xe9, 0x77, 0x35, 0x1a, 0x3b, 0xfd, 0x43, 0x8d, 0x94, 0xaf, 0x9b, 0xe4,
+       0x60, 0x4d, 0xd9, 0xc5, 0xe4, 0x77, 0xed, 0x9c, 0x2f, 0xff, 0x7f, 0x30,
+       0xe7, 0xc4, 0xaa, 0x39, 0xbb, 0x76, 0xce, 0x15, 0xbc, 0x6f, 0xc3, 0xfb,
+       0x16, 0xea, 0x82, 0x64, 0x55, 0xde, 0x58, 0x5c, 0xe8, 0x79, 0xd5, 0xca,
+       0x89, 0x50, 0x46, 0x70, 0x5e, 0x1f, 0xb1, 0x73, 0x78, 0xa0, 0x66, 0x5e,
+       0x1f, 0x79, 0x13, 0xf3, 0xea, 0x5c, 0x31, 0xaf, 0x5d, 0x17, 0x9d, 0x57,
+       0x3d, 0x1e, 0x27, 0x2f, 0x87, 0xf3, 0x8b, 0xc9, 0x8d, 0x05, 0xce, 0x71,
+       0x27, 0xe6, 0x48, 0x18, 0xc2, 0x39, 0x0e, 0xd9, 0x39, 0x8a, 0xea, 0xda,
+       0xf1, 0x73, 0xf8, 0x5d, 0x3b, 0x3f, 0xea, 0xfe, 0x1f, 0x83, 0xa6, 0x9b,
+       0x24, 0xd3, 0xdf, 0x64, 0xe5, 0xff, 0x97, 0xe5, 0xd6, 0x22, 0xd7, 0x3a,
+       0x95, 0x16, 0xd9, 0xa3, 0xf6, 0x15, 0x9f, 0x6d, 0x64, 0x8c, 0x7f, 0x97,
+       0x6f, 0xf5, 0x18, 0xf4, 0xc5, 0x6e, 0xd8, 0x7c, 0x3b, 0x0b, 0x6a, 0x20,
+       0x22, 0x41, 0x70, 0x9b, 0xdf, 0x8c, 0xb1, 0x37, 0x6a, 0x5f, 0x75, 0x6d,
+       0x7c, 0xfd, 0x99, 0x46, 0xf1, 0x68, 0x6f, 0x50, 0x9f, 0x43, 0xdf, 0x1d,
+       0xa3, 0x0d, 0x96, 0x81, 0x9d, 0x9c, 0x4e, 0x44, 0xb4, 0x2d, 0x46, 0x9d,
+       0x98, 0x4a, 0xa4, 0xa5, 0x2c, 0xd9, 0x63, 0xe9, 0x84, 0x12, 0x8e, 0x01,
+       0x5b, 0x0d, 0x36, 0xe4, 0xad, 0x90, 0x35, 0xb7, 0x56, 0xf6, 0xaa, 0x5b,
+       0x60, 0xef, 0xdc, 0x72, 0xf2, 0x03, 0xea, 0x36, 0xd8, 0x3a, 0xb7, 0x9d,
+       0xbc, 0x41, 0xed, 0x83, 0x6d, 0xb3, 0x0f, 0x76, 0xce, 0xbe, 0x0a, 0x6d,
+       0xcf, 0x9b, 0x41, 0x7b, 0x9d, 0x35, 0xb4, 0x46, 0x1b, 0x87, 0xf3, 0x23,
+       0xee, 0x8f, 0x71, 0x0d, 0xfc, 0xa4, 0x7a, 0x45, 0xaf, 0x4b, 0xdb, 0x8a,
+       0xb2, 0xd7, 0x92, 0x55, 0xa1, 0x7e, 0xda, 0x60, 0xe3, 0x46, 0x94, 0xb7,
+       0xaf, 0x45, 0x5b, 0xa4, 0x11, 0x17, 0x78, 0x26, 0xfe, 0x48, 0x5b, 0xb5,
+       0xf3, 0xdf, 0xd4, 0x24, 0x5e, 0x67, 0x93, 0x34, 0xdf, 0x0b, 0xf9, 0x5a,
+       0x4b, 0x53, 0xbc, 0xbb, 0x56, 0xd7, 0x90, 0xb6, 0x28, 0x83, 0x43, 0x7a,
+       0xd8, 0xfa, 0x1a, 0xf2, 0xf7, 0xa2, 0xf4, 0x74, 0x4f, 0x64, 0x28, 0x08,
+       0xc6, 0x07, 0x64, 0x23, 0xe3, 0x01, 0x99, 0x4a, 0x35, 0x26, 0xa0, 0xbc,
+       0xda, 0x98, 0x00, 0xfd, 0xac, 0x47, 0x80, 0xdf, 0x19, 0x5c, 0x22, 0x63,
+       0x8c, 0x3b, 0x54, 0x42, 0xbb, 0xfc, 0x1b, 0xd6, 0x2e, 0x0f, 0xe1, 0x48,
+       0x02, 0x0e, 0x23, 0x9f, 0xd7, 0xea, 0xb9, 0x95, 0xfa, 0x3b, 0xb7, 0x6c,
+       0xd3, 0x26, 0xe5, 0xc6, 0x22, 0xe7, 0x4d, 0x19, 0x4c, 0xdc, 0xd4, 0xca,
+       0xe0, 0x84, 0xb5, 0xa3, 0x50, 0x47, 0xcb, 0xcf, 0xb5, 0xb2, 0x93, 0x72,
+       0x8f, 0xf1, 0xf9, 0x07, 0x7c, 0xd2, 0xfa, 0x7b, 0x24, 0xbd, 0x1c, 0x9f,
+       0x17, 0xd0, 0x9b, 0xf8, 0x91, 0x21, 0xbd, 0xdf, 0xe6, 0xce, 0xca, 0x6e,
+       0x19, 0x8e, 0x33, 0xd6, 0xc9, 0x78, 0x9e, 0x97, 0x9b, 0x05, 0x0f, 0x4c,
+       0x16, 0x15, 0x2c, 0xf8, 0x46, 0x19, 0x73, 0x03, 0xd9, 0xe5, 0x3b, 0x3a,
+       0x76, 0x6c, 0x74, 0xed, 0x4c, 0x93, 0xb1, 0x5d, 0x1d, 0x1d, 0xff, 0x5d,
+       0x04, 0xf5, 0x2d, 0x6a, 0xfb, 0x56, 0x69, 0xfd, 0xbb, 0xa0, 0xeb, 0x7c,
+       0xae, 0x29, 0x8c, 0x63, 0x2e, 0xba, 0x11, 0x5b, 0xaf, 0xb6, 0xfc, 0x8b,
+       0x36, 0x3e, 0x9d, 0x84, 0xec, 0x0f, 0xcb, 0xfe, 0xb0, 0x4e, 0xd9, 0xb7,
+       0xea, 0x94, 0xfd, 0xcf, 0x3a, 0x65, 0x26, 0x2e, 0xb8, 0xb3, 0xf0, 0xf7,
+       0x78, 0x37, 0xa5, 0x7d, 0x77, 0xb1, 0xfb, 0x61, 0xb9, 0xe5, 0x3a, 0x1b,
+       0xac, 0x5f, 0xc6, 0x18, 0xb1, 0x89, 0x0d, 0x67, 0x75, 0x6c, 0xb8, 0xcf,
+       0xdd, 0xa1, 0xf4, 0x5e, 0xca, 0x7e, 0xc6, 0x19, 0xf7, 0x69, 0xbc, 0x10,
+       0x27, 0x5f, 0x61, 0x0c, 0x38, 0xc7, 0xbd, 0xd8, 0xa4, 0xba, 0x18, 0x6d,
+       0x57, 0x6d, 0x13, 0xb3, 0x6e, 0xb4, 0x8b, 0x5b, 0x64, 0x04, 0xb6, 0xc2,
+       0xce, 0x42, 0x9b, 0xec, 0x9a, 0x1e, 0x58, 0x47, 0xbd, 0xb5, 0x7b, 0xda,
+       0xf8, 0x83, 0xfb, 0xc0, 0x57, 0x69, 0x21, 0x8c, 0x29, 0x5f, 0x84, 0x36,
+       0xf1, 0x5a, 0x5b, 0xf8, 0xb5, 0xfb, 0xfb, 0xa5, 0x8b, 0xf4, 0xe7, 0xc0,
+       0x76, 0x78, 0xa3, 0xfd, 0x35, 0xcb, 0xc8, 0x74, 0x88, 0x2b, 0xf5, 0x33,
+       0xb6, 0x8b, 0x5c, 0xa4, 0x9d, 0xb6, 0x4b, 0xe4, 0xe9, 0x65, 0x59, 0xbc,
+       0x15, 0x36, 0x93, 0x04, 0x99, 0x01, 0xe9, 0x8c, 0x88, 0x8e, 0xf1, 0xf8,
+       0x46, 0x36, 0xf7, 0x70, 0x6f, 0x07, 0xf4, 0x6f, 0x6c, 0x15, 0x13, 0x37,
+       0x0d, 0xed, 0x94, 0x7a, 0xb4, 0x7b, 0x9d, 0xa5, 0x5d, 0xee, 0xb9, 0xee,
+       0xa6, 0xcc, 0xd5, 0x6b, 0x42, 0x3a, 0xde, 0x55, 0x90, 0x64, 0x48, 0xc7,
+       0x8b, 0x92, 0x5e, 0x41, 0xc7, 0x8b, 0x32, 0xa4, 0xe9, 0xb8, 0x71, 0x05,
+       0x1d, 0x77, 0x5a, 0x3a, 0xde, 0x13, 0x33, 0x74, 0xa1, 0xb4, 0x9e, 0x22,
+       0x9d, 0x1a, 0x3a, 0x76, 0x34, 0x1d, 0x2f, 0xe2, 0x1e, 0xf5, 0xae, 0xb3,
+       0x75, 0x22, 0xb6, 0x8c, 0xbf, 0xc3, 0x32, 0xca, 0xc5, 0x4f, 0xc6, 0x8c,
+       0x5e, 0x1a, 0x02, 0x1d, 0x85, 0xe5, 0xfb, 0x6d, 0xfc, 0xa0, 0xb6, 0xcc,
+       0xc4, 0x47, 0x76, 0x16, 0xc6, 0x62, 0x2b, 0xe9, 0x73, 0x08, 0xf4, 0x19,
+       0xd6, 0x79, 0x2d, 0xfa, 0x6c, 0xb6, 0xfb, 0x16, 0x71, 0xbd, 0x2f, 0x9f,
+       0x8e, 0x1b, 0x5a, 0xbd, 0x45, 0xcf, 0x9d, 0xf3, 0x3e, 0xfb, 0x06, 0x68,
+       0xd5, 0xac, 0xcd, 0xb9, 0xaa, 0xbf, 0xcd, 0x58, 0x54, 0xd2, 0xc4, 0xb0,
+       0x19, 0x27, 0xbd, 0x98, 0xed, 0x68, 0xe4, 0x53, 0x83, 0x96, 0x4f, 0xad,
+       0x63, 0xcc, 0x35, 0xa8, 0xca, 0xec, 0x01, 0xe8, 0x0a, 0xda, 0xd8, 0x5a,
+       0x4e, 0xe3, 0x5d, 0x67, 0x32, 0x53, 0x78, 0x35, 0x88, 0x78, 0x8c, 0x0f,
+       0x71, 0x5f, 0x40, 0xc6, 0x1c, 0x94, 0x75, 0x95, 0xcd, 0xbc, 0x94, 0xd7,
+       0x8a, 0xe7, 0x01, 0xe9, 0x2a, 0x2b, 0xf9, 0xe8, 0x74, 0x8b, 0xec, 0x2f,
+       0x44, 0xe5, 0xe3, 0x68, 0xff, 0xb1, 0x82, 0x0b, 0x7f, 0xfc, 0x4c, 0x8c,
+       0x76, 0xe1, 0xbe, 0x02, 0xf7, 0x27, 0x59, 0x37, 0xbe, 0x6a, 0x7f, 0x36,
+       0x22, 0x5d, 0x3d, 0x79, 0x78, 0x2a, 0x12, 0xdd, 0x03, 0x38, 0x9a, 0x86,
+       0x86, 0xe4, 0x07, 0x03, 0x1b, 0x51, 0xf6, 0xb2, 0x1d, 0x6f, 0xd4, 0x31,
+       0xf1, 0xde, 0x41, 0x79, 0x77, 0x65, 0x48, 0xae, 0xaf, 0x98, 0x3d, 0xd5,
+       0xea, 0x9e, 0x69, 0xca, 0x5d, 0x80, 0xfe, 0x49, 0xbb, 0x41, 0x70, 0xce,
+       0xc3, 0xaa, 0x1f, 0x89, 0x4a, 0xac, 0x27, 0x95, 0x58, 0x10, 0xf3, 0x7c,
+       0xbe, 0xfc, 0x0f, 0xc1, 0x58, 0x3c, 0x2a, 0x3f, 0xf0, 0x38, 0xc7, 0x41,
+       0xb9, 0xae, 0x5c, 0x3b, 0x36, 0x97, 0xf3, 0x0f, 0x63, 0xdc, 0xa7, 0xc8,
+       0x54, 0x16, 0x62, 0x8c, 0xa5, 0xd3, 0xe7, 0xe8, 0x7a, 0x1b, 0xfc, 0x38,
+       0x48, 0xee, 0xae, 0xb7, 0x81, 0x6e, 0xe2, 0xd0, 0xf9, 0x57, 0x01, 0xc6,
+       0xab, 0x18, 0xfb, 0x62, 0xcc, 0x8b, 0xcf, 0x5f, 0xc7, 0xb8, 0x6c, 0xfb,
+       0x1b, 0xd6, 0x5e, 0xe6, 0xfa, 0x1b, 0xde, 0xa9, 0xaf, 0x77, 0x5a, 0xc7,
+       0x62, 0x43, 0xe2, 0xc4, 0xde, 0x91, 0x90, 0x75, 0x5e, 0xed, 0xf8, 0xdc,
+       0x27, 0x86, 0xc5, 0x38, 0x20, 0xd1, 0xdd, 0xdb, 0x07, 0x65, 0x04, 0xf3,
+       0xdb, 0xb9, 0x66, 0x7e, 0xf7, 0x08, 0xe3, 0xab, 0xe7, 0x0b, 0x9c, 0x43,
+       0x75, 0x5e, 0xea, 0x0b, 0x66, 0x5e, 0xb1, 0x9e, 0xd5, 0xf3, 0xd1, 0xed,
+       0xd5, 0x09, 0xc0, 0xf2, 0x35, 0x9d, 0x57, 0x10, 0x04, 0x6f, 0xed, 0x39,
+       0x1f, 0x24, 0x2f, 0x49, 0xf5, 0x2e, 0x54, 0xf7, 0x77, 0xc6, 0x22, 0x43,
+       0x69, 0xad, 0xcf, 0xf0, 0x9c, 0xcc, 0x96, 0xd3, 0x58, 0x47, 0x89, 0x66,
+       0xfb, 0xa3, 0x9a, 0x4f, 0xb2, 0x5e, 0xda, 0xee, 0x61, 0x85, 0x3e, 0x54,
+       0x10, 0x28, 0x6f, 0xb5, 0xdc, 0xa0, 0xbe, 0xc2, 0xdc, 0xe5, 0xdf, 0xda,
+       0x1c, 0x96, 0x5e, 0xc6, 0xb3, 0xc6, 0xa2, 0x43, 0xb1, 0x64, 0xbe, 0xec,
+       0xe1, 0x77, 0x0b, 0xee, 0x3b, 0x60, 0xaf, 0xf8, 0xb0, 0x67, 0x24, 0xae,
+       0x8c, 0x6c, 0x00, 0x2d, 0xf7, 0xe4, 0x94, 0x22, 0x6f, 0xba, 0xc9, 0xc9,
+       0x72, 0x3c, 0x59, 0x2a, 0x7f, 0x96, 0xed, 0x51, 0xb7, 0x5e, 0x2c, 0xcf,
+       0xc8, 0x86, 0xa7, 0x2a, 0x1c, 0x83, 0xfe, 0xef, 0x1b, 0x19, 0x23, 0x6a,
+       0xfb, 0x66, 0x9f, 0x21, 0x5e, 0xa2, 0x74, 0xc9, 0xf1, 0x2f, 0x6d, 0x7d,
+       0x13, 0xce, 0xef, 0xb3, 0x16, 0xee, 0xd5, 0xe3, 0xbe, 0xa0, 0xed, 0x97,
+       0xd3, 0x15, 0xda, 0x8c, 0xdc, 0xdf, 0x49, 0x1d, 0x9f, 0x11, 0xc2, 0x11,
+       0x04, 0xcf, 0xf9, 0x46, 0x77, 0x3f, 0x55, 0xe1, 0x1e, 0x47, 0x10, 0xfc,
+       0x88, 0x76, 0xf1, 0xde, 0x22, 0xc6, 0x0b, 0x71, 0xb0, 0x35, 0x17, 0x85,
+       0x5c, 0x9c, 0x1a, 0x20, 0x7e, 0x05, 0x1e, 0x6a, 0x8f, 0x7b, 0xa3, 0xc4,
+       0x92, 0x9f, 0x2a, 0xb7, 0x24, 0x3f, 0x5d, 0x76, 0x81, 0x67, 0xce, 0x3b,
+       0x9e, 0x9c, 0xb0, 0x73, 0xce, 0x96, 0x89, 0xdf, 0xd7, 0xda, 0x87, 0x7c,
+       0x61, 0x85, 0xbf, 0x44, 0x98, 0xaa, 0xb0, 0x10, 0xb6, 0xa4, 0xc5, 0x4d,
+       0x10, 0xfc, 0xd8, 0x37, 0x6b, 0x3a, 0x55, 0x94, 0x29, 0x8c, 0x9b, 0xdb,
+       0xac, 0x88, 0x87, 0x58, 0xf2, 0x0e, 0x8c, 0xfd, 0x29, 0x8c, 0xbd, 0xbf,
+       0xcc, 0xf1, 0x20, 0x2b, 0x30, 0xf7, 0xa9, 0x4a, 0x08, 0x6f, 0xbd, 0xb1,
+       0xc3, 0x35, 0xef, 0xb5, 0x36, 0x5e, 0xf8, 0xac, 0x11, 0xd9, 0xae, 0xbc,
+       0x7e, 0xd0, 0xd7, 0xe2, 0xa6, 0xa8, 0xfc, 0x22, 0xe4, 0x6e, 0x20, 0x8f,
+       0x42, 0x9e, 0x2d, 0x6a, 0xba, 0xc9, 0x5c, 0xce, 0xff, 0x23, 0xf2, 0xeb,
+       0xeb, 0x18, 0x5f, 0x1e, 0xf6, 0x68, 0xbb, 0x2e, 0x05, 0x8b, 0x1e, 0xe5,
+       0xf3, 0x06, 0x99, 0x71, 0x73, 0xbd, 0xd0, 0x15, 0x28, 0x6b, 0xa5, 0xbf,
+       0x9d, 0xcc, 0x44, 0x52, 0xc9, 0x49, 0x61, 0x3e, 0x14, 0x73, 0x15, 0x98,
+       0x23, 0x44, 0xd9, 0x10, 0x85, 0xcc, 0xe3, 0x1a, 0x9a, 0xf1, 0x26, 0xcb,
+       0xd5, 0xba, 0x07, 0x84, 0x7b, 0x86, 0xa9, 0xc4, 0x3e, 0x6d, 0x9f, 0x88,
+       0x8c, 0x17, 0x58, 0x77, 0x3b, 0xac, 0x13, 0xaf, 0xa6, 0xbe, 0xce, 0xe1,
+       0x02, 0x9f, 0x87, 0x71, 0xac, 0x58, 0x2c, 0x53, 0x90, 0x97, 0x23, 0x03,
+       0xf2, 0x32, 0xed, 0xce, 0x61, 0xd0, 0xb6, 0xeb, 0xf1, 0xbd, 0x29, 0xcf,
+       0xf8, 0xb2, 0x94, 0x19, 0xec, 0xa3, 0x9d, 0x9d, 0x53, 0x9a, 0x27, 0x44,
+       0xa1, 0x6d, 0x2c, 0x5b, 0x96, 0x91, 0x6c, 0xc1, 0xc6, 0x7a, 0x46, 0x39,
+       0xe7, 0x0d, 0x35, 0x73, 0x6f, 0x95, 0x28, 0x60, 0x1a, 0x89, 0x24, 0x9d,
+       0x06, 0xef, 0x23, 0x2d, 0x46, 0xe7, 0x43, 0xee, 0xb7, 0xdd, 0xdf, 0xce,
+       0x3d, 0x53, 0x05, 0x1f, 0x5a, 0xb5, 0xdf, 0x7e, 0x8d, 0x1a, 0xfa, 0xf3,
+       0x04, 0xf4, 0xa0, 0x95, 0x95, 0xb1, 0x91, 0xae, 0x65, 0xfa, 0xe6, 0xf8,
+       0xd2, 0x1e, 0xf1, 0x92, 0x23, 0xc3, 0x65, 0x51, 0x91, 0x21, 0x37, 0x36,
+       0x5c, 0x5e, 0x49, 0xf3, 0x4f, 0x55, 0xfe, 0xbd, 0xb5, 0x05, 0x6b, 0x63,
+       0xaa, 0xb5, 0xef, 0xc8, 0x77, 0x2b, 0xf6, 0x2b, 0x92, 0x26, 0x07, 0x86,
+       0xfb, 0xb4, 0x5c, 0x93, 0xf4, 0x5b, 0x1b, 0xa0, 0x7c, 0x66, 0xb4, 0x8f,
+       0xc6, 0x9c, 0x8b, 0x98, 0xcd, 0x3d, 0x33, 0xb8, 0x4e, 0x97, 0x1d, 0x99,
+       0x82, 0x7c, 0x38, 0x20, 0x7f, 0x1f, 0xa4, 0xe3, 0xe6, 0xbd, 0x59, 0x5f,
+       0xd6, 0xe7, 0x5e, 0x44, 0xb3, 0xe4, 0x4f, 0x46, 0x25, 0x77, 0x92, 0x7b,
+       0x60, 0xcf, 0xed, 0xaf, 0xe6, 0x6d, 0x50, 0x0e, 0x70, 0xbf, 0xd6, 0x91,
+       0x3c, 0xfc, 0xda, 0x11, 0xee, 0xc3, 0xf7, 0xff, 0x1f, 0xf4, 0xc1, 0x7a,
+       0x61, 0xdb, 0x16, 0xb4, 0x6d, 0xb4, 0x6d, 0x47, 0xef, 0x78, 0x73, 0x6d,
+       0x5b, 0xd1, 0x36, 0x16, 0x8e, 0xfb, 0x06, 0xdb, 0x6a, 0x7c, 0x5e, 0x33,
+       0x5c, 0x28, 0x2e, 0xc1, 0x4f, 0x4e, 0x4c, 0x48, 0xda, 0x19, 0x1f, 0xd0,
+       0xf3, 0xb9, 0x66, 0xb8, 0x0c, 0x38, 0xe2, 0x41, 0x90, 0xf7, 0x43, 0x3d,
+       0xcc, 0x7f, 0xc7, 0x44, 0x3c, 0x96, 0x71, 0xdf, 0x92, 0xfe, 0x04, 0xa3,
+       0xa4, 0x2e, 0xf3, 0xd9, 0x24, 0xcf, 0xfd, 0xc9, 0xf8, 0x46, 0xdc, 0x55,
+       0x17, 0x71, 0x92, 0xf5, 0x18, 0xef, 0xdd, 0x68, 0xcb, 0x23, 0x2c, 0x4f,
+       0x45, 0x21, 0x4b, 0x4c, 0x79, 0xc4, 0x96, 0x03, 0x26, 0x3f, 0x9f, 0x04,
+       0xb7, 0xd9, 0x72, 0x3e, 0x2b, 0x5d, 0x6e, 0x9e, 0x0d, 0x0f, 0x8d, 0x09,
+       0xe3, 0x3a, 0x99, 0xeb, 0x1a, 0x64, 0x2b, 0xd6, 0x87, 0x3e, 0xa3, 0x23,
+       0xcd, 0x80, 0xe3, 0x9c, 0xff, 0x76, 0xd8, 0xd6, 0x81, 0xfc, 0xc0, 0x37,
+       0xf4, 0x3f, 0x2b, 0x3d, 0x69, 0xe5, 0x30, 0x07, 0x20, 0x90, 0x9d, 0xfe,
+       0xb6, 0xc4, 0x2e, 0xfc, 0x1e, 0xef, 0x4f, 0xca, 0xec, 0x20, 0xe8, 0xb1,
+       0x9f, 0xbc, 0xb1, 0x15, 0x36, 0x0f, 0x7e, 0xf7, 0xb4, 0xc8, 0x92, 0x9b,
+       0x73, 0xd7, 0xc1, 0x5f, 0x1b, 0xc1, 0xac, 0xe6, 0x0a, 0x9e, 0x7b, 0x1b,
+       0x84, 0x5c, 0xda, 0xed, 0xc1, 0xbd, 0x76, 0xbe, 0xdf, 0xc2, 0x7c, 0x7f,
+       0xad, 0x59, 0x9a, 0x59, 0x5e, 0x5b, 0xb7, 0x51, 0xf6, 0xb8, 0xdb, 0xdd,
+       0xd8, 0x8a, 0xba, 0xe7, 0x51, 0x97, 0x65, 0x9e, 0xcb, 0x1c, 0x9d, 0xd9,
+       0x32, 0xe9, 0xcc, 0xc0, 0xda, 0xd5, 0x13, 0x04, 0xd7, 0xf9, 0x1c, 0x37,
+       0x08, 0xae, 0xf7, 0xfb, 0xdc, 0x67, 0xe5, 0xf9, 0xc0, 0xd8, 0x54, 0x21,
+       0xed, 0x3c, 0x67, 0xe5, 0x75, 0x10, 0xbc, 0xec, 0xf7, 0xca, 0xef, 0x54,
+       0x52, 0x8f, 0xd3, 0xe7, 0x3e, 0x83, 0xe7, 0x33, 0xbe, 0xc9, 0x2b, 0xfa,
+       0x13, 0xb4, 0x8b, 0xab, 0x7e, 0xd0, 0xb0, 0x27, 0x5f, 0xd4, 0x3e, 0x3a,
+       0xf1, 0x67, 0x62, 0xfc, 0x55, 0x18, 0x30, 0x61, 0x2f, 0xb3, 0xc9, 0x65,
+       0x7e, 0xa0, 0xa6, 0xdf, 0xda, 0x77, 0x0a, 0xef, 0x58, 0x16, 0x04, 0x97,
+       0x0c, 0xfc, 0x31, 0xe6, 0x94, 0x2a, 0x71, 0xef, 0xee, 0x03, 0x9a, 0xff,
+       0x04, 0x7e, 0x3d, 0xe9, 0x24, 0xea, 0x2a, 0xe5, 0x1d, 0xee, 0x52, 0xa9,
+       0x9c, 0xc8, 0x5b, 0xb0, 0xfe, 0x5c, 0x63, 0x30, 0x48, 0x1b, 0x60, 0xdf,
+       0xb6, 0xbd, 0xd9, 0xc4, 0x92, 0xe8, 0x4b, 0xa7, 0x37, 0xc1, 0xd7, 0xd5,
+       0xf6, 0x4c, 0x14, 0x7c, 0x3d, 0xd1, 0x16, 0x04, 0xef, 0xf7, 0xc3, 0x35,
+       0xb3, 0xb1, 0x6a, 0xe8, 0xf8, 0x6c, 0xff, 0xb9, 0x66, 0x63, 0xc7, 0x31,
+       0x4f, 0x30, 0xa9, 0xe3, 0xfa, 0xaa, 0x1d, 0x3a, 0x64, 0xdb, 0x57, 0x39,
+       0x7e, 0x8e, 0xe5, 0xef, 0xf3, 0x43, 0x98, 0xaa, 0xed, 0xb3, 0xfd, 0xeb,
+       0xac, 0xcd, 0x19, 0x05, 0x2e, 0x3d, 0xb7, 0x4b, 0xfd, 0x4d, 0x60, 0x74,
+       0x6b, 0x48, 0xc3, 0x7f, 0x17, 0x3c, 0x18, 0x37, 0xcf, 0x99, 0x6d, 0xec,
+       0x63, 0xab, 0x4c, 0x6e, 0xc3, 0x73, 0xf4, 0x5a, 0xdc, 0x87, 0x2f, 0x8b,
+       0xc8, 0x15, 0x89, 0x61, 0xb5, 0xcd, 0x7d, 0x50, 0xfa, 0xac, 0x8c, 0xfb,
+       0x1a, 0xf4, 0x7d, 0x0e, 0xfe, 0x78, 0x93, 0x3c, 0x08, 0x9a, 0x56, 0x03,
+       0xa9, 0xe4, 0x82, 0x4a, 0xf5, 0xce, 0xa8, 0x94, 0x3f, 0xa6, 0xae, 0xe7,
+       0xbc, 0x06, 0x89, 0x8b, 0x19, 0xe2, 0xb7, 0x08, 0xfc, 0x17, 0x81, 0xe3,
+       0x8b, 0xee, 0xf1, 0xfa, 0x56, 0xb7, 0x18, 0xfd, 0x96, 0xd3, 0xb4, 0x69,
+       0xec, 0xf2, 0x3f, 0xf6, 0xc3, 0x35, 0x84, 0x6d, 0xc8, 0x1c, 0x99, 0xba,
+       0x6b, 0x94, 0xe5, 0x1a, 0x41, 0x31, 0xe4, 0x40, 0xf7, 0xa9, 0xe4, 0x84,
+       0x5a, 0x0a, 0x36, 0xed, 0xe8, 0xee, 0x7d, 0x42, 0xf7, 0x93, 0xf2, 0xd3,
+       0x2a, 0x0f, 0x78, 0xb6, 0x4a, 0xd3, 0x0e, 0xe2, 0x99, 0xb0, 0xc6, 0x18,
+       0x4f, 0x72, 0xef, 0x40, 0xdd, 0x31, 0xa5, 0xf7, 0xa0, 0x6d, 0x1d, 0xc2,
+       0x1c, 0x5f, 0x2f, 0xcd, 0xd4, 0x43, 0x8c, 0x93, 0xbd, 0x96, 0x2e, 0x84,
+       0x4c, 0x3a, 0x46, 0x19, 0x18, 0x31, 0xb1, 0xdf, 0xca, 0xcf, 0xa1, 0x9d,
+       0xce, 0x67, 0x89, 0x45, 0x21, 0xa3, 0xa6, 0xc0, 0xc5, 0x87, 0x8e, 0x49,
+       0xb4, 0xc1, 0xfb, 0x5f, 0xcd, 0xc6, 0x6f, 0xa2, 0x0f, 0xc5, 0xb1, 0x1b,
+       0x24, 0xbf, 0x26, 0xde, 0x52, 0x02, 0xfc, 0xcd, 0x32, 0x79, 0x8c, 0x6b,
+       0x11, 0x85, 0xcc, 0xe1, 0xd8, 0x12, 0xcd, 0xf4, 0x07, 0xc1, 0x38, 0xcb,
+       0x4f, 0x92, 0x7f, 0x25, 0xc5, 0x77, 0xb9, 0x93, 0x0b, 0x9b, 0xd4, 0x0a,
+       0x59, 0xdb, 0x62, 0xe1, 0xd0, 0x78, 0x92, 0x92, 0x96, 0x23, 0xd4, 0x37,
+       0xb7, 0xd5, 0xc0, 0x33, 0x7a, 0xc7, 0x94, 0xd7, 0xf8, 0x26, 0xe0, 0xf9,
+       0x3d, 0xc0, 0xd3, 0x62, 0xe1, 0x69, 0x5c, 0x05, 0x4f, 0x4b, 0x08, 0x0f,
+       0xe4, 0x1c, 0xe5, 0x6a, 0xec, 0x9a, 0x74, 0x59, 0x9c, 0xbc, 0x27, 0x9d,
+       0x4a, 0xfb, 0x2f, 0xd4, 0x37, 0x8d, 0xee, 0xf8, 0x80, 0x2b, 0xe3, 0x5a,
+       0xd7, 0x44, 0xaf, 0xe9, 0x2e, 0x2f, 0xc0, 0x7a, 0x15, 0x27, 0xe3, 0x11,
+       0xf6, 0x7a, 0x76, 0xd5, 0x3d, 0x90, 0xff, 0x8b, 0xa9, 0xa8, 0xb5, 0x25,
+       0x4a, 0x3e, 0xfd, 0x96, 0xb8, 0xde, 0xdb, 0xaf, 0xc2, 0xf4, 0x12, 0x60,
+       0x82, 0x3c, 0x3e, 0xd6, 0xe7, 0x8e, 0xca, 0xa5, 0xda, 0x37, 0xb3, 0xb8,
+       0xc6, 0xdc, 0x62, 0x35, 0x73, 0x83, 0xfe, 0x53, 0xe1, 0xdc, 0x20, 0x13,
+       0x51, 0xaf, 0x24, 0xf7, 0x5b, 0x5c, 0xb4, 0x62, 0x4e, 0xb1, 0x9a, 0xf9,
+       0x74, 0x27, 0xf6, 0xb3, 0xcc, 0xcc, 0xa7, 0x27, 0xef, 0xc5, 0x2c, 0x7e,
+       0x57, 0xc3, 0x58, 0xf5, 0x17, 0x67, 0x24, 0x90, 0x29, 0x1f, 0x6b, 0xd4,
+       0x4b, 0xff, 0x24, 0x66, 0xf3, 0x98, 0x15, 0x9e, 0x37, 0x58, 0xfe, 0x72,
+       0x25, 0xaf, 0xfd, 0xb7, 0x2f, 0xad, 0x37, 0x7c, 0x1a, 0xb5, 0xf9, 0x6b,
+       0xfc, 0xdd, 0xb1, 0xde, 0xee, 0xef, 0xe7, 0xd2, 0xf2, 0xfb, 0xeb, 0x69,
+       0x97, 0x34, 0x78, 0x43, 0xab, 0xca, 0x62, 0x28, 0xbb, 0x7d, 0xbd, 0x95,
+       0x0b, 0x28, 0xbb, 0x07, 0x7e, 0x1a, 0xf3, 0x34, 0xf8, 0x8e, 0x32, 0xb8,
+       0x16, 0x27, 0x7d, 0x60, 0x45, 0xf2, 0x3c, 0xe5, 0x22, 0x6d, 0x4a, 0xcc,
+       0x51, 0x7d, 0x27, 0x8c, 0xa3, 0xe3, 0x77, 0x3d, 0xdb, 0x9f, 0xf8, 0x26,
+       0xae, 0xe5, 0xdb, 0x53, 0xe0, 0xfb, 0x03, 0xbe, 0x13, 0x9d, 0x65, 0x1e,
+       0x80, 0xa6, 0xe1, 0xda, 0xbe, 0xaf, 0x47, 0xdf, 0x21, 0x2d, 0x93, 0x5e,
+       0xae, 0xd7, 0x74, 0xd3, 0x44, 0x5d, 0x7c, 0x8c, 0xf4, 0xc7, 0x58, 0x72,
+       0xb3, 0xd6, 0x8f, 0xd5, 0x75, 0x6c, 0x82, 0xae, 0x89, 0x1b, 0x1e, 0x75,
+       0xcd, 0x7e, 0x77, 0xb5, 0xbf, 0x31, 0xf4, 0x47, 0x3b, 0x0d, 0x7e, 0xba,
+       0xc7, 0x68, 0x0e, 0xe5, 0x97, 0x13, 0x55, 0x57, 0x6a, 0x3f, 0x33, 0xa6,
+       0xf3, 0x8e, 0x96, 0xeb, 0x4e, 0xd8, 0xb1, 0x49, 0xb7, 0x26, 0xfe, 0x5f,
+       0x1d, 0x5f, 0x1c, 0xb5, 0x4d, 0x40, 0x65, 0x8d, 0x32, 0x35, 0x40, 0x1a,
+       0xe5, 0xdc, 0xb5, 0x0d, 0x75, 0x0d, 0xed, 0x08, 0x43, 0x9f, 0xb4, 0x9d,
+       0xa2, 0xd7, 0x64, 0x0b, 0x8d, 0xc6, 0x67, 0x89, 0xcb, 0xe6, 0x06, 0x9d,
+       0x47, 0x80, 0xb2, 0x72, 0xa8, 0xcb, 0xa2, 0x32, 0xdb, 0xff, 0xbf, 0x83,
+       0xf4, 0x5e, 0xd6, 0xad, 0xbb, 0x6f, 0x9f, 0x98, 0x11, 0x8d, 0xa7, 0xbf,
+       0xa8, 0xe2, 0xc9, 0xce, 0x2d, 0xbe, 0x7a, 0x6e, 0x05, 0xc0, 0x7b, 0x0f,
+       0x64, 0x27, 0xd7, 0xc9, 0xe4, 0x6f, 0x3f, 0x2e, 0x4e, 0x34, 0xd3, 0x5b,
+       0x6f, 0x6e, 0xa5, 0x10, 0xaf, 0x9c, 0x1b, 0x68, 0x35, 0x9c, 0x17, 0x69,
+       0x3b, 0xae, 0xf7, 0x89, 0x94, 0x22, 0x2c, 0xad, 0xab, 0x70, 0x1b, 0xd2,
+       0x9d, 0xa1, 0xb9, 0xa7, 0x34, 0xcd, 0xb5, 0x58, 0x9a, 0x43, 0x5d, 0x97,
+       0xfb, 0xde, 0xa3, 0x2d, 0x55, 0x9a, 0xdb, 0x60, 0x69, 0xee, 0x99, 0xf5,
+       0x66, 0x4f, 0xfc, 0xfd, 0x2d, 0x66, 0x4f, 0xea, 0x2f, 0x57, 0x3d, 0x6f,
+       0xa2, 0xcd, 0x08, 0x5f, 0x2c, 0x7c, 0xae, 0x85, 0xf5, 0x0c, 0x60, 0xad,
+       0x95, 0x35, 0x4d, 0x36, 0xee, 0xc6, 0xfd, 0x73, 0xfa, 0x7d, 0x51, 0x79,
+       0x14, 0x76, 0x50, 0xbe, 0xfc, 0x8f, 0xc1, 0x02, 0x7c, 0xbf, 0xa9, 0x65,
+       0xdd, 0x7b, 0x5b, 0x0b, 0xf9, 0x6d, 0x06, 0xbf, 0x0e, 0xd6, 0xf8, 0x3c,
+       0x98, 0x2f, 0xca, 0xfe, 0x01, 0xeb, 0x01, 0xb9, 0xbc, 0x5c, 0x97, 0x31,
+       0x0b, 0xe3, 0xe3, 0x30, 0x66, 0x68, 0xf6, 0x13, 0x29, 0xe7, 0xef, 0x84,
+       0x4f, 0x74, 0x0f, 0xf4, 0x24, 0xe9, 0xfb, 0xa5, 0x16, 0x93, 0xe7, 0x1b,
+       0x87, 0x1e, 0xfb, 0x65, 0x9b, 0x0b, 0x75, 0xf8, 0x57, 0xeb, 0xe7, 0xf8,
+       0x82, 0xf6, 0x1d, 0xd2, 0xcc, 0xdf, 0xb7, 0x98, 0x98, 0xf1, 0xb7, 0x5a,
+       0xc8, 0x67, 0x6a, 0xdb, 0x0f, 0x37, 0x68, 0xbe, 0x70, 0xc2, 0xe7, 0xcf,
+       0xb4, 0xae, 0x7c, 0x0e, 0xdb, 0x3d, 0xd9, 0xba, 0xb2, 0x5d, 0x58, 0xfe,
+       0x73, 0x1b, 0x57, 0x96, 0x5f, 0xe3, 0xae, 0x6c, 0xff, 0xf5, 0x55, 0xcf,
+       0x2d, 0x9b, 0x56, 0x3e, 0x5f, 0xbd, 0xea, 0x79, 0x6a, 0xd5, 0xf3, 0x85,
+       0x55, 0xcf, 0x57, 0xb5, 0xad, 0x7c, 0xbe, 0xbd, 0xad, 0x3e, 0xbc, 0x87,
+       0xdb, 0x56, 0xc2, 0x75, 0xa7, 0x8e, 0xf7, 0xcf, 0x54, 0xa2, 0xb2, 0xab,
+       0x80, 0xf7, 0x4e, 0xe7, 0x66, 0xa3, 0xd7, 0x6a, 0xdf, 0x33, 0xbe, 0xf6,
+       0xd7, 0xab, 0xfa, 0xab, 0xb6, 0xdb, 0x5d, 0x6d, 0xe7, 0x57, 0xdb, 0x19,
+       0xd9, 0x36, 0x5b, 0xe1, 0x3b, 0x96, 0x87, 0xfd, 0x9a, 0xb6, 0x53, 0xc5,
+       0x4e, 0x9d, 0x0b, 0x3b, 0xaa, 0x73, 0x61, 0x93, 0xe0, 0xc3, 0x3b, 0x75,
+       0x4c, 0x69, 0x93, 0x42, 0x79, 0xa5, 0x55, 0xc7, 0x95, 0x74, 0x2c, 0xb5,
+       0x30, 0x0a, 0xdb, 0x96, 0x39, 0xb0, 0x81, 0xec, 0xf1, 0xcd, 0xdd, 0xe4,
+       0xc4, 0x1e, 0x0e, 0x86, 0xdd, 0x20, 0x98, 0xf4, 0x6e, 0xb3, 0xf9, 0x62,
+       0xb8, 0x57, 0x4c, 0x1b, 0xea, 0xe0, 0x27, 0xa0, 0x83, 0xab, 0xba, 0xf7,
+       0x4e, 0x8c, 0xb5, 0x00, 0x9a, 0x19, 0x90, 0xdf, 0xad, 0xa4, 0xbe, 0x24,
+       0xfa, 0xcc, 0x4d, 0x3f, 0x6c, 0xb8, 0xa5, 0x4f, 0xbd, 0xdf, 0xf3, 0x61,
+       0xeb, 0x05, 0xf2, 0xb0, 0x3f, 0x08, 0x1a, 0xea, 0x85, 0xbd, 0xe7, 0x69,
+       0xbf, 0xf4, 0xb4, 0xa6, 0x2d, 0xd2, 0x58, 0x8b, 0xce, 0xd7, 0x7f, 0xd4,
+       0x77, 0x62, 0x99, 0xfe, 0x3f, 0x32, 0x71, 0x1a, 0xbf, 0xdb, 0xfd, 0x1a,
+       0xf8, 0x76, 0xa7, 0xb7, 0x05, 0x3e, 0x0a, 0x69, 0x88, 0xf1, 0xaf, 0xcb,
+       0x75, 0x1e, 0x21, 0x03, 0x68, 0x33, 0x51, 0xc6, 0x09, 0x53, 0x83, 0x63,
+       0xc2, 0x79, 0xa7, 0x12, 0x49, 0xa5, 0xed, 0xaa, 0xe0, 0x46, 0x9f, 0x39,
+       0xb6, 0xdc, 0x63, 0x21, 0x3f, 0xef, 0xff, 0xf4, 0x94, 0x97, 0x73, 0x23,
+       0x36, 0x2f, 0x37, 0x53, 0x30, 0xb4, 0x39, 0x41, 0xda, 0x84, 0x3f, 0xb5,
+       0xd8, 0xff, 0xb7, 0x01, 0xed, 0xfb, 0xa4, 0x22, 0xed, 0xff, 0x4d, 0x30,
+       0x17, 0x65, 0x5f, 0x84, 0x7b, 0xff, 0xa7, 0x33, 0x1a, 0x57, 0x77, 0xca,
+       0x81, 0x22, 0x6d, 0xe1, 0x98, 0xce, 0xe7, 0x18, 0xf7, 0x69, 0xa7, 0xc5,
+       0x80, 0xc7, 0x0f, 0x01, 0x7f, 0x2d, 0xb0, 0xb9, 0x47, 0x50, 0x27, 0x22,
+       0x63, 0x60, 0xf1, 0xd9, 0x02, 0xf9, 0x93, 0xf7, 0x28, 0xea, 0xbb, 0x32,
+       0x5f, 0xb8, 0x59, 0xe7, 0xdb, 0x9d, 0x46, 0xdb, 0x27, 0x71, 0xcd, 0x16,
+       0x26, 0xd0, 0x66, 0xaf, 0xae, 0x3f, 0x5b, 0x62, 0x8e, 0xb2, 0x40, 0x2e,
+       0xed, 0x97, 0xfc, 0x5c, 0x97, 0x8c, 0xc5, 0x17, 0x66, 0xa2, 0xcb, 0x71,
+       0x99, 0x8f, 0x6f, 0xe0, 0x1e, 0x47, 0xfe, 0x4a, 0xee, 0x07, 0x4b, 0x74,
+       0x74, 0xbb, 0xea, 0x6d, 0xd3, 0x3e, 0xd7, 0xa0, 0xec, 0xac, 0x0c, 0xc9,
+       0x4d, 0x95, 0xcf, 0x6e, 0x36, 0xb1, 0xa8, 0x15, 0xf1, 0xad, 0xc3, 0xc4,
+       0x8a, 0x3a, 0x1a, 0xe5, 0xb9, 0x25, 0x99, 0x3d, 0x25, 0x12, 0x39, 0x1a,
+       0xc6, 0x12, 0x59, 0xe6, 0x4a, 0xd7, 0x95, 0x80, 0xeb, 0x14, 0x64, 0x6b,
+       0x3c, 0x26, 0x5f, 0xdc, 0x16, 0x8e, 0x95, 0x0b, 0xa6, 0xb7, 0xe5, 0xe4,
+       0xd3, 0xb8, 0xb2, 0x57, 0xa6, 0x4a, 0x19, 0xc5, 0x71, 0xbf, 0x13, 0x50,
+       0x96, 0xa9, 0x21, 0x4f, 0x72, 0x6d, 0xe1, 0xd8, 0xf0, 0x6f, 0x76, 0x84,
+       0xe3, 0xd3, 0xe6, 0x36, 0x67, 0x1e, 0xf2, 0xdc, 0x77, 0x01, 0xfd, 0x45,
+       0x86, 0xee, 0xde, 0x40, 0xdf, 0x61, 0x58, 0xd8, 0x0e, 0x32, 0x5d, 0xb1,
+       0x6f, 0xc2, 0x49, 0xf8, 0x6b, 0xe1, 0x5c, 0x4c, 0xc6, 0x81, 0xa3, 0xdc,
+       0xeb, 0xc2, 0xdb, 0xe7, 0x7a, 0xaa, 0x1e, 0xbc, 0xa3, 0x36, 0x96, 0xc8,
+       0xf8, 0xe0, 0x3a, 0xe0, 0xad, 0x05, 0xe5, 0x1f, 0x94, 0xa9, 0x63, 0x6f,
+       0xdb, 0xcc, 0xbd, 0xec, 0x06, 0xcf, 0xb1, 0x39, 0xa7, 0x3c, 0xbf, 0x73,
+       0x37, 0xea, 0xf0, 0xfd, 0xcd, 0x68, 0x93, 0xca, 0x65, 0x22, 0x9b, 0xe1,
+       0x13, 0x71, 0xdc, 0x20, 0xd2, 0xb5, 0xa3, 0x59, 0xe7, 0x90, 0xca, 0x29,
+       0xea, 0xf3, 0xb0, 0xed, 0xdd, 0x3a, 0x47, 0x03, 0x7e, 0x7b, 0x6e, 0x24,
+       0x42, 0xf9, 0xd5, 0x2b, 0xc3, 0xd4, 0x27, 0xa7, 0x6e, 0xd6, 0xb4, 0xdf,
+       0xbd, 0x8d, 0x67, 0x99, 0xfa, 0x8c, 0x8d, 0x1e, 0x27, 0x8c, 0xa3, 0x28,
+       0x87, 0xfd, 0xfe, 0x9a, 0x30, 0xdc, 0xf5, 0x26, 0x61, 0xb8, 0xeb, 0x4d,
+       0xc2, 0x40, 0x5c, 0x00, 0x8e, 0xca, 0x5f, 0x6c, 0x08, 0x63, 0xd5, 0x97,
+       0x62, 0x1e, 0x07, 0x8b, 0x77, 0xc9, 0xa1, 0xa2, 0xa3, 0xe3, 0x8e, 0x0b,
+       0x8a, 0x32, 0xc1, 0x05, 0x4f, 0x82, 0xf7, 0x8a, 0xe0, 0xcd, 0x22, 0x78,
+       0xb1, 0x08, 0xbe, 0x84, 0xfd, 0x7f, 0x06, 0xf6, 0xff, 0x93, 0x58, 0x9b,
+       0xd3, 0x2b, 0x78, 0x39, 0xad, 0x79, 0x39, 0x5f, 0xa4, 0xaf, 0xd6, 0x7f,
+       0x11, 0x7e, 0x8d, 0xca, 0x70, 0x21, 0x05, 0x55, 0xe2, 0x44, 0xb3, 0xfd,
+       0x9f, 0x24, 0xbf, 0xca, 0x83, 0xfe, 0x0d, 0x68, 0x73, 0x18, 0x34, 0x9e,
+       0xa2, 0x1d, 0x48, 0xfb, 0x27, 0x07, 0xde, 0x3c, 0x4c, 0x5f, 0x4d, 0x5d,
+       0xb9, 0x49, 0xa8, 0x5f, 0xa2, 0x3b, 0x98, 0x7b, 0xc8, 0xb9, 0x26, 0x57,
+       0xe1, 0xc9, 0xf0, 0xef, 0x84, 0x47, 0x3d, 0x43, 0xbe, 0x7d, 0x99, 0x7c,
+       0x5b, 0xc3, 0xab, 0x01, 0xe7, 0x17, 0xb8, 0xdb, 0xea, 0xb5, 0xad, 0xd6,
+       0xdf, 0xb4, 0x5c, 0x5f, 0x8f, 0x5f, 0x22, 0x3f, 0x42, 0x27, 0x11, 0xf7,
+       0xc9, 0x4c, 0x64, 0x8b, 0xc5, 0x3d, 0x6c, 0xb7, 0x1d, 0x97, 0x00, 0xf7,
+       0x9d, 0x92, 0x9b, 0x0f, 0xc4, 0xdb, 0x11, 0xf6, 0x59, 0xed, 0xc7, 0xb5,
+       0xfd, 0x8c, 0x17, 0x1c, 0x19, 0xd9, 0xc6, 0x7d, 0x08, 0x07, 0x7a, 0x3e,
+       0x5c, 0x0f, 0xd8, 0xfb, 0x7a, 0xcd, 0x29, 0x63, 0x29, 0x5b, 0x5b, 0x6c,
+       0xfc, 0x89, 0xfd, 0x1d, 0x5e, 0xb5, 0x4e, 0x17, 0x02, 0x9e, 0x11, 0x9b,
+       0xf2, 0x6e, 0xa8, 0xa1, 0x95, 0xfb, 0x2c, 0xad, 0xa8, 0x55, 0xf3, 0xb8,
+       0xdd, 0xd2, 0x4a, 0x08, 0x6f, 0x3c, 0xa4, 0x95, 0xa6, 0x90, 0x56, 0x72,
+       0x33, 0x21, 0xad, 0xb0, 0xed, 0xed, 0x21, 0xad, 0x24, 0x6b, 0x69, 0x25,
+       0x37, 0xe3, 0xe0, 0x5a, 0x0d, 0x07, 0xe9, 0x85, 0xfd, 0x90, 0x5e, 0x00,
+       0x4b, 0xe5, 0xd6, 0xd6, 0x90, 0x5e, 0xe2, 0xe8, 0xe7, 0x50, 0xd1, 0xe4,
+       0x74, 0xc0, 0xef, 0xb2, 0x3a, 0xc4, 0xc5, 0x9a, 0x1b, 0x1f, 0xb1, 0x3e,
+       0x8d, 0xf8, 0x96, 0x46, 0xaa, 0x79, 0xee, 0xab, 0x68, 0x03, 0xb8, 0x67,
+       0x2e, 0xeb, 0x76, 0x4d, 0x1b, 0xf7, 0xfb, 0x53, 0xa8, 0xbb, 0x07, 0xb4,
+       0x11, 0xe2, 0xe0, 0x7a, 0x8b, 0x83, 0xd5, 0x6b, 0x39, 0x66, 0x71, 0xb0,
+       0xc7, 0xe2, 0x40, 0xf3, 0x4b, 0x8e, 0x6b, 0xa6, 0x34, 0x0e, 0x9a, 0x34,
+       0x0e, 0x44, 0x85, 0x6d, 0xc7, 0xea, 0xe0, 0x80, 0x75, 0xf6, 0xe8, 0xf9,
+       0x47, 0x30, 0xff, 0xfd, 0x98, 0xbf, 0xd2, 0xf3, 0xe7, 0x3a, 0x70, 0xfe,
+       0x80, 0xa5, 0x72, 0x72, 0x79, 0xfe, 0x6d, 0xe8, 0xe3, 0x60, 0x31, 0xa2,
+       0xe7, 0x0f, 0xdb, 0x7e, 0x30, 0x9c, 0xff, 0xe9, 0x8a, 0xc9, 0x7f, 0x3e,
+       0xbd, 0x46, 0xcf, 0x4d, 0x59, 0xde, 0xf0, 0xb4, 0x5f, 0xcc, 0x98, 0xf6,
+       0x19, 0xe8, 0xb6, 0x69, 0x3f, 0x69, 0xcf, 0x43, 0x19, 0x7b, 0xe9, 0x1b,
+       0x3e, 0x79, 0xe7, 0xe3, 0x3a, 0x0f, 0xe5, 0x71, 0xda, 0x4d, 0xc5, 0x36,
+       0x19, 0x99, 0xae, 0x85, 0x9b, 0xf0, 0xe6, 0xb4, 0x1c, 0xcd, 0x62, 0x7e,
+       0xe3, 0x7e, 0x2f, 0xe4, 0x9b, 0xa6, 0x25, 0x94, 0xa7, 0x72, 0xc3, 0x91,
+       0x26, 0x51, 0x0f, 0x7c, 0x08, 0x73, 0x8e, 0xca, 0x66, 0xaf, 0xdb, 0xdd,
+       0xa1, 0xa8, 0x0b, 0x2f, 0xab, 0xd1, 0x85, 0xed, 0x56, 0x17, 0x6e, 0xa2,
+       0x2e, 0x04, 0xdc, 0x77, 0xca, 0xe1, 0x22, 0xd7, 0x2f, 0x97, 0x6c, 0x82,
+       0xfe, 0xff, 0x81, 0xc7, 0xb3, 0x27, 0x3a, 0x6e, 0x96, 0x38, 0xac, 0x69,
+       0x99, 0x3a, 0x2d, 0xa5, 0xcf, 0x6a, 0x2c, 0xd2, 0xc6, 0x8e, 0x33, 0x16,
+       0x4a, 0xbd, 0xf7, 0xe3, 0xe0, 0x73, 0x75, 0xf4, 0xde, 0x64, 0xd1, 0xd8,
+       0x6f, 0x0d, 0xb0, 0x09, 0xe5, 0x44, 0x3b, 0xae, 0x8d, 0x3c, 0xab, 0xd0,
+       0xdb, 0xa3, 0x9a, 0xa5, 0xe1, 0x44, 0xab, 0x4c, 0x4c, 0x1b, 0x1b, 0x57,
+       0x9d, 0x00, 0xfe, 0x4f, 0x30, 0xdf, 0x55, 0x74, 0x7e, 0x7e, 0xb6, 0x04,
+       0x3b, 0x77, 0xf6, 0x4e, 0x93, 0xb7, 0x32, 0xdd, 0xa0, 0x7f, 0xd3, 0x06,
+       0xc9, 0xfb, 0x69, 0xe8, 0xbb, 0x98, 0x4c, 0xa0, 0xcf, 0xee, 0x6d, 0x8d,
+       0x98, 0x73, 0x1c, 0x6d, 0xe9, 0xf3, 0x31, 0x8e, 0xd6, 0x28, 0xd1, 0xd9,
+       0xb8, 0xce, 0xad, 0xe7, 0xd9, 0xd1, 0xcc, 0x60, 0x1b, 0xde, 0x31, 0x9f,
+       0xc1, 0xc5, 0x58, 0xa1, 0xec, 0x47, 0xbf, 0x47, 0xc5, 0xee, 0xf7, 0x0c,
+       0x69, 0xfd, 0x17, 0x39, 0xea, 0xda, 0x33, 0x74, 0x83, 0x58, 0xf7, 0x7a,
+       0x7a, 0xd1, 0x18, 0xb9, 0x19, 0xac, 0x9f, 0x3a, 0x15, 0xc5, 0xbd, 0x13,
+       0xf7, 0xb0, 0xbf, 0x50, 0x8f, 0x40, 0x37, 0xbe, 0xb3, 0x6f, 0xa3, 0x34,
+       0x03, 0xdf, 0xb3, 0x0a, 0xb8, 0x36, 0x39, 0x59, 0x39, 0xcd, 0x0b, 0x55,
+       0x7a, 0x78, 0xf2, 0x75, 0xf9, 0x81, 0x34, 0x41, 0x5a, 0xa0, 0x5c, 0x24,
+       0x6d, 0x50, 0x26, 0x3a, 0xfa, 0x6c, 0x03, 0xe9, 0xe1, 0x09, 0xdf, 0x8b,
+       0x70, 0xdf, 0xde, 0xc4, 0xe5, 0x49, 0x1b, 0xa4, 0xf9, 0xa4, 0x8e, 0xd7,
+       0xa7, 0xe5, 0x7b, 0x92, 0x6e, 0xeb, 0x86, 0x5d, 0xf6, 0x2f, 0xbb, 0xc6,
+       0xe6, 0xdc, 0xad, 0xa6, 0x39, 0xe8, 0x26, 0xe6, 0xd0, 0xf5, 0xca, 0xfb,
+       0x2a, 0x39, 0xe0, 0xe1, 0x5e, 0x28, 0xe5, 0x3b, 0x75, 0x5e, 0xe2, 0xee,
+       0xc2, 0x46, 0xb9, 0xc5, 0x8f, 0xd9, 0xb8, 0xfb, 0x41, 0xd0, 0xc1, 0xa2,
+       0x23, 0x27, 0xce, 0xe2, 0x3a, 0xe7, 0x70, 0xfd, 0xce, 0xfb, 0xe9, 0x94,
+       0x22, 0xb3, 0x7b, 0xd1, 0xc4, 0xa2, 0xf4, 0xb9, 0x13, 0xfa, 0x0c, 0xc8,
+       0x82, 0xd3, 0x74, 0xe2, 0xd0, 0x46, 0xe3, 0x4b, 0x03, 0x16, 0xaf, 0xd1,
+       0x1d, 0xa1, 0x2d, 0xe7, 0x07, 0x41, 0x96, 0x76, 0x83, 0x28, 0xed, 0x23,
+       0xc1, 0xe7, 0x43, 0x19, 0xe3, 0x13, 0x5b, 0x9d, 0xc6, 0x53, 0x2f, 0x5a,
+       0x5a, 0x91, 0x88, 0x1a, 0x7a, 0xc6, 0x69, 0x38, 0x71, 0x9c, 0x6b, 0xa6,
+       0xf3, 0xa4, 0x0d, 0x5d, 0x3d, 0xe7, 0x54, 0xe9, 0xea, 0x1b, 0xf6, 0xb7,
+       0x1a, 0x6a, 0x92, 0x74, 0xaa, 0x09, 0xf3, 0x1d, 0x2e, 0x84, 0x30, 0x7e,
+       0x1f, 0x70, 0x11, 0x1e, 0xd0, 0xed, 0xec, 0x9f, 0xe1, 0x5a, 0x02, 0x2c,
+       0xf7, 0x01, 0xee, 0xf3, 0x80, 0xf9, 0x02, 0x2e, 0xd5, 0x11, 0x91, 0x3f,
+       0x76, 0x22, 0xb3, 0xb5, 0xf0, 0x12, 0xc6, 0xd3, 0x16, 0xde, 0xd7, 0x82,
+       0xd5, 0x95, 0xc5, 0x81, 0x2e, 0xc0, 0x43, 0x38, 0x5f, 0x02, 0x8c, 0xb4,
+       0x5b, 0x9f, 0xc7, 0xb3, 0x0b, 0xf8, 0x5e, 0xb0, 0x30, 0x81, 0x1e, 0xa7,
+       0xff, 0x47, 0xf5, 0x77, 0x81, 0x76, 0xf4, 0x9f, 0xdb, 0xe7, 0xce, 0x55,
+       0x32, 0xa0, 0xc7, 0x21, 0x9e, 0xa7, 0x8a, 0x4b, 0xb4, 0x03, 0xc0, 0xf7,
+       0x3f, 0x94, 0xc8, 0xa9, 0x84, 0x1c, 0x2a, 0x70, 0x0f, 0xe8, 0x24, 0xf0,
+       0xa1, 0xcf, 0xa4, 0xa0, 0xce, 0x15, 0xb8, 0xa0, 0xec, 0x67, 0xb7, 0xe3,
+       0xea, 0xc5, 0xf5, 0x56, 0x5c, 0x20, 0x87, 0xd9, 0x13, 0xb8, 0xfa, 0xd0,
+       0xb7, 0x8a, 0x37, 0x09, 0x73, 0xa9, 0xbe, 0x8d, 0x36, 0xda, 0xb6, 0xcc,
+       0xa9, 0xa1, 0x01, 0xe0, 0x6f, 0x00, 0xb0, 0x25, 0x70, 0x31, 0xff, 0xf8,
+       0x87, 0x8e, 0x9c, 0x7a, 0x19, 0x17, 0x18, 0xec, 0x14, 0x08, 0xf3, 0xd4,
+       0x20, 0x2e, 0x28, 0xb1, 0x53, 0x69, 0x5c, 0x23, 0xb8, 0xfe, 0xd2, 0x31,
+       0x3c, 0xd7, 0x09, 0x7c, 0x85, 0x3c, 0x02, 0x9c, 0xaf, 0xe0, 0xb9, 0xaf,
+       0x3b, 0x6f, 0x9c, 0xe7, 0x7e, 0xe2, 0x18, 0x9e, 0x7b, 0xc5, 0xa9, 0xf2,
+       0xdc, 0x59, 0x47, 0x3d, 0xfc, 0x8c, 0x13, 0x79, 0x98, 0xbe, 0xc4, 0x59,
+       0xc7, 0xf0, 0x7f, 0x44, 0x86, 0xf7, 0x82, 0x96, 0x1e, 0x5e, 0xc0, 0x45,
+       0xba, 0x7a, 0x16, 0xe5, 0x2f, 0xac, 0x1a, 0xf7, 0xf9, 0x37, 0x31, 0xee,
+       0xab, 0x76, 0x5c, 0x51, 0xd5, 0x71, 0x2f, 0xa0, 0xef, 0x97, 0xec, 0xb8,
+       0x17, 0x6a, 0xc6, 0x05, 0xad, 0x3c, 0xbc, 0x84, 0x8b, 0x74, 0xf1, 0x22,
+       0xca, 0x43, 0x99, 0x80, 0x85, 0x6e, 0x6e, 0xd0, 0x67, 0x9d, 0xe2, 0x5e,
+       0xc3, 0xb2, 0x6e, 0x4c, 0xd7, 0xe8, 0x87, 0x37, 0xa2, 0x1f, 0x27, 0x8b,
+       0xb4, 0x11, 0x17, 0x6a, 0xe4, 0x02, 0x7d, 0xa3, 0x40, 0x8e, 0x69, 0x3f,
+       0x88, 0x3e, 0x11, 0xfd, 0xa3, 0xd5, 0xb6, 0xd5, 0x27, 0x75, 0xee, 0xd8,
+       0xaf, 0x15, 0x3a, 0xe5, 0xd3, 0x05, 0xda, 0x84, 0xa4, 0x97, 0x20, 0x98,
+       0xd8, 0x41, 0xfb, 0x34, 0x17, 0x5c, 0xe2, 0x91, 0x4e, 0x3c, 0xf7, 0x33,
+       0x6b, 0x75, 0x46, 0x69, 0x18, 0xbe, 0x7b, 0xe6, 0xe8, 0xaf, 0x40, 0x67,
+       0x34, 0x00, 0x6e, 0xd2, 0x5b, 0x87, 0xdc, 0x58, 0x52, 0x53, 0x9b, 0x25,
+       0x21, 0x37, 0x15, 0x1a, 0x61, 0xf7, 0x30, 0xaf, 0xaa, 0x59, 0xba, 0x77,
+       0xc4, 0x4c, 0xde, 0xb7, 0x1b, 0xc7, 0x6f, 0xd7, 0xe4, 0xa1, 0xc7, 0x13,
+       0x78, 0xff, 0x7b, 0x2e, 0xe5, 0x60, 0xdc, 0xbb, 0x56, 0xe7, 0xf4, 0x74,
+       0xed, 0xa0, 0xdd, 0x72, 0xbd, 0xd6, 0xe1, 0xd1, 0x35, 0x76, 0x92, 0xea,
+       0x70, 0xa5, 0x6a, 0xa3, 0x8d, 0x17, 0x52, 0x49, 0xc2, 0xf5, 0x90, 0x70,
+       0xff, 0xeb, 0x1e, 0xc9, 0xfb, 0xad, 0xf0, 0x0b, 0x18, 0x3b, 0x4f, 0xf5,
+       0xd2, 0x36, 0x9a, 0x9d, 0x76, 0x6d, 0x5e, 0xf4, 0x46, 0x79, 0x4e, 0x8f,
+       0xd3, 0xa8, 0x61, 0x34, 0x67, 0x25, 0xb8, 0x8f, 0x10, 0xd3, 0xe7, 0x73,
+       0x66, 0xcb, 0x2d, 0x5a, 0xef, 0xcc, 0x96, 0x99, 0x87, 0x0f, 0x7f, 0xaa,
+       0xcc, 0xbc, 0x7b, 0x5f, 0xdc, 0x77, 0xc2, 0xcf, 0x2d, 0x6f, 0x91, 0xf1,
+       0xe9, 0x75, 0xd2, 0xe8, 0xa9, 0xf8, 0x66, 0xc8, 0x47, 0xb6, 0xe9, 0xda,
+       0x01, 0xff, 0x70, 0x66, 0xab, 0x3c, 0x39, 0xc3, 0xbe, 0x3b, 0x64, 0x6e,
+       0x5e, 0x1c, 0xf7, 0x9d, 0xeb, 0x51, 0x07, 0x72, 0x7d, 0x07, 0xcb, 0x92,
+       0xb8, 0x8b, 0x72, 0xdf, 0x19, 0x95, 0x73, 0x03, 0x7c, 0x66, 0xee, 0xbf,
+       0x44, 0xd9, 0xdf, 0xb9, 0x81, 0x4e, 0x79, 0x7c, 0x1e, 0x34, 0x01, 0xb9,
+       0x3f, 0x72, 0x82, 0x30, 0x89, 0xec, 0x9a, 0x65, 0x2c, 0xbd, 0xdb, 0x65,
+       0xdc, 0x94, 0xfb, 0x34, 0xb7, 0x0c, 0x70, 0x2c, 0xe8, 0x25, 0xe8, 0xb8,
+       0xae, 0x1d, 0x46, 0x16, 0xa4, 0x67, 0x1b, 0x50, 0xce, 0x7e, 0xe1, 0x3f,
+       0xee, 0x65, 0x3f, 0x61, 0x5b, 0x85, 0x39, 0x35, 0x6a, 0x7a, 0x59, 0x5a,
+       0xa5, 0x3f, 0xce, 0xfc, 0x4c, 0xf6, 0x37, 0xfb, 0xe8, 0xd5, 0x7b, 0x21,
+       0xdc, 0x53, 0x36, 0xb6, 0x15, 0xd7, 0x44, 0xef, 0x29, 0xc0, 0xae, 0xba,
+       0x42, 0xdb, 0x17, 0x73, 0x15, 0xae, 0x20, 0x63, 0x51, 0xe1, 0x1a, 0x25,
+       0xe4, 0xd1, 0xe2, 0xf2, 0x3a, 0x6d, 0x69, 0x58, 0xb9, 0x4e, 0xa4, 0x15,
+       0x7f, 0xcc, 0xda, 0x1e, 0x8b, 0x92, 0x83, 0x5d, 0xd6, 0xab, 0xd7, 0x6c,
+       0x11, 0xb6, 0xac, 0x5d, 0x33, 0x6d, 0xcf, 0xe6, 0xc3, 0x35, 0x1b, 0x85,
+       0xc6, 0x29, 0xab, 0x4d, 0x5c, 0x33, 0x97, 0xf1, 0x6e, 0xe0, 0x3d, 0x87,
+       0x75, 0xca, 0x61, 0x8d, 0x72, 0xe5, 0x0e, 0x99, 0x3d, 0xa6, 0x3a, 0x1b,
+       0x44, 0x92, 0xe3, 0x5e, 0x87, 0x4c, 0xce, 0x33, 0x96, 0xb0, 0x05, 0x36,
+       0xd8, 0x56, 0x5c, 0x9d, 0x78, 0x66, 0x3b, 0xf0, 0x54, 0x59, 0xa1, 0x6d,
+       0xd3, 0x1a, 0x3b, 0xeb, 0x71, 0x8c, 0xcd, 0x1c, 0xe1, 0x27, 0x80, 0x87,
+       0x2a, 0xef, 0x4c, 0xd5, 0xc4, 0x9f, 0x38, 0x57, 0xad, 0x43, 0x31, 0xdf,
+       0xb8, 0x5e, 0x4f, 0x1d, 0x87, 0x2a, 0x36, 0xbe, 0x19, 0x7b, 0x2a, 0x41,
+       0x7b, 0x2a, 0x5b, 0x72, 0xcd, 0xf9, 0x80, 0x51, 0xf8, 0x4e, 0x5e, 0xef,
+       0x26, 0xd2, 0xfa, 0xd8, 0x0c, 0xe1, 0x8a, 0x85, 0x70, 0xad, 0x58, 0x33,
+       0x9e, 0xe7, 0x5a, 0x1b, 0xe7, 0x98, 0x5a, 0xce, 0x5f, 0x34, 0xb1, 0x7d,
+       0xc6, 0x51, 0x3a, 0xeb, 0xc0, 0x74, 0xa7, 0xb6, 0x61, 0x45, 0x8d, 0xc9,
+       0x81, 0x22, 0xcf, 0x82, 0x31, 0x9e, 0x78, 0x23, 0xe3, 0x49, 0xbd, 0xb3,
+       0xf2, 0x5e, 0x8c, 0xcd, 0x5c, 0x1d, 0x65, 0xe3, 0x37, 0x1b, 0x6c, 0x8e,
+       0x48, 0x6d, 0x0c, 0xc7, 0xe4, 0xf2, 0xac, 0xcc, 0x8b, 0x4e, 0x8d, 0x2e,
+       0x61, 0x9d, 0x7f, 0x5d, 0xef, 0x0d, 0x4a, 0x29, 0x02, 0xed, 0x37, 0x3e,
+       0x90, 0x1a, 0x34, 0xe7, 0x60, 0x92, 0xb2, 0xb3, 0x68, 0xe6, 0x7f, 0x5e,
+       0xe7, 0xf4, 0x98, 0xdc, 0x45, 0x93, 0xef, 0x73, 0x8f, 0x9c, 0x87, 0x0e,
+       0xaf, 0xae, 0x6d, 0x93, 0x4c, 0x02, 0x17, 0x59, 0xbd, 0x2f, 0x91, 0x94,
+       0xec, 0xc0, 0xc7, 0x37, 0xf1, 0x9c, 0x44, 0x0c, 0xeb, 0x93, 0x9f, 0xe1,
+       0xd9, 0x49, 0xf6, 0x7b, 0xb1, 0xbe, 0x28, 0x66, 0x99, 0x87, 0x0f, 0x59,
+       0xf9, 0xb6, 0xbe, 0x44, 0xb3, 0x7e, 0xbf, 0xce, 0xe6, 0x5b, 0x3b, 0x22,
+       0x37, 0x06, 0xf2, 0x87, 0x10, 0x9f, 0x8f, 0xd9, 0x39, 0x25, 0x75, 0xcc,
+       0x4a, 0x82, 0x73, 0x7e, 0xc2, 0xc6, 0x2c, 0x39, 0x97, 0x1b, 0x2c, 0x7d,
+       0x1b, 0xfb, 0xa7, 0x6a, 0x43, 0x9b, 0x7d, 0xbf, 0x27, 0xb5, 0x2c, 0xec,
+       0xb7, 0xb6, 0xb3, 0x8e, 0xf3, 0x1c, 0x17, 0x9d, 0x13, 0x10, 0xfa, 0x46,
+       0x3d, 0x35, 0x7e, 0x81, 0xf1, 0xe5, 0xf2, 0xd3, 0xf5, 0x64, 0x54, 0xd5,
+       0x27, 0xa4, 0x2f, 0x37, 0xb1, 0x8d, 0xdf, 0x2d, 0x08, 0x7d, 0xb9, 0x7e,
+       0xeb, 0xcb, 0xb5, 0x6a, 0x5f, 0xce, 0xc4, 0x1e, 0x5a, 0x97, 0x7d, 0xb9,
+       0xfc, 0x74, 0x0e, 0xb4, 0x12, 0x7e, 0x67, 0xc1, 0xd8, 0x42, 0x93, 0x05,
+       0x9e, 0x79, 0x69, 0x94, 0xec, 0xa8, 0x82, 0xdf, 0x60, 0x7c, 0x2c, 0xc6,
+       0x2a, 0x94, 0xfa, 0x96, 0xf5, 0x2f, 0x3a, 0x25, 0xdd, 0xbe, 0x0e, 0xf3,
+       0xbe, 0x53, 0xaf, 0xf9, 0x5c, 0xc1, 0xec, 0x7d, 0x66, 0xf7, 0x32, 0x26,
+       0xc4, 0x73, 0x4d, 0x9a, 0xbf, 0x92, 0xc3, 0x91, 0x5e, 0x63, 0xcf, 0x7a,
+       0xdf, 0x04, 0xde, 0x4f, 0x02, 0xe7, 0x31, 0x3b, 0x6e, 0x12, 0x30, 0x1d,
+       0xc0, 0xda, 0x5c, 0x6b, 0x65, 0x32, 0xc7, 0xde, 0xd3, 0xc4, 0xd8, 0xc0,
+       0x7c, 0x21, 0x8c, 0x11, 0x46, 0xec, 0x99, 0x4a, 0x2f, 0xd2, 0xe8, 0xad,
+       0xab, 0x6b, 0xab, 0x9e, 0x7e, 0x5d, 0xdd, 0x44, 0x5a, 0xba, 0x53, 0xe7,
+       0xb9, 0xac, 0x1f, 0x48, 0xed, 0xd1, 0x39, 0xf2, 0x3a, 0xc6, 0x98, 0x13,
+       0xe6, 0x94, 0x7d, 0x57, 0xde, 0xa1, 0x65, 0xfe, 0x01, 0x9f, 0xfa, 0x6b,
+       0x87, 0xfe, 0xdd, 0x38, 0x14, 0x04, 0xe7, 0x06, 0xee, 0x86, 0xad, 0xe2,
+       0xb9, 0xdf, 0x97, 0xee, 0xc4, 0xb0, 0xb6, 0x9d, 0xb0, 0x46, 0x7b, 0x9b,
+       0x65, 0x9d, 0x77, 0xb3, 0xcd, 0x99, 0xc9, 0x41, 0x6e, 0xa6, 0x60, 0x33,
+       0xf1, 0x4c, 0x70, 0x8f, 0x7d, 0x97, 0x0b, 0x9a, 0x41, 0x47, 0x1f, 0x13,
+       0x23, 0x63, 0xb2, 0x55, 0x19, 0xc3, 0x5c, 0x83, 0x34, 0x09, 0x39, 0x7a,
+       0x44, 0x52, 0xfc, 0xee, 0x07, 0xc7, 0xce, 0xcb, 0xa5, 0xd0, 0xcb, 0x6c,
+       0xa7, 0xbf, 0xd9, 0x83, 0x67, 0xee, 0xe1, 0x78, 0xee, 0x41, 0xe8, 0x96,
+       0xeb, 0xd7, 0xea, 0x96, 0x04, 0xfd, 0xfa, 0x6c, 0x89, 0xbe, 0xe1, 0x7a,
+       0xb4, 0xe9, 0x90, 0x8f, 0x4f, 0x77, 0xb7, 0x91, 0xb7, 0xc6, 0x20, 0xd7,
+       0xd5, 0xfd, 0xe1, 0x59, 0x20, 0x96, 0xf1, 0x3d, 0xfb, 0x6d, 0x92, 0xe4,
+       0xfb, 0x5d, 0xf9, 0x7c, 0x25, 0x95, 0x5c, 0x82, 0x6e, 0x1a, 0x73, 0x7e,
+       0xf1, 0x72, 0x13, 0x53, 0x7d, 0x7b, 0x9b, 0x39, 0x3b, 0xd0, 0x4c, 0x9b,
+       0xdd, 0xc6, 0x59, 0x6b, 0x69, 0x76, 0xc9, 0xca, 0xe3, 0x20, 0x68, 0x1e,
+       0xd0, 0x32, 0x78, 0x0f, 0x65, 0xf0, 0x01, 0xbf, 0xc7, 0xd0, 0xbe, 0xf6,
+       0x99, 0x02, 0xac, 0x23, 0xf0, 0x30, 0x10, 0x65, 0x7e, 0x9e, 0xe5, 0x4f,
+       0x2f, 0xbd, 0x68, 0xe5, 0x92, 0x72, 0xd6, 0xf2, 0xa5, 0xba, 0x2a, 0xb6,
+       0x42, 0xe6, 0x1e, 0x9a, 0xa6, 0x3e, 0xf6, 0x17, 0xbe, 0x0b, 0x39, 0x95,
+       0xd5, 0x78, 0xe8, 0x90, 0xfb, 0xa6, 0x25, 0x7d, 0x1e, 0xba, 0x2a, 0x3f,
+       0xbf, 0x92, 0x37, 0xd7, 0xf6, 0xc7, 0xb9, 0x7e, 0xb8, 0xcd, 0xf8, 0xb6,
+       0x2b, 0xe7, 0xba, 0x80, 0xb9, 0xa6, 0xf5, 0x5c, 0xb9, 0x6f, 0xf3, 0x31,
+       0x3b, 0xd7, 0xf5, 0xe1, 0x5c, 0x07, 0x57, 0xce, 0x35, 0xf4, 0xed, 0x43,
+       0xb9, 0x9b, 0xd4, 0xf9, 0xf2, 0x3a, 0x4f, 0x7b, 0x7a, 0xbd, 0x0c, 0x97,
+       0x5a, 0xad, 0xbc, 0x74, 0xa1, 0x7b, 0x98, 0xc3, 0xbe, 0x70, 0xaf, 0x2b,
+       0x16, 0x67, 0x8a, 0x78, 0xa0, 0xac, 0x6d, 0xd3, 0x67, 0x6c, 0x66, 0xe1,
+       0x5f, 0xdd, 0x5a, 0x60, 0xdd, 0xf0, 0xfd, 0xc5, 0x62, 0xc7, 0xa1, 0x4f,
+       0x4d, 0xbf, 0xa9, 0x77, 0x4d, 0x4c, 0xc1, 0xc4, 0x87, 0x19, 0x17, 0x36,
+       0x67, 0x7f, 0x99, 0x8b, 0x78, 0x07, 0x78, 0xea, 0x53, 0x85, 0xd4, 0x60,
+       0x26, 0x42, 0x39, 0x7a, 0x5c, 0x0e, 0x55, 0x46, 0xa4, 0x4b, 0x9f, 0xff,
+       0x7c, 0xdd, 0xd8, 0x71, 0xba, 0x36, 0x76, 0xcc, 0x74, 0x02, 0xc6, 0x8e,
+       0xf7, 0xfc, 0x0c, 0xb1, 0x63, 0x71, 0x4c, 0xec, 0xb8, 0x9e, 0x7f, 0x35,
+       0x55, 0x3c, 0x8e, 0x79, 0x35, 0x43, 0x96, 0x2c, 0x3a, 0xd9, 0xf9, 0x16,
+       0xdc, 0xcf, 0xe2, 0x1e, 0xc3, 0xfd, 0x3c, 0xee, 0x2e, 0xee, 0x17, 0x70,
+       0x8f, 0xcb, 0xd4, 0xb2, 0xce, 0x38, 0x0e, 0xb9, 0x41, 0x5d, 0xc6, 0xb6,
+       0xc6, 0x1f, 0x98, 0x2b, 0xb7, 0xf3, 0x7b, 0x2d, 0xce, 0xec, 0x3c, 0xe7,
+       0xd0, 0x2a, 0x93, 0xd3, 0x94, 0xd9, 0x6d, 0x52, 0x9a, 0x0e, 0x6d, 0xdb,
+       0x9f, 0xef, 0xe0, 0x9e, 0xc1, 0x98, 0x84, 0xb6, 0xeb, 0x3d, 0x1d, 0x66,
+       0xaf, 0xf1, 0x3b, 0x58, 0xe3, 0x8d, 0x58, 0x83, 0x93, 0x72, 0x7e, 0x66,
+       0xe3, 0x0a, 0x1b, 0x36, 0x69, 0x63, 0x82, 0x33, 0x56, 0xf7, 0xd6, 0x97,
+       0x11, 0xb5, 0xeb, 0x9f, 0xb0, 0x67, 0xcb, 0xc2, 0x1c, 0xa1, 0xa4, 0x5e,
+       0x9f, 0xd1, 0xca, 0x71, 0x8c, 0x37, 0x28, 0xe9, 0x19, 0xce, 0x73, 0xf9,
+       0x9b, 0x11, 0x90, 0x87, 0x27, 0xa0, 0x57, 0x57, 0xd0, 0x25, 0xe8, 0x96,
+       0x73, 0x73, 0x40, 0xbb, 0x8f, 0xca, 0x6c, 0x89, 0xf0, 0xf5, 0x24, 0x22,
+       0xfa, 0xac, 0x19, 0x9e, 0x67, 0x4c, 0x8e, 0xfb, 0x70, 0x25, 0x3c, 0x67,
+       0xb6, 0x89, 0x67, 0x07, 0x57, 0x9d, 0x35, 0xb3, 0xfa, 0x59, 0xdb, 0x0e,
+       0x3c, 0x73, 0x16, 0xce, 0xa1, 0x1e, 0x3d, 0x05, 0x32, 0xa9, 0xf3, 0xce,
+       0x36, 0xcb, 0x63, 0x0f, 0x2e, 0xe7, 0xbc, 0xb6, 0xc1, 0x46, 0xe9, 0x84,
+       0x89, 0x3c, 0x1a, 0x1d, 0xea, 0x81, 0x8f, 0xc7, 0x3c, 0x99, 0x9e, 0xc4,
+       0x6d, 0x3a, 0x17, 0xb9, 0x7a, 0xee, 0xaf, 0x9a, 0x8f, 0x1c, 0x9e, 0xb3,
+       0x4a, 0xe8, 0xef, 0x5a, 0xec, 0xd4, 0xe5, 0x71, 0xcc, 0x87, 0xfb, 0x7e,
+       0x1a, 0x0f, 0x09, 0x7e, 0xa7, 0xeb, 0x29, 0xe0, 0x60, 0xb2, 0xf2, 0x6d,
+       0xd0, 0xbb, 0x63, 0xcf, 0x9c, 0x91, 0xc6, 0x06, 0x64, 0xa2, 0x9c, 0x70,
+       0x26, 0xca, 0x03, 0xce, 0xbe, 0xb2, 0x7d, 0x37, 0xb0, 0x67, 0xb3, 0x34,
+       0xe3, 0xf7, 0x4c, 0x97, 0x33, 0x06, 0x7c, 0xe5, 0x8b, 0xdd, 0x4e, 0x5a,
+       0xdf, 0x3d, 0x7b, 0x87, 0x1c, 0xc0, 0x5a, 0x0d, 0xcf, 0xc4, 0xb5, 0x9c,
+       0xaf, 0x7e, 0x5b, 0x2a, 0x5c, 0x57, 0x7e, 0x13, 0x89, 0x7c, 0x7c, 0x5c,
+       0x7f, 0xe7, 0xc8, 0xd8, 0x0e, 0x27, 0xd1, 0xdf, 0x71, 0x1b, 0x13, 0xef,
+       0x73, 0xb2, 0xba, 0x1f, 0xb3, 0x1e, 0xf9, 0xe2, 0x09, 0xdc, 0x57, 0x9f,
+       0x79, 0x0e, 0xf5, 0x8c, 0x85, 0xbb, 0x10, 0xdc, 0x63, 0xe4, 0xd5, 0x71,
+       0x99, 0xaa, 0x30, 0x7f, 0xc4, 0xd1, 0x7c, 0x34, 0x59, 0x3e, 0x00, 0x9d,
+       0xb4, 0xf2, 0xcc, 0xdf, 0xce, 0xea, 0x3a, 0x24, 0x67, 0x84, 0xb0, 0x70,
+       0x0d, 0x56, 0x9e, 0x87, 0xbf, 0xf8, 0xbf, 0x70, 0x5f, 0xd1, 0xc8, 0x50,
+       0x0b, 0x47, 0x9a, 0xf2, 0xce, 0xc8, 0x95, 0x69, 0x39, 0x08, 0x78, 0x0e,
+       0xe3, 0x52, 0xf7, 0xf3, 0x3b, 0x2c, 0xf3, 0x92, 0x9f, 0xbb, 0x4f, 0xd4,
+       0x43, 0xe7, 0x9d, 0xe8, 0x43, 0x07, 0x25, 0xf2, 0xd0, 0xa2, 0xd3, 0xf0,
+       0x50, 0xb7, 0xf6, 0xcb, 0x77, 0xfb, 0xdd, 0x89, 0x7d, 0x72, 0x52, 0xa2,
+       0xf7, 0x2b, 0x7d, 0xfe, 0x2b, 0xef, 0x32, 0xc6, 0x77, 0x52, 0x22, 0xf7,
+       0xc7, 0xec, 0xd9, 0x51, 0x13, 0xd7, 0x5b, 0xd2, 0x7c, 0xff, 0x9b, 0x71,
+       0xe2, 0x6c, 0x49, 0x8e, 0x6b, 0xde, 0x19, 0x86, 0x9e, 0xc8, 0x94, 0x92,
+       0xcb, 0x75, 0x4c, 0xbe, 0xe7, 0xf3, 0x9b, 0x0d, 0xbf, 0xb0, 0x4e, 0x8f,
+       0xc3, 0xef, 0x38, 0x18, 0x9d, 0x91, 0xb9, 0x2c, 0xcc, 0xfd, 0x34, 0x6b,
+       0xca, 0xf7, 0x67, 0xb1, 0x86, 0x3d, 0x58, 0x2f, 0x8e, 0xe7, 0xe8, 0xfd,
+       0x5c, 0x9e, 0x9d, 0x75, 0xa5, 0x2f, 0xd1, 0xb4, 0x6c, 0x07, 0xb1, 0xee,
+       0x7d, 0xd2, 0x04, 0xb8, 0xd5, 0x43, 0x79, 0x63, 0xd7, 0x09, 0xe9, 0x54,
+       0x20, 0xb9, 0x49, 0xb3, 0x3d, 0x83, 0xbb, 0xf5, 0x1a, 0xde, 0x6b, 0x69,
+       0x66, 0x9d, 0xb1, 0x1f, 0xf1, 0x6c, 0xe8, 0x22, 0x2f, 0xbb, 0xa6, 0x7f,
+       0x08, 0x3d, 0xcf, 0x7d, 0x17, 0x6d, 0x2f, 0xd6, 0xb1, 0x05, 0xc9, 0x4b,
+       0xcf, 0x58, 0xbf, 0x32, 0x08, 0xa6, 0x7d, 0x1f, 0x78, 0xac, 0xe7, 0x4b,
+       0x6e, 0x71, 0xe6, 0x4a, 0x5b, 0x9d, 0xd9, 0x52, 0x20, 0x13, 0x3e, 0xbf,
+       0xe3, 0xc1, 0x1c, 0x00, 0xda, 0x5b, 0x2c, 0xeb, 0x86, 0x6e, 0xfd, 0xeb,
+       0xcd, 0x3c, 0x8f, 0x74, 0x93, 0xf7, 0xa2, 0x98, 0x7a, 0xc4, 0x31, 0x7d,
+       0xe4, 0xee, 0xe3, 0x59, 0xe1, 0xf7, 0x34, 0xfa, 0x12, 0x71, 0xfd, 0x5d,
+       0x8f, 0xcf, 0xa1, 0x1d, 0xc6, 0x28, 0x72, 0xdc, 0x67, 0x9d, 0x59, 0xc8,
+       0xb3, 0xb9, 0x69, 0x9e, 0xe1, 0x67, 0x3e, 0x6d, 0xa4, 0x53, 0xc9, 0x15,
+       0xee, 0xa4, 0xfd, 0x06, 0x5c, 0x0e, 0x2e, 0x50, 0x44, 0x97, 0xf5, 0xb9,
+       0xe3, 0xcb, 0xdf, 0x85, 0x0b, 0xcb, 0xc2, 0xef, 0xc3, 0x29, 0x9d, 0x3b,
+       0x0d, 0x5f, 0xf6, 0xb1, 0x31, 0xf9, 0x89, 0x33, 0x5f, 0x78, 0xc5, 0x79,
+       0xb4, 0x90, 0xbe, 0xea, 0x12, 0xd0, 0xc7, 0x39, 0xbf, 0x97, 0xf2, 0x0b,
+       0x36, 0x5f, 0x41, 0x72, 0x95, 0x09, 0x99, 0xe9, 0xe8, 0x76, 0xef, 0xd7,
+       0x6b, 0x33, 0x03, 0x9c, 0x7d, 0x1b, 0xeb, 0xf7, 0xc9, 0x38, 0xf5, 0xdb,
+       0x78, 0x41, 0x81, 0x97, 0xd5, 0xcf, 0xe3, 0x82, 0x6d, 0xdb, 0xa8, 0x6d,
+       0x94, 0x7d, 0x3e, 0xeb, 0x6d, 0x75, 0x86, 0x4b, 0x5b, 0xb0, 0x8e, 0x7b,
+       0xa1, 0x3f, 0x1d, 0xd8, 0x69, 0xa0, 0x6d, 0x94, 0x4d, 0x02, 0x07, 0xe3,
+       0xbe, 0x91, 0xe7, 0xc3, 0x92, 0xd3, 0x3e, 0x9e, 0xb9, 0xa7, 0x95, 0x89,
+       0x99, 0x05, 0xc1, 0x1c, 0xec, 0x83, 0x6c, 0x7f, 0x09, 0xbc, 0xf0, 0x08,
+       0xae, 0xb7, 0xdb, 0x3d, 0xed, 0x17, 0x2e, 0xb2, 0xa7, 0xed, 0xca, 0xc9,
+       0x8a, 0x3e, 0xd7, 0xae, 0xf3, 0xab, 0x92, 0xea, 0xbf, 0x5f, 0xa2, 0xd7,
+       0x4a, 0xf5, 0xe8, 0x9c, 0xb4, 0xb4, 0x7c, 0x38, 0x6e, 0xf4, 0x30, 0x61,
+       0x4a, 0x02, 0x9e, 0xad, 0xc0, 0x05, 0xe1, 0x31, 0x6d, 0x44, 0x6d, 0xba,
+       0x94, 0xfa, 0x70, 0x49, 0x3e, 0x12, 0x0f, 0xcf, 0x14, 0xa0, 0x1f, 0xc8,
+       0xb8, 0x8f, 0x5d, 0x6a, 0xf4, 0xe4, 0xe6, 0x3a, 0xfd, 0x84, 0x73, 0x73,
+       0xec, 0xdc, 0x48, 0xb7, 0x7f, 0x96, 0xa0, 0x4f, 0xb1, 0x24, 0x4d, 0xab,
+       0xea, 0x33, 0xa6, 0xbf, 0xe1, 0x72, 0x73, 0x46, 0x81, 0x75, 0x5d, 0xd8,
+       0xa6, 0xb4, 0x73, 0x89, 0x47, 0xbd, 0x6e, 0x05, 0x25, 0x3c, 0x67, 0x00,
+       0x6e, 0xae, 0x5c, 0xe1, 0xbe, 0x43, 0x91, 0x0e, 0x43, 0x5c, 0x7f, 0x5b,
+       0xf3, 0xc9, 0x78, 0x81, 0xb1, 0x95, 0x47, 0x83, 0xf4, 0x28, 0x79, 0x8c,
+       0x7d, 0xf0, 0x7d, 0x41, 0xc7, 0x73, 0xf7, 0xfa, 0x8c, 0x15, 0x75, 0x1f,
+       0xbf, 0x43, 0x85, 0x72, 0x0a, 0xfa, 0xb7, 0xb8, 0xe8, 0xf0, 0x1b, 0x78,
+       0x37, 0x0a, 0xee, 0xf3, 0x8b, 0xce, 0x77, 0xa7, 0x9f, 0xc5, 0x73, 0x83,
+       0xfd, 0xee, 0x9d, 0xd1, 0x53, 0x22, 0xc5, 0x70, 0xbe, 0x89, 0x1c, 0xd6,
+       0xfe, 0x02, 0xd6, 0xbe, 0xfe, 0x77, 0xee, 0xf0, 0xae, 0x8c, 0x77, 0xe5,
+       0x0f, 0x07, 0xe9, 0x36, 0xd2, 0x22, 0xe9, 0xef, 0xb5, 0xfc, 0xe6, 0x41,
+       0xcd, 0x17, 0x93, 0xc5, 0xc7, 0xc1, 0x17, 0x69, 0xee, 0x37, 0x07, 0x0f,
+       0xfb, 0x37, 0x80, 0x2f, 0xf6, 0xc8, 0xef, 0xc3, 0x2e, 0xf8, 0xdd, 0xca,
+       0x10, 0xf8, 0x63, 0x10, 0xfc, 0x32, 0x00, 0x1e, 0xf1, 0xb5, 0x8d, 0xfc,
+       0x04, 0xf4, 0x1f, 0xf4, 0x9a, 0xb3, 0xaf, 0xd4, 0xe5, 0x64, 0x4b, 0x9e,
+       0x33, 0x51, 0xe2, 0xf7, 0x5a, 0xd4, 0x5b, 0x1b, 0x24, 0x9a, 0x98, 0x13,
+       0xf2, 0x42, 0x37, 0x73, 0x1c, 0xdb, 0x81, 0xab, 0x53, 0xc4, 0xd5, 0x5c,
+       0xa5, 0xcf, 0xbd, 0x04, 0x3c, 0xd1, 0xae, 0x79, 0xa2, 0xd5, 0x49, 0xbb,
+       0x37, 0x58, 0x9e, 0x78, 0x11, 0x3c, 0x71, 0x7e, 0x0d, 0x4f, 0x3c, 0x6d,
+       0xe9, 0x7f, 0xa1, 0x86, 0x27, 0xe6, 0x6c, 0xd9, 0xcc, 0x45, 0x78, 0xe2,
+       0x52, 0x2f, 0xf5, 0xa5, 0x31, 0x79, 0x15, 0x3c, 0x21, 0x8a, 0x3c, 0x71,
+       0xa9, 0xe6, 0x09, 0xc6, 0x8e, 0xc8, 0x17, 0x9d, 0x90, 0x23, 0xe4, 0x8b,
+       0xb3, 0xb2, 0x04, 0xbe, 0x78, 0x5e, 0x71, 0xec, 0x19, 0xda, 0x0a, 0x25,
+       0xfa, 0x64, 0x27, 0x8a, 0x5d, 0xe0, 0x77, 0x25, 0xff, 0x65, 0x3a, 0x08,
+       0x16, 0xe1, 0xa7, 0x3f, 0x08, 0x7b, 0x3e, 0xaa, 0xbf, 0xa9, 0xb8, 0x00,
+       0xba, 0x0f, 0xe9, 0x7d, 0xc2, 0x01, 0xbd, 0x1f, 0x9e, 0xc5, 0x1c, 0x26,
+       0xd4, 0x7f, 0x86, 0x2f, 0xec, 0x62, 0x5d, 0x69, 0xe7, 0x1f, 0xd3, 0x3c,
+       0xd4, 0x00, 0x7d, 0xf0, 0xe8, 0x00, 0x63, 0x4d, 0x9e, 0xbb, 0x4f, 0x75,
+       0xe7, 0x46, 0x00, 0x73, 0x44, 0xdd, 0x2f, 0x8c, 0x73, 0xb4, 0xad, 0xb2,
+       0xf3, 0x29, 0x23, 0x46, 0x21, 0xeb, 0xcc, 0xbb, 0x5c, 0xd0, 0x04, 0x9b,
+       0xb4, 0x49, 0x19, 0x1b, 0x5d, 0xed, 0x48, 0xb9, 0x1f, 0x84, 0x00, 0x6d,
+       0x84, 0xbd, 0xb0, 0x0b, 0xab, 0x3d, 0x52, 0xa8, 0xb5, 0xf1, 0xff, 0x03,
+       0x6c, 0x7c, 0xb6, 0x91, 0xa8, 0xb1, 0xf1, 0x7f, 0xcd, 0xf2, 0x1a, 0x7f,
+       0xbb, 0xda, 0xde, 0x3f, 0x00, 0xf8, 0x76, 0x2f, 0xdb, 0xfb, 0xec, 0x83,
+       0x76, 0x87, 0xc8, 0xf5, 0xb0, 0xf9, 0xde, 0x0d, 0x1e, 0xbc, 0x01, 0xbe,
+       0xd4, 0x7b, 0x0a, 0xae, 0xec, 0x29, 0xb4, 0xc3, 0xe7, 0xee, 0x94, 0xf7,
+       0x4e, 0x6f, 0x95, 0x9d, 0x25, 0xff, 0x12, 0x69, 0xee, 0x80, 0x8d, 0x5a,
+       0x00, 0x9c, 0x11, 0x2b, 0xb7, 0xcf, 0x02, 0x6f, 0xdd, 0xc9, 0x9f, 0xa8,
+       0x17, 0xad, 0x5d, 0xc4, 0xb3, 0x8e, 0xf5, 0xfa, 0x89, 0xa3, 0x3d, 0x63,
+       0x29, 0x1d, 0x72, 0xea, 0x18, 0xbd, 0xaf, 0x24, 0xec, 0x72, 0x1f, 0x36,
+       0xc9, 0x16, 0xf4, 0xc7, 0x78, 0xf2, 0x46, 0x79, 0xfa, 0xaa, 0xe8, 0x5d,
+       0x59, 0xcd, 0x87, 0x9d, 0x4e, 0x66, 0x1a, 0x3e, 0xc0, 0xde, 0x18, 0xe6,
+       0xa0, 0xda, 0x37, 0xcb, 0x75, 0xb2, 0x53, 0xcf, 0x67, 0x46, 0x0e, 0x42,
+       0x37, 0xff, 0x41, 0x61, 0xa7, 0x2c, 0x8d, 0xb6, 0xe1, 0x39, 0x26, 0x4f,
+       0x17, 0xfa, 0xe0, 0xfb, 0xbc, 0x0b, 0x38, 0x6a, 0xc4, 0x73, 0xa3, 0x0c,
+       0x5f, 0x42, 0x5e, 0x6d, 0x91, 0x45, 0x94, 0xbf, 0x5b, 0x7e, 0xc1, 0x96,
+       0xb3, 0x8c, 0xbc, 0xd1, 0x82, 0xb6, 0x31, 0x39, 0x57, 0xa0, 0x5d, 0xa9,
+       0x79, 0x62, 0xf0, 0x7b, 0xd2, 0x97, 0xfe, 0x1e, 0xec, 0xd4, 0xb3, 0xb8,
+       0x9e, 0x91, 0xd4, 0x9e, 0x71, 0xa7, 0x2f, 0xd9, 0xed, 0x40, 0x77, 0xe2,
+       0x8a, 0x3a, 0x7d, 0x6e, 0xa3, 0x73, 0x85, 0xed, 0xa3, 0x41, 0x9e, 0xd9,
+       0xab, 0x12, 0x2d, 0x58, 0x93, 0xed, 0x4e, 0x8f, 0x2d, 0xe3, 0x73, 0xca,
+       0x78, 0x40, 0xa7, 0xd4, 0x96, 0x0d, 0x22, 0x5d, 0x2d, 0xb0, 0x79, 0x26,
+       0x44, 0xb5, 0xb7, 0x48, 0x54, 0xba, 0x67, 0x55, 0x27, 0xca, 0x3c, 0x5b,
+       0x16, 0x6f, 0x81, 0x7e, 0x40, 0x59, 0x07, 0xca, 0xb6, 0xd9, 0xb2, 0xb6,
+       0x16, 0x69, 0x44, 0xd9, 0x8c, 0xe6, 0xf9, 0xf3, 0x3d, 0x9e, 0x9b, 0x75,
+       0x9a, 0xa5, 0xeb, 0x44, 0x0b, 0x64, 0xc3, 0x46, 0x59, 0xbc, 0xaa, 0x49,
+       0xba, 0xf0, 0x8e, 0x71, 0x6e, 0xff, 0x44, 0x4c, 0xae, 0x3d, 0xd1, 0x9d,
+       0xf8, 0x38, 0xe6, 0xd0, 0x7d, 0x8a, 0x71, 0xef, 0xfc, 0x25, 0x8c, 0xfb,
+       0x74, 0x9d, 0xe2, 0xbd, 0x49, 0xcb, 0x1f, 0xe2, 0xc3, 0x7c, 0x93, 0x88,
+       0x32, 0xf9, 0x24, 0xfc, 0x5c, 0xea, 0xf0, 0x6e, 0xfb, 0xfd, 0x8c, 0xe3,
+       0x97, 0xd0, 0x6f, 0x9b, 0xa5, 0x5d, 0x52, 0x24, 0x3f, 0x52, 0x0f, 0xe1,
+       0x3e, 0xe3, 0x48, 0xbe, 0x2a, 0xb3, 0xe6, 0xc9, 0x57, 0xc7, 0x14, 0x73,
+       0x59, 0x50, 0x56, 0xf9, 0xc5, 0xc0, 0xac, 0x31, 0x79, 0xc1, 0xc8, 0xa5,
+       0x0f, 0x18, 0xb9, 0xf4, 0xd8, 0x99, 0x15, 0x72, 0xe9, 0xbc, 0x96, 0x4b,
+       0x7b, 0x05, 0xf7, 0xf9, 0xf3, 0x90, 0x4b, 0x2f, 0xe2, 0xd9, 0xd5, 0x72,
+       0x29, 0x2e, 0xd6, 0x5e, 0x96, 0xaf, 0xea, 0xf1, 0xe7, 0x8a, 0x51, 0x6d,
+       0x57, 0xe5, 0x67, 0x60, 0x93, 0x14, 0xa7, 0xac, 0xfe, 0x96, 0xa1, 0x36,
+       0xe9, 0x19, 0xfc, 0xa9, 0x84, 0x36, 0xe7, 0x7f, 0xba, 0x84, 0xdf, 0xee,
+       0x7c, 0x5e, 0x51, 0x86, 0xbd, 0x0a, 0x19, 0x26, 0xaa, 0xbe, 0x0c, 0xc3,
+       0xbb, 0x32, 0xde, 0x95, 0xd9, 0xef, 0x8f, 0x7e, 0x3a, 0xe6, 0x52, 0x7e,
+       0x50, 0x66, 0x40, 0x26, 0x15, 0x21, 0x93, 0x8a, 0x90, 0x53, 0x45, 0xc8,
+       0x25, 0xd8, 0x6c, 0x67, 0x8a, 0x90, 0x4b, 0x45, 0xc8, 0x25, 0xc8, 0xb8,
+       0x27, 0x20, 0xe3, 0x8c, 0x4c, 0x1b, 0x85, 0x4c, 0x9b, 0x91, 0xfb, 0xac,
+       0xae, 0x37, 0xb1, 0x92, 0x7e, 0xeb, 0x23, 0x0d, 0xe8, 0x18, 0xf2, 0x99,
+       0x9a, 0xd8, 0xe0, 0x8d, 0x47, 0x34, 0xbf, 0xbb, 0x9e, 0xba, 0xc2, 0x61,
+       0x0e, 0xcd, 0x4f, 0xb4, 0xff, 0xbe, 0x9d, 0xbf, 0xa5, 0x09, 0x7c, 0xfd,
+       0x03, 0xcb, 0xd7, 0xdb, 0x97, 0xf9, 0x3a, 0xe5, 0x30, 0x56, 0x5c, 0x9f,
+       0xaf, 0x3b, 0xec, 0xbb, 0x5c, 0xb0, 0x0e, 0x7c, 0xbd, 0x6e, 0x15, 0x5f,
+       0xc7, 0xc0, 0xd7, 0x7b, 0xd6, 0xf0, 0xf5, 0x06, 0x67, 0x58, 0xb7, 0xe1,
+       0x19, 0x09, 0x3e, 0x37, 0x3a, 0x55, 0xbe, 0xbe, 0x47, 0xf3, 0xf5, 0x21,
+       0xf0, 0xf5, 0x75, 0x35, 0x7c, 0xbd, 0x47, 0x52, 0x37, 0x67, 0x22, 0x5b,
+       0x65, 0xfc, 0x7e, 0xd5, 0xbe, 0x49, 0xfe, 0x49, 0x4c, 0x7b, 0xc3, 0x63,
+       0xc3, 0xd3, 0xed, 0x92, 0x7d, 0xe8, 0x15, 0x94, 0x91, 0xcf, 0x52, 0x63,
+       0x69, 0xc7, 0x95, 0x83, 0x47, 0x7e, 0x22, 0x0b, 0x9a, 0xb7, 0x44, 0x26,
+       0x8e, 0xc4, 0x64, 0xf2, 0x08, 0xe3, 0x10, 0x7f, 0x63, 0xe9, 0xbd, 0x49,
+       0x26, 0xf7, 0x32, 0x6f, 0x2e, 0x2a, 0xe3, 0x47, 0xe0, 0x6f, 0x1d, 0x61,
+       0x1c, 0xe2, 0xa5, 0x65, 0x1e, 0x5b, 0x80, 0x6c, 0x19, 0x3f, 0xc2, 0xb5,
+       0x8e, 0xa1, 0x9f, 0x16, 0x39, 0x74, 0x44, 0xe4, 0xb6, 0x23, 0x51, 0xf9,
+       0xe8, 0x91, 0x65, 0x5e, 0x1b, 0x0d, 0x79, 0xed, 0x59, 0xf0, 0x5a, 0xb7,
+       0xe5, 0x35, 0xb5, 0xcc, 0x6b, 0x7f, 0x5a, 0xc3, 0x6b, 0x6c, 0x4f, 0x5e,
+       0x7b, 0xce, 0x96, 0xf1, 0x39, 0x2a, 0xfb, 0x8e, 0x74, 0xca, 0xf8, 0x43,
+       0x6f, 0x91, 0x89, 0xfb, 0x09, 0xab, 0xf9, 0x8e, 0x13, 0x6d, 0xb1, 0x99,
+       0x4a, 0x37, 0xfa, 0x0f, 0x73, 0x88, 0xf4, 0xf7, 0x10, 0x7a, 0x67, 0x25,
+       0x95, 0xe3, 0x78, 0x8d, 0xf0, 0xa3, 0x4f, 0xc0, 0xbf, 0xd8, 0x07, 0x98,
+       0x6e, 0x39, 0x22, 0xa9, 0xa8, 0xbc, 0x2c, 0x53, 0xfe, 0x27, 0x2e, 0x37,
+       0xf6, 0x04, 0x6c, 0x11, 0x6d, 0xfb, 0xa4, 0x25, 0xfb, 0xce, 0x40, 0xfb,
+       0x18, 0xa5, 0xb2, 0x30, 0x16, 0xc0, 0xb8, 0xb9, 0x63, 0xbe, 0xc7, 0xc4,
+       0xfc, 0xc7, 0x06, 0x7d, 0xe6, 0x45, 0xc7, 0x6c, 0x07, 0xf8, 0x9e, 0xcf,
+       0xb0, 0x67, 0xf4, 0x59, 0x43, 0xb6, 0x7f, 0x44, 0x7f, 0x1b, 0x91, 0x31,
+       0xf5, 0x7c, 0x99, 0xdf, 0xb0, 0x81, 0xff, 0x59, 0xe6, 0xb7, 0xb0, 0xf6,
+       0xb7, 0x9b, 0xf8, 0x2c, 0xf9, 0xee, 0x87, 0x0e, 0xbf, 0x5d, 0x35, 0xa5,
+       0x73, 0xbd, 0xf0, 0xbb, 0xcc, 0x67, 0xd6, 0x7f, 0x84, 0xf1, 0x8e, 0x64,
+       0x52, 0xbd, 0xf7, 0x72, 0xe6, 0x1e, 0xec, 0x9d, 0x67, 0xdd, 0xad, 0x96,
+       0x47, 0xb7, 0x6a, 0xbf, 0x83, 0x36, 0xd6, 0x78, 0xe9, 0x45, 0xc9, 0xd3,
+       0x36, 0x19, 0xdd, 0xea, 0xe4, 0x66, 0x92, 0x97, 0x1b, 0xfb, 0x79, 0xdd,
+       0xa5, 0xcc, 0x3b, 0x4c, 0xab, 0xb5, 0x32, 0xf9, 0x84, 0x84, 0x32, 0x39,
+       0x75, 0x33, 0xbf, 0xb7, 0x9b, 0x3d, 0xa2, 0xbf, 0x2f, 0x95, 0xec, 0x56,
+       0x9c, 0xd3, 0xa7, 0x21, 0x5f, 0x43, 0x5a, 0x48, 0xc8, 0x27, 0x8f, 0x90,
+       0x1e, 0x54, 0xbc, 0x55, 0x3e, 0x61, 0xe9, 0x61, 0x46, 0x0a, 0x90, 0x3b,
+       0x47, 0x8e, 0x7c, 0x54, 0x66, 0x6e, 0x5c, 0x4d, 0x0f, 0x13, 0x55, 0x7a,
+       0x88, 0xc3, 0x3e, 0x73, 0x6a, 0xe9, 0xe1, 0x97, 0x97, 0xe9, 0x61, 0xc6,
+       0xf9, 0xe7, 0xd2, 0xc3, 0xf5, 0x2b, 0xe8, 0x61, 0x4a, 0xd3, 0xc3, 0xce,
+       0x65, 0x7a, 0x98, 0x3a, 0xc2, 0x71, 0xf5, 0xde, 0xa8, 0xbb, 0xe8, 0x70,
+       0xcd, 0x97, 0x69, 0x21, 0x39, 0xa9, 0xf3, 0xf5, 0x53, 0x39, 0x9e, 0x6f,
+       0xda, 0xa0, 0x18, 0x27, 0xa9, 0xae, 0x7f, 0xeb, 0xbf, 0xe8, 0xfa, 0xbf,
+       0xfc, 0xff, 0x79, 0xfd, 0xd5, 0xa5, 0xcc, 0xdd, 0xe7, 0x99, 0x55, 0x23,
+       0x8f, 0x43, 0x7a, 0x88, 0x5d, 0x6a, 0xf4, 0x02, 0xd7, 0x98, 0xcf, 0x90,
+       0x67, 0x90, 0x7f, 0x67, 0x20, 0xff, 0x9e, 0x84, 0xfc, 0x3b, 0xbd, 0x62,
+       0x4f, 0x60, 0xd0, 0xc6, 0x23, 0x02, 0x39, 0xe8, 0x57, 0xf1, 0xb1, 0x38,
+       0x40, 0x7c, 0x98, 0xfc, 0x13, 0xe6, 0xfe, 0xae, 0xc4, 0x49, 0x54, 0xe7,
+       0x1c, 0x3d, 0xea, 0xd7, 0xe2, 0x84, 0x70, 0xbf, 0x5c, 0x33, 0x47, 0xfc,
+       0x2e, 0xf3, 0x79, 0x46, 0xe7, 0x91, 0xe4, 0xf5, 0x1e, 0x14, 0xf1, 0xc2,
+       0x3d, 0x28, 0xe2, 0x24, 0xaa, 0xed, 0xfd, 0x7c, 0xb9, 0x49, 0xe7, 0xd0,
+       0x1f, 0x98, 0x8f, 0xcb, 0x62, 0x9c, 0x31, 0x3e, 0x7e, 0x97, 0x90, 0x7e,
+       0xb3, 0x97, 0xc8, 0x4b, 0x8e, 0xb9, 0x72, 0xe0, 0xe9, 0x0d, 0x96, 0xb6,
+       0x19, 0x1b, 0xe4, 0x99, 0xdd, 0x70, 0x2f, 0xa2, 0xd7, 0xca, 0xba, 0x96,
+       0x9a, 0x98, 0x25, 0xf0, 0x3e, 0x2d, 0xc9, 0xcc, 0x00, 0xee, 0xf3, 0x1c,
+       0x7b, 0xbf, 0x4c, 0x3d, 0x38, 0x01, 0x5b, 0x6e, 0x2f, 0x74, 0x0e, 0xcf,
+       0x9f, 0x99, 0xef, 0x70, 0x13, 0x86, 0x59, 0xfd, 0xdd, 0x29, 0xfa, 0x80,
+       0xa4, 0x87, 0x04, 0x9e, 0x67, 0x6c, 0x5c, 0x29, 0x21, 0xf9, 0xc2, 0x05,
+       0xf3, 0x6d, 0xcb, 0xc2, 0x4b, 0xb8, 0xbf, 0xde, 0x7a, 0x18, 0x3f, 0x64,
+       0xd4, 0xdc, 0xd1, 0xd7, 0x92, 0xa4, 0xcb, 0x26, 0xc7, 0xa5, 0x1a, 0x37,
+       0x99, 0x91, 0xc3, 0xda, 0x7e, 0x1e, 0xb2, 0xb9, 0x2d, 0xa9, 0xd1, 0x9c,
+       0x18, 0x1b, 0xfa, 0x77, 0x60, 0x43, 0x7f, 0xb1, 0x92, 0xd6, 0xfb, 0x58,
+       0xa7, 0x61, 0x43, 0x3f, 0x01, 0xdd, 0x43, 0x9d, 0x13, 0xb7, 0x3a, 0x67,
+       0x4a, 0xdd, 0xa8, 0x75, 0xce, 0x37, 0xb5, 0xce, 0x79, 0xef, 0x1a, 0x9d,
+       0x73, 0x48, 0x75, 0x97, 0xa8, 0x73, 0x86, 0xd5, 0x1e, 0x87, 0xf6, 0xe2,
+       0xe6, 0x3a, 0x3a, 0xe7, 0x7d, 0xf2, 0x2e, 0xfb, 0xee, 0x1e, 0x79, 0xff,
+       0x0e, 0xbd, 0x77, 0xe3, 0xce, 0x2a, 0x7e, 0x6b, 0xc9, 0xe8, 0xa0, 0xeb,
+       0x54, 0xaf, 0xde, 0xf3, 0xfd, 0x46, 0x8d, 0xce, 0xe9, 0x52, 0x03, 0xce,
+       0xb0, 0x6e, 0xc3, 0xd8, 0x04, 0x9f, 0x7d, 0x27, 0x3d, 0xda, 0x84, 0xe7,
+       0x84, 0x44, 0x8e, 0x60, 0xee, 0xe6, 0x7b, 0x50, 0xca, 0xbc, 0x7b, 0xab,
+       0x7d, 0xa7, 0xc2, 0xf2, 0xa8, 0x29, 0xef, 0xb6, 0xe5, 0x46, 0x57, 0x75,
+       0xa9, 0x4e, 0xad, 0xab, 0xb6, 0x83, 0xa1, 0x66, 0xa1, 0x5f, 0x67, 0x8b,
+       0xa1, 0xce, 0xe2, 0x6f, 0xc6, 0x9e, 0x19, 0xa3, 0x08, 0x63, 0xd8, 0x49,
+       0xd4, 0xc1, 0x55, 0x0c, 0x6d, 0x4a, 0xfe, 0x86, 0xaf, 0x80, 0x6b, 0x1e,
+       0x78, 0xbd, 0x19, 0xfc, 0xf3, 0x6f, 0x0a, 0x8c, 0x81, 0xb6, 0xcb, 0xd1,
+       0xe9, 0xda, 0x77, 0x9d, 0xf2, 0x9e, 0xe9, 0x2d, 0xb2, 0xbf, 0xf4, 0x2d,
+       0xf0, 0xc1, 0x56, 0x99, 0x2a, 0x15, 0xf4, 0x79, 0xf5, 0x4d, 0xfa, 0x3b,
+       0x1e, 0xfc, 0xbe, 0x8d, 0x91, 0x91, 0x3b, 0x1d, 0x23, 0x23, 0xd3, 0xaa,
+       0x6a, 0xb3, 0x86, 0x7d, 0xf2, 0xdb, 0x21, 0x23, 0xa5, 0x84, 0xfe, 0xc6,
+       0xe9, 0x6c, 0xe5, 0x0a, 0xf9, 0xc2, 0x31, 0x75, 0xa7, 0xaa, 0x9e, 0xef,
+       0xd5, 0x36, 0xeb, 0xdc, 0x0a, 0x9b, 0xf5, 0xaf, 0x64, 0xf1, 0xfd, 0x31,
+       0xcc, 0x13, 0x34, 0x7c, 0xe5, 0xf7, 0xb8, 0x17, 0xda, 0x1e, 0x97, 0x0b,
+       0x32, 0xa2, 0xf1, 0x47, 0x79, 0xda, 0x02, 0x39, 0xb8, 0xa4, 0xf5, 0xeb,
+       0x66, 0xd0, 0x20, 0x65, 0xe9, 0xc7, 0xe4, 0x45, 0x2d, 0xcf, 0x36, 0x5b,
+       0xdb, 0x75, 0x81, 0xb1, 0xd4, 0x23, 0xb4, 0x5d, 0xbf, 0x69, 0xcb, 0x59,
+       0x96, 0x4a, 0x2c, 0x09, 0xf5, 0x5d, 0x1c, 0x32, 0x94, 0xf2, 0xf4, 0x8d,
+       0xda, 0xae, 0x5f, 0xb3, 0x7d, 0x50, 0x7e, 0x1a, 0xd9, 0xbd, 0xdd, 0x59,
+       0xb0, 0x65, 0x7c, 0x0e, 0xe3, 0xe9, 0x5e, 0x3a, 0x6b, 0xf9, 0x4c, 0x39,
+       0x5f, 0xc2, 0xfb, 0x4d, 0x78, 0x4f, 0x3e, 0x3b, 0xad, 0xf9, 0x4c, 0xdb,
+       0x27, 0x4e, 0xbf, 0xdd, 0x5f, 0x58, 0xde, 0x1b, 0xc8, 0x91, 0xcf, 0xd4,
+       0x51, 0x77, 0xc1, 0xc8, 0x03, 0xe6, 0xa9, 0x7e, 0x1e, 0xba, 0x83, 0x6d,
+       0x51, 0xfe, 0x70, 0x9a, 0xbe, 0x2d, 0xfc, 0x9f, 0x56, 0x3c, 0xb7, 0xe3,
+       0x79, 0x56, 0xde, 0xbb, 0x37, 0xa6, 0xe7, 0x3d, 0x85, 0x79, 0x1c, 0x38,
+       0x82, 0x39, 0x39, 0xc6, 0x76, 0x8e, 0x9e, 0x8a, 0x4a, 0xc3, 0x29, 0xf2,
+       0x1d, 0xcf, 0xda, 0x04, 0xc1, 0xbe, 0x7e, 0xd2, 0x6d, 0xca, 0xdd, 0xa9,
+       0xcf, 0x96, 0x6e, 0x4f, 0x44, 0x80, 0x93, 0x03, 0x58, 0x8f, 0xa9, 0x82,
+       0xe7, 0x66, 0x1c, 0x2f, 0x81, 0x79, 0xc2, 0x06, 0xec, 0x86, 0x2d, 0xd8,
+       0x0d, 0x3b, 0xb0, 0x1b, 0x76, 0xe0, 0x46, 0x39, 0x71, 0x15, 0x73, 0x4c,
+       0x72, 0xd7, 0xc2, 0x2b, 0x97, 0xef, 0xe8, 0x38, 0x7d, 0xe3, 0xcd, 0x23,
+       0xf0, 0xd9, 0xc5, 0x4d, 0x8d, 0x32, 0x0f, 0x7f, 0xc9, 0x6d, 0xbc, 0x79,
+       0xa7, 0x74, 0x0f, 0xe2, 0xfd, 0xe0, 0x05, 0xe9, 0xb9, 0xf9, 0x56, 0xa7,
+       0x71, 0x74, 0x04, 0x78, 0x4c, 0x3b, 0xa9, 0xc4, 0x98, 0xb3, 0x80, 0x71,
+       0x32, 0xdb, 0x23, 0xc2, 0xb8, 0xe5, 0x02, 0x63, 0x11, 0x37, 0x77, 0x47,
+       0xfa, 0x92, 0xe3, 0x4e, 0x6a, 0x54, 0x45, 0x52, 0xa3, 0x23, 0x4e, 0x58,
+       0x8f, 0xdf, 0x48, 0x85, 0x9c, 0x01, 0xac, 0x07, 0x8a, 0xd3, 0xa0, 0xa7,
+       0xff, 0x28, 0xf9, 0x63, 0x2d, 0x32, 0x5f, 0xe8, 0x76, 0x33, 0x2a, 0xae,
+       0x73, 0x4b, 0xd4, 0x09, 0x10, 0xfd, 0xa9, 0x98, 0xcc, 0x96, 0xb6, 0x8a,
+       0xd2, 0xb6, 0x7b, 0x87, 0x64, 0xa6, 0x4b, 0x72, 0x6e, 0x40, 0xda, 0x14,
+       0xfa, 0xe7, 0xb7, 0x67, 0xd5, 0x09, 0xee, 0x25, 0x86, 0xbc, 0x70, 0x39,
+       0xf9, 0xa4, 0x04, 0x1c, 0x82, 0x6e, 0x19, 0xe3, 0x6d, 0x12, 0xca, 0xbd,
+       0x8f, 0xea, 0xf8, 0x29, 0x63, 0xb6, 0xb5, 0x7b, 0x0f, 0xe4, 0x8f, 0x58,
+       0x5d, 0xfe, 0x98, 0x2b, 0x72, 0x9f, 0x46, 0x72, 0x51, 0xc6, 0x88, 0x3d,
+       0xfc, 0x9e, 0x61, 0xdd, 0x26, 0x99, 0x1a, 0xc8, 0xd9, 0x3c, 0x8f, 0x47,
+       0x12, 0xcc, 0x21, 0x26, 0x4e, 0xc6, 0x07, 0xc8, 0xeb, 0xab, 0xf7, 0x36,
+       0x62, 0x35, 0xf2, 0xc0, 0x91, 0xc5, 0x52, 0xb8, 0x17, 0xc2, 0xfe, 0xf0,
+       0x3c, 0x63, 0xe4, 0x6d, 0x66, 0x4d, 0x3b, 0xc2, 0xc5, 0xfd, 0xca, 0x95,
+       0x32, 0x56, 0x79, 0x94, 0xa9, 0xae, 0x96, 0xaf, 0x8f, 0x55, 0x8c, 0x6c,
+       0x9d, 0xa9, 0x84, 0xba, 0x25, 0x66, 0x74, 0xe9, 0x1a, 0x7d, 0x62, 0xa2,
+       0x99, 0x55, 0x7d, 0x42, 0xbd, 0xa8, 0xe4, 0x03, 0xf3, 0x1d, 0x12, 0x7d,
+       0x58, 0x96, 0xa6, 0xbc, 0xec, 0xe5, 0xcc, 0xd5, 0x98, 0xf2, 0xdf, 0x8c,
+       0x7e, 0xfc, 0x6f, 0x09, 0xea, 0xc3, 0x31, 0xf5, 0x75, 0xdc, 0x37, 0x69,
+       0xfa, 0x03, 0x4f, 0xe1, 0xd9, 0xf8, 0x09, 0xbf, 0x03, 0x3f, 0xe1, 0x8b,
+       0xd0, 0x75, 0x67, 0xe0, 0x27, 0x3c, 0x09, 0x3f, 0xe1, 0x34, 0xfc, 0x84,
+       0x27, 0xa0, 0x27, 0x6b, 0xfd, 0x83, 0xc9, 0x15, 0xfe, 0x41, 0xa0, 0xf9,
+       0x9f, 0xf1, 0xc0, 0x27, 0x6b, 0x7c, 0x83, 0x7d, 0x46, 0x5f, 0xc1, 0xef,
+       0x37, 0x7c, 0xd4, 0xa5, 0x6e, 0xd2, 0xfa, 0xd1, 0xe4, 0xed, 0x8e, 0x2e,
+       0xeb, 0xab, 0x2e, 0x65, 0xf4, 0xd5, 0x6c, 0x55, 0x5f, 0x19, 0x3e, 0x7a,
+       0xb8, 0x24, 0x11, 0xaf, 0xb4, 0x90, 0xf1, 0x77, 0x69, 0x1e, 0x6a, 0xf3,
+       0xb6, 0x4a, 0xe4, 0x01, 0xd5, 0xde, 0x20, 0x19, 0xfb, 0x0c, 0xfa, 0x3a,
+       0x3a, 0x8d, 0xbe, 0xae, 0x95, 0xac, 0xb6, 0xcf, 0x2e, 0x8e, 0xef, 0x27,
+       0x56, 0xe1, 0x3b, 0x5f, 0xbc, 0x5b, 0xe3, 0xfc, 0xfe, 0x32, 0xf7, 0x59,
+       0x5a, 0x64, 0xb2, 0x1c, 0xe2, 0x9c, 0xe7, 0x59, 0x99, 0x8b, 0xd1, 0x29,
+       0x91, 0x87, 0x3b, 0x78, 0xce, 0x4a, 0x65, 0xfd, 0xf5, 0x3a, 0x87, 0xe5,
+       0xc4, 0x80, 0x24, 0xb2, 0x03, 0xa4, 0xd5, 0xfb, 0x64, 0x56, 0xaf, 0x45,
+       0x87, 0x34, 0x3c, 0x4c, 0x1b, 0x25, 0xdc, 0xcf, 0xeb, 0xba, 0xcc, 0x7e,
+       0x23, 0x35, 0x66, 0xea, 0x89, 0x1c, 0xd4, 0xeb, 0x75, 0x5c, 0xe7, 0x19,
+       0xde, 0x34, 0xcf, 0xb8, 0x3c, 0xbf, 0x47, 0xc5, 0x98, 0xfc, 0x3f, 0x67,
+       0xfd, 0x7e, 0xe1, 0x32, 0x63, 0xcf, 0x6c, 0xb2, 0x76, 0x8c, 0x89, 0x53,
+       0xd5, 0xb7, 0x61, 0xd8, 0x4f, 0xed, 0x37, 0x14, 0xb7, 0x38, 0x93, 0xa5,
+       0xad, 0x4e, 0xbe, 0xc4, 0xbd, 0x6c, 0xfb, 0xf7, 0x2e, 0xdc, 0x3d, 0xce,
+       0x01, 0x6f, 0x0b, 0xca, 0x18, 0xb3, 0x64, 0xcc, 0xe6, 0x97, 0x2e, 0x63,
+       0x8c, 0x36, 0xe3, 0x71, 0x6c, 0x96, 0x6d, 0x71, 0xa6, 0x4a, 0xdd, 0xf0,
+       0xcd, 0x79, 0xae, 0x8a, 0xef, 0x77, 0x72, 0xed, 0xa0, 0x83, 0x5d, 0x7d,
+       0x66, 0x77, 0x42, 0xae, 0xb0, 0x31, 0x68, 0xea, 0xe1, 0x9f, 0x5f, 0xb1,
+       0x77, 0x7b, 0x08, 0x7a, 0xec, 0x16, 0xc8, 0x23, 0xea, 0xe1, 0x43, 0x72,
+       0xb5, 0xa5, 0xe7, 0x95, 0x7a, 0xf8, 0xbc, 0x30, 0x4e, 0xdc, 0x8f, 0x77,
+       0xb9, 0x20, 0x06, 0x7a, 0x38, 0x5c, 0xe3, 0xab, 0xd1, 0xef, 0x6b, 0x1a,
+       0x32, 0xfb, 0x61, 0x2b, 0xfd, 0x3e, 0xc8, 0x81, 0x78, 0xe8, 0xe7, 0x35,
+       0x2e, 0xef, 0xd7, 0xee, 0xb1, 0x6d, 0xa7, 0xfc, 0xfb, 0x89, 0xa3, 0xe4,
+       0x21, 0xe9, 0x81, 0x2e, 0x63, 0x0e, 0xc8, 0x6f, 0x69, 0x9c, 0x89, 0x22,
+       0xed, 0x6d, 0xd2, 0x30, 0x5a, 0x39, 0x9f, 0x0c, 0x73, 0x38, 0xf2, 0xb6,
+       0xed, 0x84, 0xdd, 0x93, 0xcf, 0xcb, 0xdc, 0x65, 0xd4, 0x83, 0x23, 0x91,
+       0xf5, 0xfc, 0x7e, 0x22, 0xda, 0xf6, 0x18, 0xbd, 0x28, 0x61, 0x5f, 0x7c,
+       0x6e, 0xa8, 0xe9, 0x9b, 0x76, 0x14, 0xef, 0xab, 0xcf, 0x91, 0x3d, 0xa3,
+       0xf7, 0x19, 0xcd, 0xf7, 0x12, 0x42, 0x3e, 0x21, 0xef, 0x24, 0xf5, 0x59,
+       0x27, 0xef, 0x61, 0xda, 0x3d, 0xdc, 0x83, 0x75, 0x17, 0x26, 0xfd, 0x4f,
+       0xe8, 0x6f, 0xfc, 0xcd, 0x88, 0x38, 0x79, 0xff, 0x36, 0x9d, 0x7b, 0x92,
+       0xd7, 0xb1, 0xe6, 0x1c, 0xee, 0x55, 0x1f, 0xb5, 0xeb, 0x61, 0xfe, 0x4d,
+       0x0b, 0x96, 0x65, 0x01, 0x1b, 0x75, 0x08, 0x65, 0x6f, 0x5c, 0xba, 0x8e,
+       0x7e, 0x58, 0xf3, 0xc2, 0x66, 0xf8, 0x02, 0xc3, 0x47, 0xa1, 0xab, 0x8f,
+       0x26, 0x64, 0xe7, 0x51, 0xad, 0x1b, 0xd3, 0x6b, 0x63, 0x05, 0x7d, 0x6e,
+       0xd4, 0x79, 0x8f, 0x3e, 0xc7, 0xf6, 0xd6, 0xa3, 0x11, 0x39, 0x1c, 0xef,
+       0x73, 0x7b, 0x9c, 0xf7, 0x5a, 0x5d, 0x18, 0xc6, 0xb0, 0x5b, 0xd0, 0xfe,
+       0xf5, 0xe2, 0xd8, 0x61, 0xfc, 0x3a, 0x22, 0x33, 0x7b, 0x3b, 0x01, 0xdb,
+       0x5f, 0x5d, 0x66, 0xce, 0x20, 0x63, 0xad, 0xf4, 0xb7, 0xe7, 0xa3, 0x09,
+       0xca, 0xb2, 0x2e, 0xc0, 0x32, 0x72, 0x94, 0xfa, 0xcc, 0xd3, 0x3c, 0x0e,
+       0x18, 0xdc, 0x06, 0xed, 0x87, 0x90, 0x2f, 0xdf, 0x22, 0xde, 0x03, 0x90,
+       0x71, 0x47, 0x63, 0xd2, 0x73, 0xb4, 0x45, 0xb6, 0x1d, 0xa5, 0x1f, 0x52,
+       0xeb, 0x97, 0xd2, 0x2e, 0x7d, 0x04, 0x73, 0x7c, 0xb7, 0x96, 0x93, 0xdc,
+       0xd3, 0xdc, 0x4f, 0xde, 0x45, 0xdd, 0x2c, 0x6c, 0xe6, 0xcc, 0x51, 0x57,
+       0xef, 0x91, 0x66, 0x30, 0xe7, 0x6c, 0xd9, 0xc5, 0x38, 0x46, 0xe6, 0xe4,
+       0xe9, 0xa7, 0x8c, 0x76, 0x00, 0xc7, 0xef, 0xb5, 0xbc, 0xb3, 0xbe, 0xc3,
+       0xf2, 0xe8, 0xcf, 0xc8, 0x7b, 0x5b, 0x3a, 0x8c, 0xec, 0x7c, 0x4b, 0x07,
+       0x73, 0x93, 0x36, 0x7b, 0xbc, 0x37, 0x69, 0x7b, 0xc2, 0xc8, 0xd0, 0xd7,
+       0xe2, 0x45, 0x01, 0x8e, 0xc2, 0x7d, 0x29, 0x7d, 0x96, 0x2f, 0x38, 0xe7,
+       0xeb, 0xf3, 0x2b, 0xfe, 0xa2, 0xfe, 0x3b, 0x21, 0xdc, 0x23, 0xab, 0x7e,
+       0x6f, 0x65, 0x57, 0x85, 0x71, 0xf2, 0xcf, 0x86, 0x7f, 0x97, 0xa4, 0x26,
+       0xef, 0xb0, 0x76, 0x0f, 0x8c, 0xb1, 0xa6, 0xe5, 0xdc, 0xa0, 0xa0, 0xa4,
+       0xbf, 0x5f, 0xf4, 0x9c, 0x73, 0xbe, 0x70, 0xd6, 0xf9, 0xee, 0xb4, 0x04,
+       0x51, 0xef, 0x27, 0xce, 0xf7, 0x3d, 0xee, 0x99, 0x7f, 0xdd, 0xf9, 0x5e,
+       0xc1, 0x03, 0x1f, 0xde, 0x87, 0x79, 0xbc, 0xe2, 0xfc, 0x00, 0xeb, 0x7b,
+       0xb0, 0x98, 0x4e, 0xb9, 0x36, 0x26, 0x7e, 0xb6, 0xf0, 0x8a, 0xf3, 0xb5,
+       0x6a, 0x3c, 0x69, 0x30, 0xa4, 0x91, 0x43, 0x7c, 0x57, 0xc6, 0xbb, 0xb2,
+       0xde, 0xff, 0x71, 0xe6, 0xa6, 0x6d, 0x7e, 0x89, 0xe6, 0xe3, 0x85, 0xe5,
+       0x7d, 0x99, 0x51, 0xbd, 0x57, 0xf1, 0xac, 0x33, 0x37, 0x7f, 0x77, 0x87,
+       0xc9, 0x33, 0x3a, 0x8b, 0x77, 0x26, 0xe7, 0x72, 0x76, 0xfe, 0x2c, 0xea,
+       0x3c, 0xe3, 0xcc, 0xea, 0xf8, 0x97, 0xf6, 0xc5, 0x9d, 0x99, 0xf9, 0x67,
+       0x9c, 0x79, 0xbd, 0x07, 0x7d, 0xce, 0x79, 0x74, 0x9a, 0x7d, 0x9f, 0x43,
+       0x9d, 0x05, 0xe7, 0x04, 0xfa, 0x9b, 0x9f, 0xe6, 0x79, 0xdc, 0x6e, 0xd8,
+       0x05, 0xfc, 0x7b, 0x3f, 0xfc, 0x1e, 0xc7, 0xb3, 0xce, 0xfc, 0x72, 0xbf,
+       0x8b, 0xe8, 0x87, 0x75, 0x49, 0x8b, 0x1c, 0xf7, 0x59, 0xf4, 0xbf, 0x76,
+       0xaf, 0x6a, 0x2d, 0x4e, 0x5e, 0x00, 0x4e, 0x2e, 0x58, 0x9c, 0xbc, 0x6a,
+       0x71, 0xf2, 0x7c, 0x0d, 0x4e, 0x44, 0xad, 0xc4, 0xc9, 0xab, 0xc0, 0x89,
+       0xa8, 0xfa, 0x38, 0xc1, 0xbb, 0x32, 0xde, 0x69, 0x9c, 0xbc, 0xb4, 0x0a,
+       0x27, 0x4b, 0xcb, 0x71, 0x79, 0x83, 0x93, 0x17, 0x81, 0x93, 0xaf, 0x5a,
+       0xd8, 0x2f, 0x58, 0x9c, 0xe0, 0x3e, 0x7f, 0x01, 0x75, 0x5e, 0xaa, 0xc1,
+       0xc9, 0x05, 0xe0, 0xe4, 0x25, 0x8b, 0x93, 0xef, 0x5b, 0x9c, 0x7c, 0x1f,
+       0x75, 0x96, 0x80, 0x93, 0xf3, 0x75, 0x70, 0xf2, 0x22, 0x70, 0x12, 0xf6,
+       0x7b, 0x1e, 0xfd, 0x7c, 0xbf, 0x06, 0x27, 0x2f, 0xd6, 0xc1, 0x09, 0xf7,
+       0x62, 0xc3, 0x9c, 0xee, 0x99, 0xd7, 0xc9, 0xe9, 0x96, 0x3b, 0x5f, 0x3f,
+       0xa7, 0x9b, 0x75, 0x66, 0xa4, 0xfa, 0x37, 0x25, 0xee, 0xb6, 0x39, 0x6a,
+       0x26, 0x17, 0xb0, 0xfa, 0xcd, 0xa6, 0x6e, 0xf0, 0x79, 0x3e, 0xe7, 0x8a,
+       0xc9, 0x29, 0x8d, 0xee, 0xf8, 0x10, 0x78, 0x6d, 0x97, 0x1c, 0x38, 0xd6,
+       0x78, 0x38, 0x6b, 0xcb, 0xbc, 0x1d, 0xdd, 0x39, 0xa5, 0xf8, 0x2e, 0xcc,
+       0x49, 0xa0, 0x5f, 0xd2, 0xc0, 0x6f, 0x0b, 0xf6, 0xa6, 0xa5, 0x76, 0x4f,
+       0xba, 0xc0, 0x6f, 0x34, 0x61, 0xec, 0x25, 0xfe, 0xfd, 0x8b, 0x24, 0xf3,
+       0xac, 0xf2, 0x1a, 0xde, 0x14, 0xf4, 0xc7, 0xa0, 0xce, 0xad, 0xca, 0x14,
+       0x68, 0x73, 0x27, 0x99, 0xa3, 0x06, 0x5b, 0x79, 0xc8, 0x9e, 0x09, 0xf3,
+       0xf5, 0x39, 0x95, 0x2a, 0xff, 0xd4, 0x9e, 0x87, 0x26, 0xdf, 0x55, 0xe9,
+       0xe6, 0xe0, 0xf2, 0x77, 0x02, 0x4f, 0xca, 0xd3, 0x3a, 0x56, 0xdc, 0x8c,
+       0xf5, 0x09, 0x82, 0xc7, 0x7c, 0x13, 0xa3, 0x5d, 0xd4, 0x31, 0x5a, 0x81,
+       0x37, 0x3e, 0x69, 0xe3, 0xb4, 0x3d, 0x83, 0x2f, 0x2d, 0xc7, 0x68, 0x6b,
+       0xf3, 0x59, 0xcc, 0xfe, 0x7a, 0xa6, 0xf4, 0x88, 0xce, 0xd1, 0x19, 0xe1,
+       0xf7, 0x37, 0x20, 0x23, 0x26, 0x66, 0xe6, 0x65, 0xf2, 0x41, 0x3e, 0x53,
+       0xbf, 0x45, 0xa0, 0xc3, 0x28, 0xc3, 0x73, 0x92, 0x19, 0x64, 0x99, 0x69,
+       0x33, 0xa2, 0xfd, 0xe5, 0x93, 0x32, 0xbc, 0x3c, 0x3e, 0xf1, 0x7b, 0x57,
+       0xcd, 0x77, 0xab, 0x69, 0xf3, 0xa4, 0x9d, 0x4c, 0x85, 0xef, 0xc3, 0x3d,
+       0xf2, 0xbb, 0xec, 0xb7, 0xb3, 0xf8, 0xbe, 0xf6, 0x5b, 0xad, 0x5a, 0x74,
+       0xe0, 0x37, 0xbf, 0x87, 0x36, 0xe5, 0x8c, 0xa0, 0xcd, 0x82, 0xdb, 0x32,
+       0xaa, 0x86, 0x6e, 0x18, 0xe5, 0xb9, 0xb9, 0xd9, 0x35, 0xdf, 0xba, 0xae,
+       0xea, 0xc5, 0xbc, 0x5e, 0x53, 0xe6, 0x67, 0xdd, 0x05, 0x5a, 0xd4, 0xb4,
+       0xa5, 0xe9, 0xff, 0xc0, 0xb2, 0xbe, 0xa4, 0x9e, 0x35, 0xdf, 0x9e, 0x31,
+       0xfa, 0x32, 0x95, 0x18, 0xc1, 0xf8, 0xfa, 0x6f, 0x2a, 0xd8, 0x73, 0xbd,
+       0xd9, 0xf9, 0xdb, 0xb5, 0xae, 0x9f, 0xf2, 0xd3, 0xc9, 0xa8, 0xd4, 0xa9,
+       0x5b, 0xaa, 0xa9, 0xab, 0xe7, 0xed, 0xca, 0x7f, 0xc5, 0xda, 0x7c, 0xbe,
+       0x58, 0x96, 0xe1, 0xe9, 0xbf, 0x84, 0xff, 0x98, 0x90, 0xdf, 0x2e, 0x96,
+       0x40, 0xaf, 0xb9, 0xcd, 0xf6, 0x5b, 0x4d, 0x19, 0xc0, 0xcd, 0x6f, 0xaf,
+       0xe8, 0x7c, 0xe2, 0xc8, 0x17, 0x40, 0x17, 0x9f, 0x2b, 0x71, 0x0c, 0xc0,
+       0x12, 0x81, 0x6d, 0x0f, 0x3b, 0x61, 0xa6, 0xa4, 0x73, 0xe7, 0xae, 0x2b,
+       0x97, 0x74, 0xcc, 0x62, 0x67, 0xb9, 0x53, 0x76, 0x95, 0x5b, 0x64, 0x37,
+       0xf4, 0xc2, 0xee, 0xb2, 0x87, 0x2b, 0x26, 0xef, 0x2e, 0x9b, 0x75, 0xfa,
+       0x58, 0x99, 0xeb, 0xbd, 0x43, 0x66, 0x8f, 0xad, 0xfe, 0x3e, 0xe7, 0x42,
+       0x2e, 0xfc, 0x3b, 0x4b, 0x4a, 0x31, 0xbf, 0x8c, 0xb4, 0x84, 0xab, 0x98,
+       0x3a, 0xbc, 0xa0, 0xf1, 0xc0, 0x0c, 0xd7, 0x54, 0x69, 0x49, 0x98, 0xa7,
+       0xcf, 0xbf, 0xad, 0x34, 0x73, 0x39, 0xcf, 0x4d, 0xf3, 0x5b, 0x5e, 0x3b,
+       0x2b, 0x61, 0xde, 0x78, 0xbd, 0x9c, 0x71, 0xd8, 0xf9, 0x3b, 0xc2, 0x1c,
+       0xbf, 0x18, 0x73, 0xc6, 0xa5, 0xeb, 0x54, 0x0b, 0xee, 0xa7, 0x2f, 0xd7,
+       0x67, 0x9b, 0x4f, 0x89, 0x2d, 0xd3, 0xf9, 0xe4, 0x78, 0x5e, 0xfd, 0x7d,
+       0xb5, 0x90, 0x1f, 0xaa, 0x7f, 0xa7, 0x40, 0xe4, 0xff, 0x02, 0xfb, 0x2e,
+       0x88, 0x71, 0xec, 0x6e, 0x00, 0x00, 0x00 };
+
+static const u32 bnx2_CP_b09FwData[(0x0/4) + 1] = { 0x0 };
+static const u32 bnx2_CP_b09FwRodata[(0x118/4) + 1] = {
+       0x0800061c, 0x0800083c, 0x08000780, 0x080007a8, 0x080007d0, 0x080007f8,
+       0x08000654, 0x08000640, 0x08000864, 0x08000864, 0x08000670, 0x0800068c,
+       0x0800068c, 0x08000864, 0x080006a4, 0x080006b8, 0x08000864, 0x080006cc,
+       0x08000864, 0x08000864, 0x080006e0, 0x08000864, 0x08000864, 0x08000864,
+       0x08000864, 0x08000864, 0x08000864, 0x08000864, 0x08000864, 0x08000864,
+       0x08000864, 0x080006f4, 0x08000864, 0x08000708, 0x0800071c, 0x08000730,
+       0x08000864, 0x08000744, 0x08000758, 0x0800076c, 0x08003200, 0x08003218,
+       0x08003228, 0x08003238, 0x08003250, 0x08003268, 0x08003278, 0x08003288,
+       0x080032a8, 0x080032b8, 0x080032c8, 0x08003358, 0x08003298, 0x080032d8,
+       0x080032e8, 0x08003300, 0x08003320, 0x08003358, 0x08003338, 0x08003338,
+       0x080050d4, 0x080050d4, 0x080050d4, 0x080050d4, 0x080050d4, 0x080050fc,
+       0x080050fc, 0x08005124, 0x08005174, 0x08005144, 0x00000000 };
+static const u32 bnx2_CP_b09FwBss[(0x3b0/4) + 1] = { 0x0 };
+static const u32 bnx2_CP_b09FwSbss[(0xa1/4) + 1] = { 0x0 };
 
 static struct fw_info bnx2_cp_fw_09 = {
-       .ver_major                      = 0x1,
-       .ver_minor                      = 0x0,
-       .ver_fix                        = 0x0,
+       .ver_major                      = 0x3,
+       .ver_minor                      = 0x4,
+       .ver_fix                        = 0x3,
 
        .start_addr                     = 0x0800006c,
 
        .text_addr                      = 0x08000000,
-       .text_len                       = 0x73cc,
+       .text_len                       = 0x6ee8,
        .text_index                     = 0x0,
        .gz_text                        = bnx2_CP_b09FwText,
        .gz_text_len                    = sizeof(bnx2_CP_b09FwText),
 
-       .data_addr                      = 0x08007500,
-       .data_len                       = 0x50,
+       .data_addr                      = 0x08007020,
+       .data_len                       = 0x0,
        .data_index                     = 0x0,
        .data                           = bnx2_CP_b09FwData,
 
-       .sbss_addr                      = 0x08007554,
-       .sbss_len                       = 0xe9,
+       .sbss_addr                      = 0x08007024,
+       .sbss_len                       = 0xa1,
        .sbss_index                     = 0x0,
        .sbss                           = bnx2_CP_b09FwSbss,
 
-       .bss_addr                       = 0x08007640,
-       .bss_len                        = 0x870,
+       .bss_addr                       = 0x080070d0,
+       .bss_len                        = 0x3b0,
        .bss_index                      = 0x0,
        .bss                            = bnx2_CP_b09FwBss,
 
-       .rodata_addr                    = 0x080073d0,
+       .rodata_addr                    = 0x08006ee8,
        .rodata_len                     = 0x118,
        .rodata_index                   = 0x0,
        .rodata                         = bnx2_CP_b09FwRodata,
 };
 
 static u8 bnx2_RXP_b09FwText[] = {
-       0x1f, 0x8b, 0x08, 0x08, 0x19, 0xfd, 0x2f, 0x45, 0x00, 0x03, 0x74, 0x65,
-       0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xec, 0x5c, 0x6b, 0x6c,
-       0x1c, 0xd7, 0x75, 0x3e, 0xf3, 0x20, 0xb5, 0xa2, 0xf8, 0x18, 0x2e, 0x57,
-       0xcc, 0x4a, 0x66, 0xec, 0x5d, 0x71, 0x24, 0xb2, 0x16, 0x6b, 0x8c, 0xd8,
-       0xad, 0x4d, 0x04, 0x6b, 0x7b, 0x33, 0xbb, 0x92, 0x98, 0x54, 0x85, 0x29,
-       0x87, 0x75, 0x0c, 0xc3, 0x75, 0xd9, 0xa5, 0x1a, 0xbb, 0xae, 0x51, 0xc8,
-       0x8f, 0xc4, 0x06, 0x6a, 0xd6, 0x9b, 0x25, 0xdd, 0xa8, 0xe9, 0x82, 0x43,
-       0x4b, 0xaa, 0xe9, 0x02, 0x69, 0xbb, 0x20, 0xa9, 0xc7, 0x8f, 0x85, 0x56,
-       0x76, 0x52, 0xc7, 0xf9, 0xe1, 0x48, 0x50, 0x95, 0x20, 0x28, 0x0c, 0x43,
-       0x48, 0x8d, 0xd6, 0x3f, 0xda, 0x40, 0x95, 0x9f, 0x68, 0x92, 0x42, 0x41,
-       0x0b, 0xc7, 0x68, 0x6c, 0x4f, 0xbf, 0xef, 0xce, 0x0c, 0xb9, 0xa4, 0x5f,
-       0x40, 0x7f, 0xf4, 0x4f, 0xe7, 0x02, 0x8b, 0xb9, 0xf7, 0xce, 0x3d, 0xe7,
-       0x9e, 0x7b, 0xde, 0xe7, 0x0e, 0xa5, 0xdf, 0xef, 0x94, 0x0e, 0x09, 0x5b,
-       0x17, 0x7e, 0x99, 0xc3, 0x8f, 0x3d, 0x74, 0xc3, 0xd8, 0x0d, 0xa3, 0x22,
-       0x7b, 0xf6, 0x18, 0x5b, 0x12, 0x7a, 0x34, 0x1f, 0xb7, 0xb8, 0xc5, 0x2d,
-       0x6e, 0x71, 0x8b, 0x5b, 0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e,
-       0x71, 0x8b, 0x5b, 0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71,
-       0x8b, 0x5b, 0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71, 0x8b,
-       0x5b, 0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71, 0x8b, 0x5b,
-       0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71, 0x8b, 0x5b, 0xdc,
-       0xe2, 0xf6, 0xff, 0xbd, 0x19, 0x22, 0x16, 0x9f, 0x5d, 0xe1, 0x4f, 0x12,
-       0x7a, 0xfe, 0xf2, 0x1f, 0xba, 0xb6, 0x24, 0x8c, 0xfc, 0xcf, 0x66, 0xa6,
-       0x6d, 0x91, 0x42, 0x63, 0x77, 0xa6, 0x28, 0xef, 0xfb, 0x95, 0x94, 0x29,
-       0x9c, 0xff, 0x6c, 0xfe, 0xbd, 0xbf, 0x7d, 0xf1, 0xa6, 0xec, 0xd5, 0xba,
-       0x21, 0x09, 0x2b, 0x3f, 0xb7, 0xc7, 0xda, 0x25, 0x89, 0x01, 0xc0, 0x7c,
-       0x6b, 0xe8, 0xc7, 0xdd, 0xd2, 0x2d, 0x6b, 0x78, 0xec, 0x84, 0x5c, 0x36,
-       0x5e, 0xd0, 0xdc, 0xa6, 0xef, 0x9f, 0x70, 0x7c, 0xff, 0x87, 0xf8, 0xbd,
-       0xe5, 0x60, 0xec, 0x7d, 0xe0, 0x17, 0x4c, 0x43, 0x74, 0xfb, 0x2f, 0x34,
-       0x77, 0xb9, 0x43, 0xaa, 0x8b, 0xa6, 0xcc, 0x7a, 0x29, 0x39, 0xe2, 0x55,
-       0xb4, 0x52, 0xb3, 0xa6, 0xed, 0x3d, 0x35, 0xaf, 0xed, 0x3b, 0x75, 0x44,
-       0xdb, 0x7f, 0x6a, 0x41, 0x73, 0x4f, 0x49, 0x45, 0xdf, 0xd3, 0x29, 0x05,
-       0xeb, 0xb4, 0x56, 0x6c, 0xf6, 0x6b, 0xee, 0xe2, 0x7b, 0xbe, 0xeb, 0x64,
-       0xad, 0xbb, 0xc4, 0x2c, 0x80, 0x16, 0x71, 0x6b, 0x3e, 0xc6, 0xa6, 0x14,
-       0x52, 0xbe, 0xaf, 0xe7, 0xfd, 0x27, 0xdc, 0x9c, 0x6d, 0xe9, 0x5a, 0x4a,
-       0xaa, 0xcd, 0x7e, 0xe0, 0xed, 0xd4, 0x8a, 0x8b, 0xa6, 0x56, 0xf2, 0xfc,
-       0x73, 0xae, 0x23, 0x03, 0x86, 0xf8, 0xfe, 0x9c, 0xb3, 0x33, 0x7d, 0x48,
-       0x4e, 0x02, 0x6f, 0x03, 0xf8, 0xc4, 0xd2, 0xf3, 0xa4, 0x8f, 0x74, 0x92,
-       0xe4, 0x8a, 0x56, 0x1c, 0x8a, 0xe8, 0x93, 0x0c, 0xe9, 0x2f, 0xaf, 0xe8,
-       0xa0, 0x73, 0x8b, 0x94, 0xeb, 0x96, 0x4c, 0xad, 0x6c, 0x5c, 0x7f, 0xd9,
-       0x7f, 0x71, 0x28, 0x25, 0xcf, 0x36, 0xb3, 0x47, 0x2a, 0x92, 0x90, 0x39,
-       0x2f, 0x23, 0x7a, 0x5e, 0x0a, 0x6e, 0x6e, 0x40, 0xce, 0x35, 0xd3, 0xf2,
-       0x5c, 0xd3, 0x4e, 0x57, 0x65, 0x93, 0x94, 0x53, 0x96, 0x9c, 0x6d, 0xa6,
-       0x70, 0x46, 0xff, 0x9c, 0x6e, 0xdb, 0x56, 0x15, 0x6b, 0xab, 0xcd, 0x97,
-       0xf8, 0xef, 0x5f, 0xac, 0xe9, 0x9c, 0x82, 0xa9, 0x80, 0xee, 0x70, 0x2d,
-       0xcf, 0xa1, 0xd6, 0xaa, 0xb3, 0x04, 0x6b, 0xa5, 0x32, 0x9d, 0xc3, 0x5c,
-       0x73, 0x34, 0xe4, 0xef, 0x16, 0x9c, 0x97, 0x4f, 0x4b, 0xaa, 0x9e, 0x01,
-       0xde, 0xb0, 0xff, 0xcf, 0xc0, 0x37, 0x80, 0xf3, 0x5e, 0xab, 0x7e, 0xee,
-       0xa2, 0xa4, 0x74, 0xd9, 0x99, 0x2e, 0x0b, 0x78, 0xdb, 0xec, 0xc4, 0x98,
-       0xf4, 0xf9, 0xfe, 0x7e, 0x47, 0xac, 0xaa, 0xd3, 0x03, 0x98, 0x8c, 0x54,
-       0x9d, 0x6e, 0xe0, 0x69, 0x13, 0xcb, 0xe6, 0xb9, 0xb8, 0xd7, 0x66, 0xcc,
-       0xfb, 0x5d, 0x46, 0xde, 0xf7, 0xa7, 0x73, 0xd2, 0x1d, 0xcc, 0xed, 0x56,
-       0x38, 0xa6, 0x26, 0x34, 0xac, 0xfb, 0x05, 0x69, 0x4e, 0x24, 0xf3, 0xec,
-       0xf3, 0x99, 0x13, 0x77, 0xfe, 0xda, 0x90, 0x96, 0x34, 0x68, 0xb9, 0x26,
-       0xec, 0x83, 0xff, 0x1e, 0xf8, 0xe0, 0x7c, 0x06, 0x63, 0xed, 0x3a, 0xe0,
-       0x19, 0xae, 0x0a, 0xf7, 0xe8, 0x93, 0xa5, 0x94, 0xe8, 0x57, 0x9c, 0xde,
-       0x70, 0x5d, 0x37, 0x68, 0x8d, 0xf4, 0xa0, 0x5f, 0xe6, 0x16, 0xc9, 0xeb,
-       0x1a, 0x64, 0x83, 0xe7, 0x8d, 0x15, 0xad, 0xd0, 0x3c, 0x82, 0xbe, 0x29,
-       0xd3, 0xb6, 0x7f, 0x6e, 0xce, 0x99, 0xd7, 0x8a, 0xa7, 0x4e, 0x6a, 0xa5,
-       0x53, 0x2f, 0x68, 0x7b, 0x9b, 0x2f, 0x74, 0x49, 0x47, 0x16, 0xa7, 0x4e,
-       0xc8, 0x93, 0x9e, 0x26, 0xa4, 0x73, 0x09, 0xbc, 0x2b, 0x58, 0x15, 0x31,
-       0xed, 0x6e, 0x6d, 0x1f, 0xf0, 0xb4, 0xd9, 0x7f, 0xd2, 0x29, 0xdd, 0x86,
-       0x6c, 0xb2, 0xa3, 0xb5, 0x29, 0xf9, 0x33, 0xd0, 0x74, 0xc1, 0x49, 0x91,
-       0x5f, 0x3d, 0x01, 0x4c, 0x44, 0x07, 0xf5, 0x8a, 0x3a, 0xa5, 0x17, 0x4a,
-       0xc7, 0xff, 0xbc, 0xaf, 0x3a, 0xb2, 0x85, 0x6b, 0xa0, 0xff, 0xd6, 0xfd,
-       0xd3, 0xb6, 0xdb, 0x6b, 0x4a, 0xc5, 0xd2, 0x25, 0x6b, 0x15, 0xe5, 0x3a,
-       0x99, 0x73, 0x44, 0x8a, 0x35, 0xec, 0x69, 0x9b, 0xe0, 0x8d, 0x0d, 0xde,
-       0xec, 0x3c, 0x32, 0xa8, 0xff, 0x96, 0x64, 0xfa, 0x2b, 0x9a, 0x19, 0xf2,
-       0x71, 0x49, 0x6e, 0x51, 0xf0, 0x7a, 0xde, 0x81, 0x7e, 0x76, 0xb0, 0x8f,
-       0x7d, 0x13, 0x6a, 0x5f, 0x23, 0x6f, 0xa7, 0x97, 0x45, 0x34, 0x3d, 0xbf,
-       0x1b, 0xf8, 0xa8, 0xb7, 0x5c, 0xf7, 0x04, 0x68, 0x24, 0xed, 0xec, 0xdb,
-       0x80, 0x49, 0x88, 0xeb, 0x74, 0xb5, 0xd0, 0x49, 0x79, 0x93, 0xd7, 0xe4,
-       0x9d, 0x3a, 0xa7, 0xb6, 0x76, 0xce, 0x5f, 0xf9, 0x9b, 0x46, 0x4d, 0xf9,
-       0xa1, 0x3a, 0x2f, 0x6d, 0x8c, 0xeb, 0x52, 0xa1, 0x4e, 0x24, 0xa0, 0x47,
-       0xa2, 0x95, 0x1d, 0x6b, 0x15, 0x57, 0x59, 0x44, 0x37, 0xf2, 0x9d, 0x52,
-       0x54, 0xf4, 0x8d, 0x61, 0x2f, 0xda, 0x1e, 0x6c, 0xc8, 0xe6, 0x59, 0x38,
-       0x97, 0x87, 0x8d, 0x67, 0xd9, 0x97, 0xf2, 0x02, 0xed, 0x9d, 0xb4, 0x9d,
-       0xcf, 0xaa, 0x7f, 0x8e, 0x45, 0x5d, 0x3c, 0xd6, 0x03, 0xda, 0x38, 0x86,
-       0x1d, 0xda, 0x78, 0x3f, 0xa2, 0x89, 0x3b, 0x36, 0x08, 0xfe, 0x70, 0x9d,
-       0x9d, 0x81, 0x9c, 0x0b, 0x2e, 0xf6, 0x74, 0x9d, 0xdf, 0x50, 0x3c, 0xe8,
-       0xc5, 0x79, 0x06, 0xe7, 0xc9, 0xaf, 0x0e, 0xe8, 0xb6, 0x26, 0x65, 0x27,
-       0x9b, 0xa1, 0xdc, 0x03, 0xda, 0x75, 0xd9, 0x74, 0x63, 0x2b, 0xed, 0x91,
-       0xac, 0xa8, 0x87, 0xa6, 0x24, 0x47, 0xb9, 0x96, 0xeb, 0xb8, 0x3e, 0x3b,
-       0x26, 0xfa, 0xaf, 0x7c, 0x6b, 0xdd, 0x59, 0x6d, 0xd9, 0x31, 0x0f, 0x1a,
-       0x02, 0xde, 0x82, 0x27, 0x9f, 0xb6, 0x96, 0x7c, 0xdd, 0xc8, 0x3f, 0xae,
-       0x6d, 0x5d, 0x07, 0x9d, 0xe8, 0x27, 0x0d, 0x27, 0x3a, 0x03, 0x5b, 0x8b,
-       0x68, 0x8a, 0x64, 0xa3, 0x85, 0x38, 0x3e, 0xe9, 0x1c, 0x5c, 0x0f, 0x1f,
-       0xe0, 0xc1, 0x07, 0xc0, 0xaf, 0x3d, 0xeb, 0xc1, 0xfe, 0x3d, 0xfa, 0x8c,
-       0x8c, 0xbc, 0x38, 0x04, 0x1f, 0xb7, 0xe6, 0x63, 0xd0, 0xc6, 0xd1, 0xd7,
-       0xc5, 0x80, 0x8f, 0x99, 0xad, 0xeb, 0xb0, 0x59, 0xf0, 0x78, 0x85, 0x73,
-       0xb0, 0xed, 0x95, 0x12, 0x9e, 0xb6, 0x54, 0x1b, 0xd4, 0xab, 0xc8, 0x97,
-       0xd2, 0xe7, 0xa4, 0xe1, 0x5f, 0xe8, 0x77, 0xe8, 0x57, 0xb8, 0xd6, 0xf7,
-       0x4b, 0x0e, 0x61, 0x7d, 0x99, 0x70, 0x68, 0x43, 0x9d, 0xa2, 0x27, 0x2b,
-       0xda, 0xc1, 0x21, 0xd8, 0xd6, 0xf5, 0x6d, 0xa0, 0x95, 0x36, 0x76, 0x8d,
-       0x48, 0x3b, 0xf7, 0xfb, 0x69, 0x57, 0xf0, 0xef, 0xee, 0x36, 0x61, 0x0d,
-       0x9f, 0xef, 0x86, 0x63, 0x2d, 0xf4, 0x2d, 0x7c, 0x9f, 0xcd, 0x14, 0xa4,
-       0x3f, 0x1c, 0xb3, 0xbf, 0x4a, 0xaf, 0xa3, 0xdf, 0x98, 0x90, 0x1d, 0x27,
-       0x03, 0x9f, 0xb8, 0x63, 0xc9, 0x12, 0xfb, 0x64, 0x40, 0xe3, 0x8e, 0x33,
-       0x91, 0x6f, 0x7c, 0x1f, 0xf0, 0xa0, 0xcf, 0x5b, 0x8d, 0x03, 0x68, 0x3f,
-       0xd3, 0x60, 0x2a, 0x98, 0xdb, 0xc8, 0x0b, 0xfa, 0x63, 0xda, 0x9b, 0xd5,
-       0x6a, 0x6f, 0x7b, 0x60, 0x6f, 0x4e, 0xbb, 0x64, 0x9d, 0xbf, 0x87, 0xbd,
-       0x7d, 0xc3, 0xd1, 0xc0, 0x1b, 0x91, 0x8b, 0xb5, 0x34, 0x6c, 0xdd, 0x4c,
-       0xbf, 0x26, 0x3b, 0x33, 0xb3, 0xa2, 0xc9, 0x09, 0xce, 0x35, 0x30, 0xa7,
-       0x7c, 0x71, 0xe0, 0x0b, 0x2e, 0x1b, 0x4f, 0x81, 0x2e, 0xdf, 0x9f, 0x05,
-       0xce, 0xf2, 0x88, 0x11, 0xda, 0x56, 0x34, 0x6f, 0xdd, 0xef, 0xda, 0xee,
-       0xaf, 0x19, 0x52, 0x19, 0x6e, 0x93, 0xec, 0xf0, 0x12, 0x70, 0x4f, 0x3b,
-       0x81, 0x1d, 0x53, 0xd7, 0x97, 0x81, 0x7f, 0xce, 0x1b, 0x82, 0x1e, 0xd3,
-       0x0e, 0x40, 0x17, 0xf0, 0x2f, 0x03, 0xff, 0x5c, 0xb3, 0x4d, 0xbe, 0x6e,
-       0x46, 0xb1, 0x32, 0x3a, 0x4f, 0x37, 0x96, 0x45, 0xfb, 0x1e, 0x96, 0x2f,
-       0x7a, 0x49, 0xcd, 0x3d, 0x46, 0xff, 0x5a, 0x1d, 0x86, 0x9d, 0x68, 0x55,
-       0x87, 0x7b, 0x1b, 0xb2, 0xbc, 0xba, 0x46, 0x0a, 0xd5, 0xc0, 0x06, 0x0b,
-       0xee, 0x50, 0x25, 0x6d, 0x28, 0x5f, 0x22, 0xb2, 0x0f, 0xb6, 0xb7, 0x6c,
-       0x73, 0xcc, 0xf9, 0x60, 0x6e, 0xbc, 0xd6, 0x0f, 0x9f, 0xc8, 0xf1, 0x7b,
-       0xfe, 0xb4, 0x13, 0xcc, 0x7d, 0xa1, 0x76, 0x57, 0x37, 0xfd, 0x2e, 0xe2,
-       0x44, 0xa6, 0xea, 0xfc, 0xbb, 0x0f, 0xfd, 0x5d, 0x07, 0xf3, 0xd1, 0x78,
-       0xb2, 0xe3, 0x81, 0xce, 0x8a, 0xb6, 0xdf, 0xd6, 0xfb, 0xdb, 0x43, 0x1f,
-       0xb6, 0x1f, 0x93, 0x7b, 0x6b, 0xd5, 0xbe, 0x76, 0x79, 0xcf, 0x60, 0x1c,
-       0xbd, 0x22, 0x62, 0xba, 0xb5, 0x5d, 0xe0, 0x47, 0xb5, 0xb7, 0x65, 0x2e,
-       0x51, 0xaa, 0xf9, 0x72, 0xc1, 0x09, 0x60, 0x30, 0xee, 0x2c, 0xd6, 0xf4,
-       0xfe, 0x84, 0xac, 0x8e, 0x2d, 0xc2, 0xac, 0xc8, 0xae, 0xe1, 0x65, 0x51,
-       0xb0, 0x7d, 0x89, 0x35, 0xd8, 0x54, 0xa9, 0x56, 0xed, 0x6d, 0x19, 0xa7,
-       0x8b, 0xc0, 0xa5, 0xef, 0x59, 0x85, 0x1d, 0x58, 0x83, 0xdd, 0x2a, 0x99,
-       0x5e, 0xc2, 0xeb, 0xfd, 0x9b, 0xd7, 0x70, 0x67, 0x42, 0x7a, 0xfa, 0x36,
-       0xaf, 0xe1, 0xb0, 0x89, 0xb3, 0x65, 0x3c, 0x4c, 0x9c, 0x3b, 0xd6, 0x70,
-       0x8e, 0xac, 0xa7, 0xe7, 0xb0, 0xc0, 0x07, 0x25, 0xda, 0xf3, 0xb2, 0xe7,
-       0x62, 0x6d, 0x70, 0xe2, 0x8b, 0x82, 0x58, 0x37, 0xb2, 0x29, 0xf4, 0xc9,
-       0xe6, 0x1e, 0x17, 0xbc, 0x32, 0x85, 0x3e, 0x4e, 0x93, 0x2a, 0xe4, 0x7c,
-       0x7f, 0x43, 0xf6, 0x5c, 0x68, 0x98, 0xa1, 0x2e, 0x51, 0x27, 0xde, 0x86,
-       0x8d, 0x75, 0x4e, 0x99, 0x88, 0xc3, 0xe7, 0x94, 0x8d, 0xc9, 0x44, 0xb5,
-       0x26, 0x95, 0xed, 0xf9, 0x27, 0x7c, 0xe8, 0xe2, 0x94, 0x05, 0x3f, 0x5a,
-       0x94, 0xce, 0x31, 0x37, 0x87, 0xf9, 0x06, 0x6d, 0x0b, 0x7e, 0x05, 0xb0,
-       0xd0, 0xb5, 0x84, 0x31, 0xbf, 0xf3, 0x55, 0xd7, 0xe0, 0x3e, 0x19, 0xe4,
-       0x4d, 0x89, 0x84, 0x3e, 0x7f, 0xd5, 0xa7, 0x9e, 0x4d, 0x8f, 0x5c, 0x45,
-       0x9e, 0x62, 0xc1, 0x57, 0xc2, 0x7f, 0x40, 0xdf, 0x67, 0x9b, 0x82, 0xb8,
-       0xfe, 0x40, 0x4f, 0x60, 0x63, 0x47, 0xb7, 0x06, 0x4f, 0x31, 0xe9, 0x9b,
-       0xa7, 0x73, 0xcc, 0x01, 0xda, 0x13, 0x6e, 0x6e, 0x7c, 0x9b, 0x71, 0xe6,
-       0xc0, 0x36, 0xfd, 0x4c, 0x65, 0x9b, 0x0e, 0x9f, 0x0e, 0x9b, 0xd2, 0xdd,
-       0x1c, 0xfa, 0x67, 0x22, 0x1b, 0x4a, 0xc3, 0x86, 0xde, 0x56, 0x39, 0xc8,
-       0xb9, 0xe6, 0x29, 0xd8, 0xab, 0xa2, 0x55, 0x26, 0x90, 0x13, 0xe8, 0xa3,
-       0xef, 0x43, 0x4f, 0x70, 0x16, 0xf8, 0xc0, 0x02, 0xb8, 0xa4, 0x8f, 0xbe,
-       0x11, 0xda, 0x33, 0xfb, 0xef, 0xf8, 0x41, 0x7c, 0xf8, 0x7c, 0xb8, 0xff,
-       0x3f, 0x75, 0x07, 0x3e, 0x20, 0xc2, 0x45, 0x3c, 0xc3, 0xda, 0x04, 0xf2,
-       0x99, 0x89, 0xa6, 0xa9, 0xd1, 0x9f, 0x17, 0x3d, 0xe6, 0x21, 0xcc, 0x41,
-       0x1e, 0x0b, 0xfd, 0x22, 0x73, 0x8f, 0xce, 0x90, 0xa7, 0xb9, 0x28, 0xce,
-       0x29, 0x7b, 0x43, 0xcc, 0xc9, 0x94, 0x9d, 0x36, 0xe5, 0x93, 0xa7, 0x73,
-       0x9d, 0x58, 0x87, 0xb9, 0x26, 0xce, 0x0d, 0xbf, 0x84, 0x5c, 0x06, 0x6b,
-       0xce, 0x63, 0x7d, 0x7b, 0x68, 0xf3, 0x17, 0xa5, 0x0c, 0x9f, 0x6a, 0xda,
-       0x7c, 0x9f, 0xeb, 0x91, 0x0e, 0x8c, 0x1b, 0xd8, 0x0b, 0x7e, 0xc2, 0x50,
-       0x7c, 0x46, 0x2c, 0x48, 0x5d, 0xc7, 0x1c, 0x09, 0x6b, 0x33, 0x58, 0x4b,
-       0xbf, 0xcb, 0xb5, 0xcf, 0x82, 0x0e, 0x8c, 0x1b, 0x84, 0xa1, 0x8f, 0x12,
-       0xdf, 0xcd, 0x6d, 0x86, 0x26, 0xf9, 0xe7, 0x0c, 0x3b, 0x5a, 0x1b, 0xe1,
-       0xdd, 0xb8, 0x96, 0xf9, 0x09, 0x71, 0xf7, 0x84, 0xf1, 0x7f, 0x5c, 0x0a,
-       0xcd, 0x02, 0x7e, 0x22, 0xd3, 0xc7, 0x90, 0x8f, 0xd9, 0x6d, 0x88, 0x55,
-       0x9c, 0xdf, 0x6a, 0x05, 0x67, 0x8d, 0xe0, 0xee, 0xef, 0x5b, 0x3f, 0xfe,
-       0x42, 0x72, 0xcd, 0x47, 0xd2, 0xc2, 0xa4, 0x80, 0x18, 0x01, 0x5e, 0x65,
-       0xa6, 0x98, 0xc3, 0x15, 0x1b, 0x4a, 0xa6, 0x98, 0x1b, 0x83, 0x5f, 0x0c,
-       0xf2, 0xa2, 0x73, 0xde, 0x46, 0xd9, 0x59, 0xe0, 0x77, 0x01, 0x3c, 0xce,
-       0x40, 0x87, 0xc6, 0x01, 0x2b, 0x87, 0x81, 0x83, 0xf1, 0xd7, 0xd1, 0xf3,
-       0x49, 0x29, 0x5b, 0xcc, 0x13, 0xda, 0x49, 0x67, 0x81, 0xf6, 0xaf, 0xe7,
-       0x37, 0x63, 0x8e, 0xfd, 0x7b, 0x7b, 0x02, 0x99, 0x75, 0x71, 0x3c, 0xa1,
-       0xe7, 0x7b, 0x36, 0xcc, 0x7f, 0xbf, 0x2b, 0xa0, 0x4d, 0x8d, 0x31, 0xff,
-       0xf2, 0x86, 0xf1, 0xef, 0x25, 0xd7, 0x8f, 0xef, 0xda, 0x16, 0xea, 0x20,
-       0xfa, 0x8f, 0x85, 0xf4, 0x82, 0xb6, 0x55, 0x5a, 0xa3, 0x9c, 0x57, 0x16,
-       0x74, 0xe4, 0x7f, 0x6e, 0x6e, 0x27, 0x62, 0x7d, 0x46, 0x4a, 0x4d, 0xd0,
-       0xbd, 0x1a, 0xcb, 0x56, 0xd7, 0x54, 0xd6, 0xd6, 0x04, 0xbe, 0xbe, 0xd4,
-       0xf4, 0x91, 0x3b, 0xb5, 0xc6, 0xbd, 0x61, 0xf4, 0x2b, 0xd8, 0xa7, 0x20,
-       0xd3, 0xde, 0x85, 0x82, 0x6e, 0x1f, 0x09, 0xf2, 0x3e, 0xfb, 0x9b, 0x5a,
-       0x69, 0x99, 0xf9, 0x20, 0xec, 0xc9, 0x56, 0xf9, 0x3f, 0xe2, 0xca, 0x51,
-       0xad, 0x70, 0xea, 0x38, 0xf2, 0xc1, 0x15, 0xfc, 0x4e, 0xe3, 0xd7, 0xc0,
-       0x2f, 0xca, 0xc3, 0x9f, 0x41, 0x1e, 0xaf, 0x7c, 0x2c, 0xe2, 0x41, 0xb0,
-       0xff, 0x1b, 0x2b, 0xd0, 0xb3, 0xe3, 0x29, 0xf9, 0x86, 0xad, 0xf7, 0xe9,
-       0x81, 0x5f, 0x29, 0x20, 0x8f, 0xb5, 0xde, 0x96, 0xdf, 0x0e, 0xf3, 0x22,
-       0x91, 0xd7, 0x16, 0xc0, 0xc7, 0x91, 0xfd, 0xa1, 0xce, 0x16, 0xee, 0x75,
-       0x95, 0xff, 0x0c, 0xf3, 0x1e, 0xe4, 0x5f, 0x05, 0xb5, 0xea, 0x5b, 0xe0,
-       0x8d, 0x26, 0x6f, 0x41, 0x87, 0x5e, 0x5b, 0xe8, 0x00, 0x3d, 0xb6, 0x94,
-       0x27, 0x91, 0x2f, 0x68, 0x83, 0xd6, 0x26, 0xad, 0x03, 0x76, 0x0c, 0x1b,
-       0x57, 0x63, 0x49, 0xb4, 0xe5, 0x2f, 0xcd, 0x2c, 0xd5, 0x74, 0xac, 0x45,
-       0xee, 0x93, 0x43, 0x1f, 0xb2, 0xbf, 0xb2, 0x40, 0x38, 0x5d, 0x5e, 0x5f,
-       0x30, 0xe4, 0x4d, 0xe4, 0x52, 0x6f, 0xd9, 0x97, 0x66, 0x10, 0xb7, 0xfa,
-       0x11, 0x23, 0x50, 0x8b, 0xec, 0xa4, 0x9f, 0xde, 0x61, 0xe2, 0x59, 0xc2,
-       0x6f, 0x1f, 0x72, 0xc1, 0x8f, 0x86, 0xf9, 0xb8, 0xf5, 0xa4, 0x2d, 0x01,
-       0x18, 0xae, 0x37, 0x41, 0x5b, 0x37, 0xe4, 0x9f, 0xb5, 0xa6, 0xe4, 0xf5,
-       0x1e, 0x95, 0xaf, 0x68, 0x9c, 0x0f, 0x7c, 0xd3, 0x87, 0xe7, 0xc9, 0x67,
-       0x03, 0x3a, 0xce, 0x31, 0xdf, 0xd1, 0x87, 0x12, 0x5f, 0x76, 0xac, 0x80,
-       0xc3, 0x5c, 0x59, 0x08, 0xfa, 0xd1, 0x9c, 0x68, 0x51, 0x1c, 0xa3, 0x6f,
-       0x2c, 0xc1, 0x4e, 0x38, 0x9e, 0x10, 0x25, 0x83, 0x75, 0xf2, 0x94, 0x84,
-       0x99, 0x3f, 0x3b, 0x33, 0x67, 0x53, 0xae, 0xf0, 0x71, 0xb5, 0x48, 0xae,
-       0x94, 0x51, 0xbb, 0x54, 0x17, 0xbe, 0x09, 0xb9, 0xea, 0x61, 0xbe, 0x0f,
-       0x1b, 0x3f, 0x4e, 0xf9, 0xa2, 0xfe, 0x5b, 0x40, 0xee, 0xb3, 0x20, 0xc9,
-       0xa0, 0x5e, 0x39, 0x8a, 0x3c, 0x1f, 0xf2, 0xab, 0x1d, 0x07, 0x0e, 0xd8,
-       0x69, 0x6d, 0x05, 0x4f, 0xd4, 0x16, 0xb5, 0xd3, 0x78, 0x0e, 0xe0, 0xd9,
-       0xa0, 0x6e, 0x86, 0xb9, 0xc6, 0x87, 0xe8, 0x81, 0x3d, 0x95, 0x68, 0x4f,
-       0xf2, 0xfd, 0x66, 0x5e, 0xbe, 0xdb, 0x1c, 0x93, 0xe7, 0x9b, 0x39, 0xf9,
-       0xbb, 0xa6, 0x23, 0xdf, 0x69, 0x8e, 0xc8, 0xb7, 0x9b, 0xc3, 0xac, 0xc9,
-       0x90, 0x37, 0x65, 0x98, 0x37, 0xc9, 0xbd, 0xde, 0xad, 0xb0, 0x77, 0xca,
-       0xff, 0xd2, 0x4c, 0xa1, 0x31, 0x28, 0xe5, 0x63, 0xf0, 0xcf, 0xce, 0xcd,
-       0xac, 0x25, 0xe5, 0x11, 0x87, 0x35, 0x41, 0x1b, 0xdf, 0xa3, 0xce, 0x84,
-       0xff, 0x86, 0x3f, 0x9b, 0x4a, 0x65, 0x4f, 0xbb, 0x46, 0x47, 0xe8, 0x03,
-       0x6e, 0x49, 0x4a, 0x07, 0xf6, 0x82, 0x0f, 0x5c, 0x7a, 0x1a, 0x36, 0xa0,
-       0x6a, 0x9a, 0x04, 0xfc, 0x0d, 0x73, 0x01, 0x93, 0x76, 0x8c, 0x3a, 0x30,
-       0x9b, 0x71, 0x0d, 0xd6, 0x77, 0xb4, 0x67, 0x03, 0x81, 0x83, 0x70, 0xfb,
-       0x2c, 0xca, 0xcd, 0xb4, 0xe9, 0x57, 0x0b, 0xa1, 0x8f, 0x4b, 0x84, 0x7a,
-       0x69, 0x61, 0xfe, 0xf1, 0xd0, 0x27, 0x6f, 0xdc, 0x07, 0xf1, 0x02, 0xf9,
-       0x64, 0xb0, 0x8e, 0xb0, 0x5a, 0x08, 0xdb, 0x17, 0xce, 0x75, 0x82, 0xdf,
-       0x8e, 0x94, 0xbd, 0x37, 0x35, 0xe6, 0xd9, 0xc8, 0x77, 0x30, 0x1e, 0xc1,
-       0xf8, 0x4a, 0x38, 0xfe, 0x9c, 0x4c, 0x2f, 0x0a, 0x68, 0xfd, 0x89, 0x56,
-       0x54, 0xe3, 0x31, 0x8c, 0x75, 0x8c, 0x0d, 0xd6, 0x02, 0x68, 0x37, 0x27,
-       0xa9, 0xeb, 0xba, 0x4d, 0x5f, 0x38, 0x19, 0xfa, 0xc3, 0x82, 0x1c, 0xf6,
-       0x06, 0x0b, 0x57, 0x11, 0x33, 0xb4, 0xb6, 0x28, 0xff, 0xd9, 0x0e, 0xbe,
-       0xf8, 0xfe, 0xed, 0xac, 0xb9, 0x93, 0xa6, 0x7c, 0x7b, 0x3e, 0x6b, 0x3d,
-       0xa4, 0x7f, 0x0d, 0x67, 0xf2, 0xfd, 0x83, 0x76, 0xf6, 0xc8, 0x94, 0xde,
-       0x25, 0xdf, 0x3d, 0xca, 0xd8, 0x7b, 0x76, 0xe6, 0x07, 0xd0, 0xbd, 0xfa,
-       0x4a, 0xbb, 0xd4, 0xeb, 0xa6, 0x5c, 0x19, 0x1d, 0x04, 0x9d, 0x96, 0xd4,
-       0x1b, 0x49, 0xe4, 0x73, 0x9b, 0x65, 0xb6, 0x5f, 0x19, 0x18, 0xfc, 0xf4,
-       0xb0, 0xf2, 0xd3, 0xae, 0x8d, 0x67, 0xe3, 0xe7, 0x3d, 0xeb, 0xcf, 0x5c,
-       0x02, 0xfd, 0xd0, 0xeb, 0xe4, 0x76, 0x25, 0xe7, 0xb2, 0x37, 0x68, 0x95,
-       0x75, 0xc4, 0x2e, 0x73, 0xd0, 0xba, 0x57, 0xff, 0x2f, 0xff, 0xf3, 0x26,
-       0x65, 0xf7, 0xaa, 0xaa, 0x61, 0x54, 0xac, 0xc3, 0x7e, 0x4b, 0x2b, 0x2f,
-       0x83, 0x16, 0xf8, 0xd8, 0xc6, 0xf6, 0x70, 0x9c, 0x51, 0xbc, 0x38, 0xdb,
-       0xe8, 0x90, 0xef, 0xd4, 0xb7, 0xc8, 0x72, 0x9d, 0xef, 0xdb, 0x65, 0xa9,
-       0x3e, 0x78, 0xb5, 0x4f, 0xef, 0x97, 0xf3, 0xd7, 0x5c, 0x6f, 0xdd, 0xa3,
-       0x23, 0x37, 0x98, 0xfc, 0x40, 0x7e, 0x39, 0xda, 0x23, 0x3f, 0xfe, 0x72,
-       0xf6, 0x99, 0x3f, 0xd5, 0x61, 0x03, 0xa3, 0x9d, 0xb4, 0x6d, 0xf4, 0x39,
-       0x9f, 0xbd, 0x5a, 0xd0, 0xa9, 0xdb, 0x3f, 0x02, 0x4f, 0xb3, 0x0b, 0x81,
-       0x1d, 0x10, 0x37, 0xf1, 0x42, 0x37, 0xec, 0xef, 0x01, 0x27, 0xde, 0x35,
-       0x06, 0x81, 0xeb, 0x7b, 0x8a, 0x17, 0xb7, 0x3b, 0xd9, 0xab, 0x08, 0x49,
-       0xfe, 0x15, 0x7b, 0x70, 0x78, 0x87, 0xbe, 0x5d, 0xea, 0xe9, 0xeb, 0xad,
-       0xe7, 0xe0, 0xff, 0x0b, 0xa9, 0xec, 0x91, 0xcb, 0x72, 0x76, 0xe6, 0xa2,
-       0x4d, 0xfd, 0xa7, 0xdf, 0x78, 0x09, 0xb9, 0xa7, 0x25, 0x0b, 0x0d, 0xfa,
-       0x4b, 0xe2, 0x62, 0xfe, 0xbf, 0xcb, 0x3a, 0xac, 0x33, 0x4f, 0xc0, 0x3b,
-       0xcc, 0x1b, 0xbf, 0x4e, 0x39, 0xb7, 0x11, 0x76, 0xb8, 0xa0, 0xff, 0x62,
-       0x03, 0x8f, 0x06, 0xad, 0xbd, 0x3a, 0xf7, 0xfb, 0x37, 0xec, 0xfb, 0x0e,
-       0x68, 0x1d, 0x04, 0x2c, 0x62, 0x66, 0xba, 0x75, 0x8f, 0x57, 0xd4, 0x1e,
-       0xc7, 0x1a, 0xc8, 0xf5, 0x56, 0xf7, 0xc0, 0x5c, 0x43, 0xc7, 0x39, 0x4d,
-       0x25, 0x97, 0x2b, 0xa3, 0xe4, 0xef, 0x9e, 0x5e, 0xe6, 0x99, 0x46, 0xfe,
-       0xaf, 0xfd, 0xa8, 0x7e, 0x7c, 0x7e, 0x7e, 0x12, 0xfe, 0xd9, 0xf7, 0x2f,
-       0xec, 0x1a, 0x04, 0x0d, 0xa8, 0x43, 0xd3, 0xe4, 0xf9, 0xd9, 0x19, 0x17,
-       0x38, 0x8a, 0x0a, 0xf7, 0x25, 0x59, 0x01, 0xee, 0x09, 0xf2, 0x01, 0xb8,
-       0xe7, 0x38, 0xaf, 0x64, 0x80, 0xf9, 0x46, 0x06, 0x78, 0x23, 0xfd, 0x4c,
-       0x42, 0xd7, 0x76, 0x5b, 0xb7, 0x07, 0xba, 0x9e, 0x60, 0x6c, 0x7b, 0x0e,
-       0xba, 0x57, 0x48, 0x52, 0x7f, 0xda, 0x7b, 0xd7, 0xf4, 0xa7, 0x15, 0x7f,
-       0xbb, 0x94, 0x16, 0x12, 0xc0, 0x6b, 0xca, 0x5c, 0x8e, 0x78, 0x31, 0xae,
-       0x53, 0xf7, 0x2b, 0xa1, 0xee, 0x77, 0x86, 0xb8, 0x17, 0xc1, 0x93, 0x6c,
-       0xa6, 0xae, 0xb3, 0x8e, 0xda, 0xa6, 0x6a, 0x5b, 0x03, 0x36, 0x5d, 0xae,
-       0xb1, 0x0e, 0xe5, 0xfd, 0xc8, 0xa5, 0x99, 0x69, 0xd4, 0xaa, 0xe5, 0xda,
-       0x88, 0x56, 0x6e, 0xda, 0x5a, 0xd9, 0xa3, 0xbe, 0xed, 0xb2, 0x2e, 0x28,
-       0x1e, 0xa7, 0x65, 0xa9, 0xf9, 0x4b, 0xbf, 0xba, 0x6b, 0x13, 0xfa, 0xd0,
-       0xfd, 0x09, 0xca, 0xf7, 0xb3, 0xa4, 0x0b, 0x41, 0x9c, 0xfc, 0x4e, 0xc9,
-       0xc9, 0x21, 0x14, 0xbd, 0xc8, 0xad, 0x4e, 0x0d, 0x11, 0x3f, 0xe8, 0x48,
-       0xa5, 0x64, 0xd9, 0xe3, 0x1e, 0x67, 0x67, 0xc8, 0xcb, 0xf2, 0x71, 0x4b,
-       0x0e, 0x2b, 0xf9, 0xbd, 0xac, 0x6c, 0xbb, 0xbc, 0x62, 0xc8, 0x74, 0x72,
-       0xd0, 0x7a, 0x58, 0xb2, 0x57, 0x2f, 0x18, 0xd9, 0x67, 0xa6, 0x60, 0xd7,
-       0x4b, 0x8b, 0x86, 0xb8, 0xaa, 0xde, 0xa2, 0x8c, 0xb2, 0x0b, 0xb0, 0xfc,
-       0xf0, 0xec, 0x7b, 0x5b, 0xce, 0xde, 0x2d, 0x2b, 0x4f, 0xff, 0x26, 0x7c,
-       0xce, 0x01, 0xc8, 0xc2, 0xcc, 0x1c, 0x42, 0x5e, 0xf1, 0xb4, 0x0c, 0x5a,
-       0x55, 0xe4, 0xc9, 0xe0, 0x3b, 0xda, 0x01, 0x65, 0x03, 0x17, 0x74, 0x8c,
-       0x07, 0xc8, 0x27, 0x8e, 0xaf, 0x95, 0x0b, 0xca, 0x96, 0xd2, 0xea, 0xdd,
-       0x0e, 0xe0, 0x08, 0xde, 0x71, 0xfc, 0x19, 0xd9, 0xa1, 0xde, 0xdd, 0xa9,
-       0xde, 0x55, 0xe9, 0x2b, 0x94, 0xfc, 0xbe, 0x82, 0x3d, 0xc9, 0xe3, 0x68,
-       0xbe, 0x4b, 0x02, 0x5b, 0x8a, 0xf8, 0x6e, 0xc9, 0xc1, 0x46, 0x4a, 0xbe,
-       0x84, 0xfa, 0xe7, 0x8e, 0xc6, 0x80, 0x94, 0x20, 0xc7, 0xe9, 0xdc, 0x83,
-       0xbd, 0x3c, 0x5b, 0x71, 0x25, 0xfb, 0x8c, 0xe8, 0xa4, 0xf5, 0x4e, 0x39,
-       0xe4, 0x45, 0xf4, 0x74, 0x86, 0xf4, 0x4d, 0x86, 0xe3, 0x44, 0x48, 0x43,
-       0x2b, 0xbe, 0x4e, 0xe0, 0x42, 0xac, 0xcf, 0x79, 0x21, 0x1e, 0xfa, 0x11,
-       0xd0, 0x3a, 0x99, 0x96, 0x15, 0x8f, 0x74, 0x6c, 0x91, 0x6a, 0x8a, 0xfd,
-       0x03, 0xd0, 0x37, 0xe2, 0xd9, 0xc4, 0x7c, 0x66, 0x1d, 0x8f, 0x1f, 0x6c,
-       0x54, 0xc0, 0x63, 0xf2, 0x97, 0xeb, 0x10, 0x23, 0x3e, 0x47, 0xf9, 0xed,
-       0x46, 0x2e, 0x6f, 0x07, 0xba, 0x69, 0xad, 0xed, 0x59, 0x3a, 0xde, 0x0d,
-       0x59, 0x71, 0xdf, 0x0e, 0x99, 0x84, 0xdd, 0x17, 0xeb, 0xdc, 0x7f, 0x12,
-       0x7a, 0x74, 0x51, 0xed, 0x5f, 0x5a, 0xe9, 0x0f, 0xe1, 0x09, 0xdb, 0xbd,
-       0x01, 0xb6, 0x5d, 0xf6, 0x2e, 0x58, 0x1f, 0x01, 0xff, 0xbb, 0x80, 0xd7,
-       0xe5, 0x44, 0x8e, 0xf0, 0xc4, 0x83, 0x75, 0xf5, 0xd4, 0x27, 0xe0, 0x49,
-       0xaa, 0xba, 0xbe, 0x58, 0x6f, 0x97, 0xe2, 0x42, 0x84, 0x8b, 0x78, 0x3e,
-       0x40, 0xdd, 0x7b, 0xb7, 0xc2, 0x35, 0xad, 0x70, 0xe1, 0x7d, 0x9d, 0x3e,
-       0xe7, 0x26, 0xc0, 0xa3, 0x76, 0xb7, 0x41, 0x5b, 0xb2, 0x4b, 0xaa, 0xaa,
-       0x76, 0xef, 0x50, 0xbe, 0xa6, 0x9a, 0xdc, 0x8c, 0xf7, 0x3e, 0xf6, 0xdc,
-       0x8d, 0x7c, 0xa6, 0x1b, 0x73, 0x99, 0x0d, 0x73, 0x1b, 0xe9, 0x4f, 0x6c,
-       0xa0, 0xff, 0xbf, 0x7b, 0x19, 0x52, 0xe6, 0x72, 0xc1, 0xba, 0x12, 0xd6,
-       0xcd, 0x1e, 0x87, 0x4d, 0x30, 0x4f, 0x4f, 0x31, 0x36, 0x5f, 0xa3, 0x68,
-       0x99, 0x5d, 0xf9, 0x29, 0xd6, 0xf5, 0x03, 0x36, 0x1a, 0x07, 0x7c, 0x78,
-       0x0a, 0x78, 0x8e, 0xd7, 0xd5, 0x1d, 0x05, 0x64, 0xf0, 0xbe, 0x3a, 0x7b,
-       0xb5, 0xfe, 0x69, 0x3c, 0xbb, 0xa6, 0x85, 0x5f, 0xe4, 0x15, 0xe9, 0x25,
-       0xad, 0xbc, 0x2f, 0x82, 0xbd, 0x39, 0xd0, 0xe3, 0xa4, 0x21, 0xa5, 0x1c,
-       0xe2, 0xba, 0xc7, 0xbb, 0x57, 0xda, 0xe5, 0x40, 0x50, 0x23, 0xd8, 0x8c,
-       0xef, 0xa6, 0x3a, 0xfb, 0xa1, 0x15, 0xde, 0xbf, 0x66, 0x78, 0x47, 0x37,
-       0x8c, 0xda, 0x5b, 0x1e, 0x5a, 0xb1, 0xe5, 0x6b, 0x8d, 0x61, 0x79, 0xb8,
-       0x91, 0xb5, 0xee, 0x81, 0x0f, 0x28, 0xaf, 0xde, 0xcb, 0x6e, 0x4b, 0xd2,
-       0x7f, 0x99, 0xc8, 0x3d, 0xdb, 0xec, 0x20, 0x17, 0xa9, 0xb2, 0x36, 0x3b,
-       0x9e, 0xe5, 0x7d, 0x8d, 0x55, 0x97, 0x8d, 0xf9, 0xca, 0xff, 0x65, 0xae,
-       0xc2, 0xfd, 0xe9, 0xaf, 0x91, 0x9b, 0x78, 0xc8, 0x4d, 0x3c, 0xe4, 0x26,
-       0x1e, 0x72, 0x13, 0x0f, 0xb9, 0x89, 0x87, 0xdc, 0xc4, 0x43, 0x6e, 0xe2,
-       0x21, 0x37, 0x41, 0x1d, 0x10, 0xd4, 0x07, 0xe3, 0xc8, 0xb9, 0xe1, 0xbf,
-       0xbc, 0x5b, 0xc2, 0xdc, 0x22, 0x8a, 0xcd, 0x9c, 0x3b, 0xbf, 0xc9, 0x0d,
-       0xea, 0x2b, 0xe5, 0x13, 0x0a, 0xcd, 0x89, 0x30, 0x07, 0xe2, 0x9a, 0x28,
-       0x76, 0x73, 0x9d, 0x8c, 0xb9, 0xa8, 0x3d, 0x0b, 0x93, 0xcc, 0x91, 0x82,
-       0x98, 0x15, 0xe4, 0xe7, 0xaf, 0x22, 0x4f, 0xca, 0x20, 0x4f, 0x1a, 0x40,
-       0x4e, 0xc4, 0x7b, 0xea, 0xe8, 0x2e, 0xa9, 0xa0, 0x1d, 0xf4, 0xc6, 0xb5,
-       0x2f, 0x79, 0xcc, 0xdf, 0xed, 0x4c, 0x59, 0xd7, 0x8f, 0xf7, 0x89, 0x2f,
-       0xc5, 0xd1, 0xaf, 0x23, 0x57, 0xfe, 0x4b, 0x75, 0x6f, 0x36, 0x31, 0x44,
-       0x99, 0xdf, 0xf7, 0x31, 0xf9, 0x72, 0xc4, 0xdf, 0xe0, 0xbe, 0x4f, 0x5f,
-       0x22, 0xff, 0x44, 0x7a, 0xcf, 0x80, 0xe1, 0x67, 0x12, 0x92, 0x3c, 0xb9,
-       0x05, 0x73, 0x96, 0xf4, 0xa9, 0x3b, 0x23, 0x88, 0xf2, 0xcc, 0x7f, 0x40,
-       0x5e, 0xb6, 0xe8, 0x67, 0x78, 0xb3, 0x40, 0xbc, 0xf4, 0xaf, 0xf5, 0x99,
-       0x62, 0xbd, 0xae, 0x74, 0xea, 0x60, 0xa3, 0x84, 0x3c, 0xca, 0xe8, 0x93,
-       0x0e, 0x13, 0xb5, 0x54, 0x84, 0x9b, 0x38, 0xdf, 0x4c, 0xaa, 0x1a, 0xe7,
-       0xcc, 0xaa, 0x3c, 0x21, 0x6b, 0xee, 0x53, 0x9f, 0xa9, 0x2e, 0x64, 0xd3,
-       0xac, 0x71, 0x0b, 0x56, 0x7d, 0xe6, 0x49, 0xe0, 0x58, 0x46, 0x6e, 0x60,
-       0xa8, 0xbd, 0xeb, 0x33, 0xb3, 0x0b, 0xc1, 0xbd, 0x55, 0x40, 0x03, 0xe3,
-       0x55, 0x87, 0x18, 0x4b, 0xc1, 0xfd, 0x95, 0xae, 0x60, 0x09, 0x47, 0x78,
-       0x13, 0x70, 0x94, 0xdb, 0x30, 0x60, 0x29, 0x3b, 0xd2, 0x50, 0x9f, 0xa9,
-       0xd4, 0x5b, 0x69, 0x20, 0x1e, 0xe2, 0x8d, 0xce, 0xc3, 0xb3, 0x24, 0x45,
-       0x3f, 0xe9, 0xfb, 0xe5, 0xd1, 0x81, 0xb0, 0xae, 0x44, 0x1d, 0x79, 0xcc,
-       0x0c, 0xf4, 0x5c, 0x8d, 0xff, 0x58, 0xc5, 0xa9, 0x8c, 0xce, 0x79, 0x3e,
-       0xf1, 0x2e, 0xf7, 0x28, 0xe6, 0x30, 0x5e, 0x8e, 0xd6, 0xea, 0xe1, 0xda,
-       0xae, 0x16, 0x7e, 0xb6, 0x85, 0xfb, 0x91, 0x26, 0x9e, 0xf3, 0x15, 0xec,
-       0x45, 0xba, 0xb8, 0xc6, 0x04, 0x6d, 0x90, 0xa5, 0xf7, 0xbf, 0xe5, 0x7d,
-       0xeb, 0x99, 0xc8, 0x53, 0x13, 0x30, 0x5c, 0x4f, 0x1c, 0x11, 0x0c, 0x5e,
-       0x9c, 0x09, 0xe0, 0xf4, 0xd5, 0x7b, 0xbe, 0x4f, 0xda, 0xb7, 0x95, 0xd6,
-       0x68, 0xff, 0x08, 0xcf, 0x70, 0x20, 0xb7, 0x55, 0x78, 0xf5, 0x7f, 0x7f,
-       0xe1, 0x09, 0x5d, 0xfc, 0xd0, 0x7d, 0xe9, 0x70, 0x4b, 0x8d, 0x1c, 0xdd,
-       0x3b, 0xb0, 0xfe, 0x67, 0x3d, 0xcf, 0xef, 0x03, 0xad, 0xf5, 0x69, 0x29,
-       0x8c, 0x65, 0xdb, 0xa4, 0x60, 0xb2, 0x56, 0x19, 0x0f, 0xc7, 0x5b, 0x11,
-       0xdb, 0x38, 0xbe, 0x15, 0xfc, 0x85, 0x2e, 0x3b, 0x1d, 0x61, 0xad, 0x94,
-       0x0c, 0xbe, 0xeb, 0x0c, 0xd3, 0x8e, 0x58, 0x6b, 0x6e, 0x0e, 0xe7, 0x22,
-       0x3b, 0xa2, 0x1f, 0x36, 0xc3, 0x39, 0xfa, 0x5b, 0x1d, 0xf5, 0x12, 0xfb,
-       0xc0, 0xb3, 0xdc, 0x6a, 0x4b, 0xd1, 0x33, 0x29, 0xa7, 0x17, 0x23, 0xbf,
-       0x05, 0x9f, 0x32, 0x64, 0x86, 0xbe, 0xbf, 0x13, 0xbe, 0xaf, 0x5b, 0xf6,
-       0xc2, 0x67, 0xed, 0x83, 0xcf, 0xda, 0x8f, 0x1a, 0x75, 0x7c, 0xa5, 0xf5,
-       0x3e, 0x97, 0x75, 0x71, 0x55, 0x0e, 0x29, 0xf9, 0x57, 0x7c, 0xc3, 0xfe,
-       0x00, 0x3a, 0xb0, 0x53, 0xe5, 0x7b, 0x81, 0x4e, 0xc0, 0xdf, 0x3a, 0x49,
-       0xe8, 0xc4, 0xc6, 0x7b, 0xe3, 0x61, 0xd8, 0x46, 0x47, 0x41, 0xc5, 0x86,
-       0x95, 0x80, 0xf7, 0xd5, 0x7a, 0xc0, 0x7b, 0xf8, 0x65, 0xe0, 0x37, 0xa5,
-       0xd2, 0xb0, 0xa4, 0x82, 0x7d, 0x2b, 0xd8, 0xb7, 0x82, 0xda, 0x72, 0xb6,
-       0xd1, 0xfa, 0xed, 0xaa, 0x2b, 0xa4, 0x9d, 0xb0, 0x51, 0xdf, 0x6a, 0x39,
-       0x7f, 0xf4, 0x3c, 0x02, 0xfe, 0x3f, 0x02, 0xfe, 0x1f, 0x46, 0x4d, 0xf5,
-       0x00, 0x6a, 0xaa, 0xfb, 0x50, 0x53, 0x1d, 0x42, 0x4d, 0x35, 0x85, 0x9a,
-       0xea, 0x6e, 0xf8, 0x8f, 0x3b, 0xe1, 0x3f, 0x26, 0xe1, 0x3f, 0x26, 0xd4,
-       0x9d, 0xd1, 0x41, 0x6f, 0xe3, 0x1d, 0x4a, 0xb4, 0x17, 0xdb, 0x1b, 0x22,
-       0x50, 0x81, 0xf2, 0xb1, 0x71, 0xa9, 0x37, 0x59, 0x5b, 0x39, 0xea, 0x3e,
-       0x6c, 0xda, 0x99, 0xd4, 0xa6, 0x90, 0xbf, 0xdf, 0x33, 0xc2, 0x9a, 0x2b,
-       0xa9, 0x15, 0x55, 0xcd, 0x95, 0x7d, 0xc1, 0x45, 0x8a, 0x84, 0xdc, 0x0f,
-       0x67, 0xce, 0x9e, 0x2e, 0x1a, 0x51, 0xbd, 0xd3, 0xbb, 0x5a, 0xef, 0x2c,
-       0xcf, 0xb3, 0xde, 0x79, 0x75, 0xb5, 0xde, 0x59, 0x9e, 0x67, 0xbd, 0xf3,
-       0xca, 0xba, 0x7a, 0xe7, 0xca, 0xd3, 0x97, 0xd6, 0xd5, 0x3b, 0x57, 0x9e,
-       0x7e, 0x29, 0x1c, 0x4b, 0xa8, 0x0f, 0x21, 0xad, 0x96, 0x83, 0x67, 0x4f,
-       0x98, 0x73, 0x34, 0xfb, 0xd6, 0xff, 0xdf, 0x74, 0xca, 0x96, 0x35, 0xb1,
-       0xff, 0x68, 0x6b, 0x50, 0x23, 0xb5, 0xce, 0x77, 0xb7, 0xcc, 0x5f, 0x56,
-       0xdf, 0x4b, 0xcb, 0xb5, 0xcd, 0xef, 0xc2, 0x03, 0xcb, 0xca, 0x10, 0xf3,
-       0xbc, 0x0f, 0x7c, 0x7e, 0xf3, 0x73, 0xf5, 0x0e, 0xf5, 0xcd, 0xcd, 0x55,
-       0xf9, 0x36, 0xec, 0x7c, 0xf4, 0xd1, 0xad, 0x81, 0x2f, 0x60, 0x3f, 0xa5,
-       0x05, 0xfe, 0xfd, 0x01, 0xe0, 0x01, 0xaf, 0x3d, 0x53, 0xdd, 0x07, 0x05,
-       0xe7, 0x0d, 0xee, 0xc6, 0xcd, 0xfc, 0xe5, 0x19, 0xe6, 0xd6, 0x55, 0x85,
-       0x9b, 0xf5, 0x23, 0x6b, 0xce, 0x28, 0x06, 0x44, 0xb8, 0x5e, 0x4d, 0x05,
-       0x74, 0xbb, 0xa8, 0x1d, 0xb9, 0x26, 0x1a, 0xb7, 0xd6, 0x9a, 0x9d, 0xe1,
-       0xbd, 0xdb, 0xe5, 0x20, 0xaf, 0x52, 0xf8, 0xcc, 0x10, 0xdf, 0xcf, 0xfd,
-       0xc0, 0xf7, 0x10, 0xde, 0x6a, 0x81, 0x1f, 0x47, 0xae, 0xc7, 0x7b, 0x1a,
-       0xe6, 0x6c, 0xa6, 0xbc, 0x33, 0xdf, 0x25, 0xff, 0x79, 0xd4, 0xf7, 0x27,
-       0x9c, 0xec, 0xf0, 0x25, 0xd4, 0x1e, 0x27, 0x69, 0x27, 0xa3, 0xa4, 0x73,
-       0x30, 0x33, 0x2b, 0xa9, 0x3e, 0xd2, 0x72, 0x5e, 0x3f, 0xac, 0x7d, 0x98,
-       0x6e, 0x3d, 0xdc, 0xe7, 0x1f, 0x5b, 0xf6, 0xc9, 0xb4, 0xec, 0x53, 0xa0,
-       0xcd, 0xd6, 0xef, 0xc0, 0x99, 0x2b, 0xdb, 0xaf, 0xb7, 0x52, 0x61, 0x5d,
-       0xf6, 0xf0, 0xe8, 0x66, 0x59, 0xe8, 0xcf, 0x9e, 0x7d, 0x05, 0xf9, 0x7a,
-       0x79, 0x14, 0x73, 0xa9, 0x41, 0xbc, 0xe3, 0x7c, 0xb6, 0x8e, 0x5c, 0xf4,
-       0x6c, 0x5d, 0xb6, 0x01, 0x3e, 0x5b, 0x11, 0xe1, 0x3c, 0xfb, 0x8a, 0xb6,
-       0x7a, 0xe8, 0x03, 0xd2, 0x17, 0x70, 0xe6, 0x29, 0xd4, 0x5f, 0x87, 0x83,
-       0x7b, 0xb4, 0x70, 0x9f, 0x1b, 0xb5, 0x20, 0x6f, 0xce, 0x69, 0x95, 0xf0,
-       0x0e, 0xf0, 0x2b, 0xf0, 0x17, 0x86, 0x4e, 0xd8, 0x77, 0x80, 0x5b, 0x93,
-       0xa5, 0xa3, 0x86, 0xba, 0x3b, 0x2d, 0x8f, 0x52, 0xd6, 0x7c, 0x7e, 0x14,
-       0xef, 0xa2, 0x33, 0xfd, 0x4d, 0x78, 0xa6, 0xd1, 0xb0, 0x6e, 0x8f, 0xce,
-       0x94, 0x90, 0xd7, 0xe7, 0x2d, 0xc0, 0x8e, 0x80, 0x1f, 0x25, 0x59, 0x69,
-       0x66, 0x3e, 0x05, 0x4f, 0xad, 0x85, 0x37, 0xe6, 0x06, 0x19, 0x46, 0x75,
-       0x0f, 0x78, 0x30, 0x91, 0x86, 0x1d, 0xde, 0xd7, 0x17, 0xdd, 0xe9, 0x1a,
-       0xb6, 0xae, 0x05, 0x75, 0x3c, 0xe7, 0x07, 0x60, 0x8b, 0x19, 0xd8, 0x27,
-       0x73, 0xa6, 0x12, 0x6b, 0x15, 0xda, 0x93, 0xe5, 0x1a, 0x59, 0x6b, 0x52,
-       0x86, 0x51, 0xef, 0xf0, 0xfc, 0x79, 0x59, 0x6e, 0x46, 0x34, 0xe4, 0x60,
-       0x8f, 0x63, 0xf8, 0x8d, 0xe0, 0x9d, 0x83, 0x1f, 0x6b, 0xa5, 0x82, 0x7c,
-       0x55, 0xe5, 0xe2, 0xc8, 0xb5, 0x87, 0x48, 0xdf, 0x01, 0xac, 0xa7, 0x3e,
-       0x53, 0x4f, 0x0f, 0x88, 0xdb, 0x4f, 0x5f, 0x91, 0x06, 0x6e, 0xc0, 0x78,
-       0xaf, 0xc1, 0xd6, 0x07, 0xf0, 0xcc, 0x5a, 0x65, 0xf2, 0x56, 0xe1, 0xf7,
-       0x7d, 0x23, 0xc7, 0x6f, 0x11, 0xe3, 0xe1, 0x78, 0xd0, 0xfa, 0x1d, 0xea,
-       0x5e, 0xfa, 0x5a, 0x39, 0xbb, 0x18, 0xc5, 0xc1, 0x19, 0xd8, 0x20, 0xef,
-       0x68, 0xc7, 0xc1, 0x17, 0x8e, 0xb5, 0x30, 0x1e, 0x62, 0x7e, 0xf9, 0xaf,
-       0x70, 0xee, 0xbc, 0x9c, 0x44, 0xfd, 0x2f, 0xfd, 0x7c, 0x66, 0x80, 0x7f,
-       0x4b, 0xa8, 0xef, 0xeb, 0xe1, 0x0d, 0x9b, 0xfd, 0x71, 0xd0, 0x67, 0xb6,
-       0xc0, 0x13, 0x26, 0xac, 0x4f, 0x04, 0xf1, 0x38, 0xed, 0xdf, 0xaa, 0xe7,
-       0xef, 0x96, 0x3f, 0x50, 0x67, 0xca, 0xcb, 0xa1, 0x45, 0xdf, 0x77, 0x73,
-       0x83, 0xc3, 0xcb, 0x92, 0x1d, 0x7e, 0x52, 0x76, 0x5b, 0x7b, 0x59, 0x8f,
-       0x59, 0xc4, 0xe3, 0xdf, 0xda, 0x96, 0xf7, 0xfd, 0x13, 0xa0, 0xfd, 0x07,
-       0x6a, 0x9f, 0xbb, 0x41, 0x3f, 0x78, 0xa5, 0x6a, 0x12, 0xd2, 0x0a, 0xde,
-       0xa4, 0x48, 0x6f, 0xa7, 0x1c, 0x6a, 0x3e, 0x1f, 0xca, 0xe6, 0x11, 0x71,
-       0xbd, 0xb7, 0x0d, 0xde, 0x6f, 0x97, 0x9b, 0x8f, 0x86, 0xb4, 0xe5, 0x41,
-       0x2f, 0xf6, 0x6f, 0xfe, 0x43, 0x8a, 0xbe, 0x81, 0x32, 0x77, 0x91, 0x35,
-       0xba, 0xa3, 0xcf, 0x40, 0x07, 0x3f, 0xce, 0x0f, 0x24, 0x65, 0xbd, 0x1f,
-       0x20, 0x5c, 0xf2, 0x23, 0x74, 0x85, 0x74, 0x88, 0xf2, 0x9f, 0x2a, 0x6e,
-       0x29, 0x7c, 0xc6, 0x06, 0x5f, 0xf0, 0xa4, 0x7a, 0x9e, 0x37, 0xe8, 0x9b,
-       0x18, 0xff, 0xa8, 0xc3, 0xdd, 0xf0, 0x7f, 0xd0, 0x41, 0xd8, 0x71, 0x71,
-       0x91, 0xf7, 0x13, 0x43, 0xea, 0x4e, 0xab, 0x04, 0xd9, 0x2e, 0xf1, 0x3b,
-       0x63, 0x2a, 0xc8, 0x27, 0x83, 0xfa, 0x2b, 0x43, 0x5f, 0x88, 0xf6, 0xb8,
-       0xf2, 0x93, 0x25, 0xf5, 0x5d, 0x31, 0x89, 0x35, 0x3e, 0x9e, 0xad, 0x7f,
-       0x27, 0xf1, 0xa3, 0x42, 0xf0, 0x77, 0x12, 0xe1, 0x37, 0xde, 0x7a, 0x90,
-       0x47, 0x3c, 0xd8, 0x30, 0x65, 0xaa, 0x11, 0xfd, 0xdd, 0x04, 0xe5, 0x60,
-       0x4b, 0xb9, 0x11, 0xe5, 0x0e, 0x7e, 0x50, 0xd3, 0xac, 0x93, 0xe5, 0xe3,
-       0x61, 0x4e, 0xc4, 0x1a, 0x80, 0x3c, 0xc4, 0x78, 0x39, 0x90, 0xdf, 0x92,
-       0xbe, 0x03, 0xf2, 0x03, 0xcf, 0x3d, 0x13, 0xb6, 0x94, 0x0e, 0xe3, 0xba,
-       0xc5, 0x1a, 0x33, 0xac, 0x7b, 0xb7, 0x4b, 0x75, 0x92, 0xef, 0x13, 0xf2,
-       0xda, 0xfc, 0x40, 0x70, 0x4f, 0x24, 0x89, 0xf0, 0x3d, 0xc7, 0x49, 0x29,
-       0xab, 0xf7, 0x77, 0x86, 0xf8, 0x50, 0xa7, 0xdd, 0x19, 0x8d, 0xd3, 0x90,
-       0x63, 0x00, 0x37, 0x8d, 0x58, 0xf6, 0x55, 0xc4, 0xb1, 0x69, 0xf0, 0xbd,
-       0x38, 0x51, 0x91, 0x6b, 0x6d, 0x4b, 0xc5, 0x7d, 0x37, 0x49, 0x1d, 0xa3,
-       0x7e, 0x11, 0xa6, 0x07, 0xb9, 0x2a, 0xce, 0x3b, 0x2a, 0x53, 0x46, 0xfe,
-       0xdd, 0xdb, 0xca, 0xb5, 0xac, 0x55, 0x90, 0xf7, 0x7d, 0xd7, 0xe4, 0xf8,
-       0xfc, 0x6d, 0x0f, 0x06, 0x77, 0xfe, 0xba, 0x9e, 0xbf, 0x78, 0x5b, 0x39,
-       0xe8, 0xe3, 0xcc, 0xef, 0x86, 0x7d, 0xc2, 0x19, 0xea, 0x7b, 0xec, 0x4f,
-       0x6e, 0x32, 0xe5, 0xc2, 0x4d, 0xbe, 0x7f, 0x0f, 0xbf, 0x09, 0x85, 0x75,
-       0xac, 0xa5, 0xea, 0xd8, 0x0e, 0x95, 0x8f, 0xb8, 0xa3, 0x19, 0xad, 0x04,
-       0xdb, 0x3d, 0xe9, 0xa1, 0xe6, 0xd1, 0xb3, 0x63, 0xe7, 0x75, 0x0b, 0xf1,
-       0x37, 0x9b, 0x39, 0x2e, 0xb9, 0x3e, 0x7e, 0x63, 0x9e, 0x73, 0xb8, 0x66,
-       0x5b, 0x70, 0xef, 0x75, 0x83, 0xab, 0x7c, 0xae, 0x48, 0x18, 0x87, 0x6e,
-       0x68, 0xb5, 0x8f, 0xd6, 0x3c, 0x93, 0x76, 0x21, 0x53, 0x26, 0xe8, 0xa9,
-       0xd6, 0xa2, 0x9c, 0x8d, 0x7f, 0x0f, 0x70, 0xfe, 0xb6, 0xa7, 0x1a, 0x17,
-       0x6f, 0x9b, 0x85, 0x7c, 0x78, 0xa6, 0xd9, 0x46, 0xa4, 0x7f, 0x51, 0xdd,
-       0xc0, 0x3e, 0xe2, 0xbf, 0x87, 0xf8, 0xef, 0x21, 0xfe, 0x7b, 0x88, 0xff,
-       0x1e, 0xe2, 0xbf, 0x87, 0xf8, 0x0f, 0x1e, 0x3e, 0x07, 0x7d, 0x79, 0xd6,
-       0x9b, 0x08, 0x73, 0xb6, 0xc7, 0x56, 0x73, 0x36, 0xfe, 0xcd, 0xcb, 0xb9,
-       0xa6, 0xa2, 0xa5, 0x52, 0x91, 0x20, 0xe7, 0x15, 0x9d, 0xf9, 0x4d, 0x94,
-       0xf3, 0x7e, 0xf4, 0xf7, 0x90, 0x00, 0x8e, 0xf9, 0x1e, 0xe1, 0x2a, 0x9a,
-       0x6e, 0x13, 0x2e, 0xc8, 0xf9, 0x58, 0x67, 0xad, 0x87, 0xe1, 0x77, 0x37,
-       0xfa, 0xb6, 0xe0, 0x9b, 0x4f, 0xf0, 0x7d, 0xa9, 0x76, 0x87, 0x8b, 0x58,
-       0x5c, 0x6e, 0xa8, 0x78, 0x8c, 0x71, 0xe3, 0x0e, 0xfe, 0xad, 0x02, 0x64,
-       0xc0, 0x77, 0x5f, 0x66, 0x6d, 0x51, 0x6e, 0x20, 0x2f, 0x5a, 0x8e, 0x72,
-       0x21, 0xc0, 0x79, 0x6f, 0x6a, 0xa5, 0x05, 0xca, 0x59, 0x97, 0xd9, 0x14,
-       0x98, 0x62, 0xb7, 0xe6, 0x78, 0x97, 0x54, 0xbd, 0x74, 0xb6, 0x49, 0x7a,
-       0x46, 0x40, 0x5b, 0x74, 0x8f, 0x2c, 0x62, 0xcc, 0xa7, 0x44, 0x9f, 0x47,
-       0x7e, 0x6b, 0x0f, 0xa9, 0xbf, 0x6f, 0xe8, 0xc5, 0x3e, 0xfa, 0xfc, 0x8e,
-       0x96, 0x7b, 0x5a, 0x29, 0x04, 0x3e, 0x9b, 0xb1, 0x87, 0xe7, 0x48, 0xc1,
-       0x76, 0xdd, 0x6d, 0x38, 0x1b, 0xe4, 0xfa, 0xaf, 0x5b, 0x55, 0x0e, 0x0e,
-       0x3f, 0x7a, 0x62, 0xa8, 0xbf, 0x5f, 0xba, 0xb7, 0xcb, 0xc9, 0x21, 0xd6,
-       0x6b, 0x9b, 0x81, 0x8f, 0x6b, 0x79, 0xff, 0xb4, 0x5d, 0x4e, 0x2d, 0xc2,
-       0xcf, 0x2e, 0x66, 0x1d, 0xea, 0xf2, 0xd2, 0x50, 0x0a, 0xfe, 0xf9, 0xe6,
-       0x7e, 0xc6, 0xe7, 0xe5, 0x26, 0x75, 0xa5, 0x17, 0xf0, 0x03, 0xd0, 0xcb,
-       0x4d, 0xb0, 0x27, 0x1d, 0xfb, 0x47, 0xb8, 0xff, 0x45, 0xe1, 0xee, 0xb5,
-       0x9d, 0x6d, 0x4a, 0x37, 0xf4, 0xac, 0x95, 0xd1, 0x41, 0xfb, 0xff, 0x14,
-       0x6e, 0x6d, 0x31, 0x71, 0x5c, 0x67, 0xf8, 0x3f, 0xb3, 0xdc, 0x8c, 0xd7,
-       0x30, 0x86, 0xf5, 0xb2, 0x58, 0xae, 0xba, 0x03, 0x63, 0x33, 0xd1, 0x62,
-       0x65, 0xb0, 0xec, 0x16, 0x55, 0x96, 0xba, 0xda, 0x05, 0x42, 0xe2, 0x3a,
-       0xdd, 0x24, 0xb4, 0x72, 0xd5, 0x2a, 0x42, 0x60, 0x37, 0x8e, 0xfa, 0xd2,
-       0x46, 0x55, 0xdb, 0x37, 0xaf, 0x16, 0xec, 0x38, 0xcd, 0xac, 0x17, 0x37,
-       0x38, 0xf4, 0x71, 0xb3, 0x2c, 0x0e, 0x90, 0x75, 0x56, 0x6e, 0xf2, 0x90,
-       0x3e, 0x19, 0x6d, 0xa2, 0x24, 0x55, 0xa5, 0xbc, 0x54, 0x7d, 0xab, 0x5a,
-       0x0b, 0x27, 0xc4, 0x0f, 0xa9, 0xad, 0xf6, 0xa5, 0x77, 0x4d, 0xbf, 0xef,
-       0xcc, 0x2c, 0xc6, 0xa4, 0x51, 0x91, 0x56, 0x73, 0xe6, 0xcc, 0xb9, 0x9f,
-       0xff, 0xf2, 0xfd, 0x17, 0x3e, 0x67, 0x67, 0xba, 0xc2, 0xbd, 0xcd, 0x95,
-       0x76, 0xc6, 0xfe, 0xb6, 0xd4, 0xcc, 0x02, 0xf3, 0x1a, 0x86, 0x64, 0xdc,
-       0x64, 0xae, 0xcf, 0x96, 0x3a, 0x57, 0x66, 0x1b, 0x1b, 0x65, 0xda, 0xe4,
-       0x4b, 0x6a, 0xa6, 0xdc, 0x23, 0x17, 0x41, 0xc7, 0x85, 0xe1, 0xd6, 0xd0,
-       0xf7, 0xda, 0x19, 0xf2, 0x73, 0x77, 0x3c, 0xd4, 0x57, 0x1a, 0x57, 0x16,
-       0x34, 0xb6, 0xee, 0xde, 0xf5, 0xed, 0x49, 0xac, 0x29, 0x41, 0x5f, 0x79,
-       0x5c, 0xcb, 0x26, 0x83, 0xef, 0x7d, 0xbb, 0xde, 0xe3, 0xbb, 0xde, 0x0f,
-       0xfc, 0x8f, 0xf6, 0x2c, 0xef, 0xa6, 0x07, 0xae, 0xd3, 0x1a, 0xe5, 0x2c,
-       0x05, 0xcf, 0x36, 0x66, 0x3d, 0x2b, 0x4d, 0x5c, 0x90, 0x15, 0x5f, 0x65,
-       0xdd, 0x36, 0xc8, 0xbb, 0x36, 0x99, 0x5f, 0x04, 0xcd, 0x63, 0x1f, 0xed,
-       0x36, 0x63, 0xe4, 0x43, 0x71, 0xf2, 0x4c, 0x07, 0xae, 0xc1, 0xb0, 0x07,
-       0x13, 0x68, 0xe7, 0x3f, 0xef, 0xa6, 0xcc, 0xb3, 0xda, 0x97, 0x43, 0x3c,
-       0xe3, 0xab, 0x82, 0xce, 0xf7, 0x60, 0x9b, 0x16, 0xb9, 0x63, 0x67, 0x7a,
-       0xc2, 0x7c, 0x20, 0xd8, 0xbe, 0x5f, 0x8d, 0x13, 0x6b, 0x3c, 0xe7, 0x6e,
-       0xd7, 0x99, 0x9b, 0xc2, 0x1c, 0x2b, 0x10, 0xcd, 0x53, 0x22, 0xe5, 0xaa,
-       0xc8, 0xeb, 0xf8, 0xfd, 0xa6, 0x1a, 0xc6, 0x4f, 0x14, 0xed, 0xee, 0x93,
-       0xb2, 0x5e, 0xfa, 0x9a, 0xd4, 0xa0, 0x7f, 0xd6, 0x5c, 0xdf, 0xbf, 0xeb,
-       0x26, 0xf5, 0x99, 0xbf, 0xe8, 0x29, 0x19, 0x18, 0xa1, 0x7e, 0x6b, 0x93,
-       0x97, 0x17, 0x5b, 0x64, 0xc3, 0xb4, 0xcc, 0xbb, 0x44, 0x01, 0x5e, 0x42,
-       0x26, 0x63, 0x11, 0x8d, 0x51, 0xe5, 0x5b, 0x22, 0x5b, 0xf8, 0xb6, 0xb5,
-       0xf8, 0x4c, 0x9c, 0xfe, 0x97, 0x4f, 0x16, 0xf9, 0x6e, 0xe0, 0x69, 0x48,
-       0xc3, 0x8e, 0x00, 0xcb, 0x42, 0x08, 0x99, 0x3c, 0x77, 0xee, 0xf7, 0xbb,
-       0x5c, 0x1b, 0xea, 0x68, 0xcf, 0xb6, 0x49, 0xe1, 0x30, 0x64, 0xa2, 0x1a,
-       0xd4, 0x39, 0x47, 0x8d, 0x98, 0x96, 0xd1, 0x91, 0x0a, 0x7d, 0xf8, 0xe6,
-       0x5e, 0x2d, 0xaf, 0x33, 0x37, 0x7e, 0xa4, 0xf7, 0x82, 0x72, 0xbe, 0xe2,
-       0x92, 0x56, 0x4d, 0x59, 0x03, 0xaf, 0xad, 0xd6, 0x5f, 0xed, 0xe3, 0x5d,
-       0xad, 0xd7, 0x5f, 0x88, 0x07, 0xf6, 0x1a, 0xeb, 0x7e, 0x1c, 0x0f, 0xea,
-       0x92, 0xa1, 0xfd, 0x45, 0x3b, 0xad, 0x8c, 0xbd, 0xbd, 0x20, 0xf5, 0xa5,
-       0x9f, 0xc9, 0x3b, 0xa5, 0x9f, 0xc8, 0xaf, 0x97, 0xce, 0x00, 0x7f, 0x58,
-       0xe5, 0x3c, 0xf4, 0xc9, 0xcd, 0xba, 0xef, 0xdf, 0x74, 0xa7, 0x60, 0x2b,
-       0xf8, 0xfe, 0xef, 0xdc, 0x0d, 0x19, 0x38, 0xf6, 0x3d, 0xec, 0x39, 0x07,
-       0x1e, 0xa2, 0x2c, 0x9c, 0x04, 0xbd, 0xb9, 0x7d, 0xd2, 0x19, 0xd5, 0x74,
-       0x32, 0x78, 0xac, 0x15, 0x7b, 0x30, 0x42, 0x4c, 0xce, 0xbd, 0x8c, 0xf4,
-       0x91, 0x66, 0x8c, 0x7a, 0x09, 0xf3, 0xb7, 0x82, 0x2f, 0xf6, 0xe2, 0xa7,
-       0xe4, 0xee, 0x08, 0xd6, 0x3a, 0x42, 0xda, 0x6b, 0x95, 0x81, 0x47, 0xb1,
-       0x8f, 0x5c, 0x8b, 0xdc, 0xf3, 0x7e, 0x19, 0xa7, 0x6f, 0xef, 0x9e, 0xc7,
-       0xb2, 0xf1, 0x95, 0x2e, 0xf1, 0xa5, 0x05, 0xba, 0x7c, 0xfe, 0x78, 0x80,
-       0x9b, 0xde, 0x55, 0x43, 0x68, 0x6f, 0xe7, 0xdf, 0x53, 0xc4, 0x79, 0x79,
-       0xbf, 0x15, 0xb8, 0x7c, 0x1c, 0x78, 0x28, 0x53, 0xbf, 0x20, 0x8d, 0x91,
-       0x28, 0xda, 0x10, 0xaf, 0x68, 0x59, 0x22, 0x59, 0x8f, 0x39, 0x5a, 0xcc,
-       0x97, 0xc2, 0x1a, 0xa7, 0x74, 0x2e, 0x57, 0x1f, 0xcf, 0x9c, 0x58, 0x3e,
-       0xa8, 0xb3, 0x41, 0x23, 0xac, 0x23, 0x7d, 0xa7, 0x35, 0xa6, 0x82, 0x0e,
-       0xc5, 0x78, 0xc3, 0x92, 0xd1, 0xe5, 0x2e, 0x8c, 0x77, 0x41, 0x32, 0x6e,
-       0x73, 0xcc, 0x51, 0xb4, 0xa1, 0x9c, 0x19, 0x05, 0x96, 0xf8, 0x58, 0x8d,
-       0x2d, 0xc6, 0xa0, 0xcb, 0xe3, 0x32, 0x66, 0xee, 0xd9, 0xb1, 0xc7, 0xbc,
-       0xb6, 0x15, 0x0c, 0x63, 0x38, 0x5c, 0x53, 0xd7, 0x8e, 0x35, 0xb1, 0x3f,
-       0x7e, 0xb0, 0x93, 0x33, 0x8b, 0x0b, 0x90, 0x53, 0x0b, 0x1f, 0x66, 0xdc,
-       0x67, 0x25, 0x1b, 0x6b, 0xd3, 0xb6, 0x4d, 0x05, 0xf7, 0x92, 0xf5, 0xe8,
-       0xd3, 0xfa, 0x0e, 0xe4, 0xd0, 0x9e, 0xb0, 0x8e, 0x6d, 0xc5, 0xc8, 0xe0,
-       0xec, 0x03, 0x1b, 0x97, 0x75, 0x5f, 0x96, 0xcc, 0x42, 0x4e, 0x26, 0x74,
-       0x3f, 0x9e, 0xe1, 0x41, 0x8d, 0x43, 0xc8, 0xab, 0x03, 0xbd, 0x38, 0xcb,
-       0xd4, 0x03, 0x7b, 0x38, 0xd9, 0x4b, 0x2e, 0xfa, 0x4f, 0xc8, 0xb3, 0xf8,
-       0xd6, 0xcb, 0x3b, 0x6a, 0x93, 0x81, 0x67, 0xa0, 0x2f, 0xbd, 0x66, 0x7d,
-       0x54, 0x3e, 0xf3, 0xfc, 0x38, 0x63, 0x2e, 0x7f, 0xf6, 0x4c, 0xf9, 0xc4,
-       0xd3, 0xb1, 0xd8, 0xe9, 0x88, 0x58, 0xe7, 0x03, 0x5b, 0xfd, 0xf0, 0xf4,
-       0xbc, 0xe2, 0xf7, 0xc3, 0xe7, 0x57, 0x54, 0x07, 0xda, 0x46, 0xd1, 0x8e,
-       0xeb, 0x30, 0x65, 0xdc, 0xfb, 0xab, 0x3f, 0x73, 0xc4, 0xf7, 0x27, 0x74,
-       0x4e, 0x58, 0xca, 0x9c, 0x57, 0x4d, 0x7c, 0xee, 0x88, 0x17, 0x6b, 0xc7,
-       0x5c, 0x29, 0x73, 0x45, 0x1d, 0xc6, 0x7a, 0x58, 0xee, 0x25, 0x4f, 0x24,
-       0x36, 0x84, 0xe3, 0x5b, 0x93, 0xcb, 0x2a, 0x95, 0x1c, 0x54, 0x56, 0xba,
-       0x80, 0x5f, 0x8b, 0xd2, 0x71, 0xcc, 0x44, 0x52, 0x81, 0x77, 0xb1, 0x27,
-       0xfb, 0xa8, 0xef, 0x4f, 0xda, 0xac, 0x4f, 0x99, 0x51, 0x45, 0xdf, 0x4b,
-       0xa7, 0x8e, 0x77, 0x5e, 0x3e, 0x90, 0x32, 0x8f, 0xaa, 0xfd, 0xe1, 0xfb,
-       0x28, 0x64, 0xe6, 0xf6, 0x78, 0x67, 0x96, 0x95, 0x29, 0x2f, 0x79, 0xa9,
-       0xe4, 0xac, 0xb2, 0x72, 0x18, 0x33, 0x37, 0xa6, 0x28, 0x37, 0x52, 0x66,
-       0xa7, 0xa2, 0x7f, 0xb4, 0x5d, 0xef, 0x7b, 0x12, 0xfd, 0x53, 0xaa, 0x25,
-       0x5c, 0x0f, 0xef, 0xeb, 0x4a, 0x5f, 0xc0, 0x33, 0x94, 0x39, 0xfd, 0xc6,
-       0xcc, 0x02, 0xf3, 0xcb, 0x74, 0x5e, 0x43, 0x7a, 0xe0, 0x18, 0xdf, 0x0d,
-       0xb9, 0x7f, 0xe2, 0x6f, 0xa8, 0x43, 0xb9, 0xcc, 0x3a, 0x27, 0xe4, 0xb7,
-       0x23, 0x1a, 0x3f, 0xdf, 0x3f, 0x91, 0xd7, 0xb9, 0x8b, 0x0d, 0x35, 0x10,
-       0xee, 0x7b, 0xfb, 0xce, 0x92, 0x19, 0xf7, 0x4b, 0x1c, 0x67, 0x21, 0x72,
-       0xb2, 0x5d, 0x98, 0x23, 0x3a, 0x5e, 0x6a, 0xd2, 0x06, 0x7d, 0x03, 0xcc,
-       0x15, 0x68, 0xc6, 0xdd, 0x2f, 0x88, 0x71, 0xac, 0x63, 0x07, 0x9d, 0x00,
-       0x77, 0x02, 0xaf, 0x56, 0x31, 0x4e, 0x61, 0x51, 0xf2, 0x41, 0x7f, 0xe9,
-       0x60, 0x4e, 0x6a, 0xa1, 0xfa, 0x45, 0x63, 0x04, 0x3a, 0x70, 0x1c, 0xef,
-       0xf7, 0x4f, 0x90, 0x3e, 0x79, 0x36, 0x49, 0x35, 0xbe, 0xc4, 0xf5, 0x1c,
-       0x94, 0x89, 0x45, 0x60, 0x23, 0xfc, 0xe6, 0x17, 0x83, 0x7b, 0xbb, 0x0e,
-       0x9c, 0x3d, 0xe1, 0x99, 0x9a, 0x5f, 0x67, 0x5d, 0xc6, 0x4f, 0xc0, 0x2b,
-       0x3a, 0x8f, 0x8a, 0x7d, 0x99, 0x4b, 0x78, 0x88, 0xfa, 0xd1, 0x6d, 0x48,
-       0x0c, 0x6d, 0x89, 0x59, 0x59, 0x6f, 0x8d, 0x26, 0x23, 0xdd, 0x32, 0x0f,
-       0x79, 0x57, 0x81, 0xee, 0x2c, 0x5c, 0x89, 0xca, 0xac, 0xa7, 0xe3, 0xd9,
-       0xc9, 0x8f, 0x95, 0x2b, 0xb5, 0xfa, 0x71, 0xb9, 0x51, 0x77, 0xf4, 0x37,
-       0xea, 0xb5, 0xc2, 0xab, 0x86, 0x7c, 0xff, 0x88, 0xce, 0xa5, 0x73, 0x2a,
-       0xd2, 0xd9, 0x4f, 0xcc, 0xb3, 0xa2, 0xf3, 0xea, 0x20, 0x3b, 0x80, 0x39,
-       0xde, 0x06, 0xe6, 0x78, 0x0b, 0x98, 0xe3, 0x57, 0xc0, 0xd8, 0x37, 0x4b,
-       0x93, 0xa1, 0xfc, 0x9f, 0x86, 0x1c, 0xa2, 0xae, 0xb6, 0xce, 0xe0, 0x4e,
-       0xa7, 0xf3, 0xa0, 0xc1, 0xdb, 0xb0, 0x3f, 0xd6, 0x4b, 0x19, 0x59, 0x5d,
-       0x9a, 0x90, 0xb5, 0xa5, 0x20, 0x0f, 0xf9, 0x03, 0xe6, 0x7d, 0x8d, 0xf0,
-       0x9e, 0x1c, 0xc8, 0xa1, 0x3d, 0x32, 0x70, 0x94, 0xf2, 0xa3, 0x43, 0x96,
-       0x8b, 0xab, 0x5a, 0x0e, 0x2d, 0x17, 0x59, 0x8e, 0x88, 0xce, 0x21, 0x9b,
-       0xda, 0x90, 0x8a, 0x5b, 0x47, 0xfd, 0x3e, 0xed, 0x0f, 0x0a, 0xfc, 0xf3,
-       0x94, 0x97, 0x7f, 0x0a, 0xef, 0x5e, 0xe9, 0xdc, 0xba, 0x19, 0xb3, 0x1b,
-       0xed, 0x9a, 0xb2, 0x6b, 0x30, 0x88, 0xb9, 0xab, 0xdb, 0x68, 0x83, 0x39,
-       0x80, 0x19, 0xaf, 0x43, 0x87, 0x34, 0x9c, 0x6e, 0x8d, 0xfd, 0x1a, 0xce,
-       0x21, 0x9d, 0x77, 0xcb, 0x71, 0x0a, 0x45, 0x5b, 0xe6, 0x8a, 0x56, 0x32,
-       0x0f, 0xfa, 0xbb, 0x01, 0xbb, 0x6d, 0x15, 0x77, 0xb0, 0x86, 0x33, 0x58,
-       0xaf, 0x53, 0xcf, 0x6f, 0x6a, 0xd9, 0xbb, 0x5c, 0xff, 0x23, 0xc6, 0xb1,
-       0xce, 0xa4, 0xe5, 0x0f, 0x7d, 0x94, 0x81, 0xf4, 0x4d, 0x65, 0x75, 0xff,
-       0xa0, 0xdf, 0x2a, 0xda, 0xae, 0xd5, 0x29, 0x8f, 0x45, 0x2e, 0x79, 0x36,
-       0x74, 0xc9, 0xcb, 0x09, 0x62, 0x80, 0xb2, 0x6a, 0xf6, 0xf3, 0xc3, 0x35,
-       0xfb, 0xfe, 0x5e, 0x9b, 0xeb, 0x72, 0x42, 0xb9, 0x4d, 0xdd, 0xbf, 0xa1,
-       0xb1, 0x8d, 0x57, 0x7a, 0x56, 0xde, 0xc4, 0x7d, 0x07, 0x18, 0x27, 0x27,
-       0x6f, 0x00, 0xe3, 0xd5, 0x4b, 0xcd, 0xbc, 0xed, 0x93, 0x38, 0xa7, 0x92,
-       0x9a, 0xbb, 0xda, 0x29, 0x97, 0xaf, 0x15, 0xd4, 0x4b, 0xd7, 0x3c, 0xf5,
-       0xf3, 0xab, 0x45, 0x55, 0xb8, 0xea, 0xfb, 0xff, 0x70, 0x67, 0xe4, 0x9d,
-       0x25, 0x5f, 0x4e, 0xbb, 0x46, 0x7f, 0x44, 0x9a, 0xf9, 0x74, 0xbe, 0xdf,
-       0x01, 0xd9, 0xbc, 0x7e, 0xc0, 0xf7, 0x1f, 0x19, 0x19, 0x11, 0xe7, 0x00,
-       0x31, 0xca, 0x70, 0x82, 0x39, 0xae, 0x94, 0x39, 0x19, 0xdb, 0x3e, 0x5f,
-       0x51, 0x0a, 0xf2, 0xad, 0x3b, 0xc0, 0x2f, 0x8f, 0xee, 0x0b, 0xe3, 0x26,
-       0x3f, 0x7c, 0x9e, 0x7e, 0xe5, 0xc4, 0xe7, 0xfc, 0xca, 0xa6, 0x9c, 0x2d,
-       0xf6, 0xa2, 0x7f, 0x4c, 0x7e, 0x50, 0x8c, 0xee, 0x2a, 0x9b, 0x78, 0x3a,
-       0x46, 0xa1, 0x78, 0xcf, 0x1f, 0xd4, 0xf1, 0x03, 0x60, 0x12, 0xd3, 0xf7,
-       0x67, 0x5d, 0xce, 0xd7, 0x8d, 0xf9, 0x36, 0xcc, 0x7d, 0xd0, 0xff, 0xa7,
-       0xb5, 0x7e, 0x2e, 0x2b, 0xd8, 0xc1, 0xe0, 0xef, 0x98, 0x8c, 0x15, 0xa1,
-       0xe3, 0x15, 0xf3, 0x4c, 0x89, 0x15, 0xac, 0xc4, 0x2c, 0x64, 0xc7, 0x0c,
-       0xe4, 0xcd, 0x29, 0x1d, 0x67, 0xed, 0xd5, 0xb2, 0x67, 0x8e, 0xe5, 0x9c,
-       0xa4, 0x2b, 0x6e, 0x8f, 0x3e, 0xbf, 0xcd, 0x1b, 0x2f, 0x26, 0x82, 0x3b,
-       0x07, 0x1f, 0xe7, 0x94, 0xb4, 0xc1, 0x1e, 0xca, 0xae, 0x4c, 0x81, 0x27,
-       0x12, 0x38, 0xdb, 0x56, 0xcd, 0x0f, 0x0d, 0xe8, 0xef, 0x86, 0xf6, 0x29,
-       0x06, 0xb1, 0x8b, 0x86, 0xc9, 0x76, 0xa7, 0xd0, 0xaf, 0x5d, 0x32, 0x57,
-       0xdb, 0xb4, 0x5c, 0x7d, 0xb8, 0x2e, 0x0d, 0x1c, 0xf2, 0x04, 0xca, 0x11,
-       0xd4, 0x25, 0xc3, 0xb2, 0x81, 0xf2, 0x34, 0xca, 0x2d, 0x78, 0xb2, 0xcd,
-       0x61, 0xe0, 0x0a, 0x3c, 0x5f, 0xc3, 0x78, 0x23, 0x58, 0x73, 0xce, 0x94,
-       0x8f, 0x4e, 0x50, 0x97, 0x38, 0x06, 0x73, 0x91, 0x67, 0x6d, 0x3c, 0x6b,
-       0x45, 0x95, 0x5d, 0x60, 0x19, 0xcf, 0x72, 0xf0, 0xfd, 0x21, 0x99, 0x84,
-       0x3e, 0x99, 0x6b, 0x81, 0x4c, 0xfa, 0x68, 0x5b, 0x26, 0xb1, 0xae, 0x5d,
-       0xc6, 0xae, 0x92, 0xd7, 0x4d, 0xd0, 0x5b, 0xa7, 0x64, 0xaf, 0xc5, 0x34,
-       0x1e, 0xad, 0x80, 0x16, 0xaf, 0x83, 0xae, 0x96, 0x41, 0x53, 0x99, 0xa2,
-       0x35, 0x3a, 0xad, 0x92, 0xda, 0x2f, 0xf0, 0x38, 0xe8, 0xb5, 0xe3, 0x0a,
-       0xb1, 0x28, 0x79, 0xd9, 0x01, 0xed, 0x89, 0xdf, 0x61, 0xdb, 0x93, 0x8e,
-       0xb2, 0x41, 0x83, 0xa0, 0xcb, 0x62, 0xc0, 0xd3, 0xef, 0x29, 0x2d, 0x57,
-       0x47, 0xef, 0x48, 0x2a, 0x7d, 0x47, 0x2c, 0xc8, 0x02, 0xcb, 0xfd, 0x50,
-       0x5c, 0x8c, 0x79, 0x5c, 0x5e, 0xc7, 0x3c, 0x06, 0xf8, 0xfb, 0xc8, 0x90,
-       0xe6, 0xef, 0x51, 0x89, 0xec, 0xe6, 0x71, 0xd0, 0x1b, 0x64, 0x50, 0xc0,
-       0xd3, 0xe9, 0x90, 0x46, 0x9f, 0x06, 0xff, 0x5a, 0xb0, 0xca, 0x92, 0x32,
-       0x0f, 0xfe, 0xbf, 0x8e, 0xef, 0xb7, 0xea, 0x9f, 0xaa, 0xb9, 0x05, 0x15,
-       0xe6, 0xb2, 0x7c, 0x1b, 0x38, 0xf9, 0xf7, 0x38, 0xbb, 0x2e, 0x8d, 0xdd,
-       0x07, 0x46, 0x18, 0x4b, 0xfb, 0xb7, 0xba, 0x6c, 0x1f, 0x95, 0xcd, 0xe1,
-       0xe3, 0x28, 0xef, 0xc3, 0xd3, 0xc0, 0x39, 0x44, 0x75, 0x2c, 0x7c, 0xd9,
-       0x1b, 0x36, 0x0a, 0x3a, 0xef, 0xe0, 0x98, 0xce, 0xcf, 0x37, 0xec, 0x03,
-       0xf8, 0x4e, 0xbf, 0x0c, 0xf7, 0x06, 0xcc, 0xa4, 0x12, 0x3a, 0xc7, 0xb4,
-       0x02, 0x2c, 0xb1, 0x82, 0xf1, 0xde, 0xa7, 0x5f, 0xaf, 0x06, 0x1e, 0x1e,
-       0xfe, 0xa7, 0x9f, 0x8e, 0x31, 0x27, 0x7d, 0x33, 0x11, 0xe8, 0xbf, 0xcf,
-       0xfc, 0x4d, 0x7b, 0x6e, 0xd4, 0xc0, 0xcb, 0x6d, 0x33, 0x86, 0xb6, 0xd0,
-       0x65, 0xd0, 0x45, 0x65, 0x4d, 0xbf, 0x6c, 0x17, 0xf4, 0x2d, 0xd4, 0x52,
-       0xe6, 0x07, 0x12, 0xf4, 0x9d, 0xb7, 0xa9, 0x77, 0xda, 0x21, 0x5f, 0x92,
-       0x1a, 0x57, 0xbe, 0x6f, 0xe7, 0x21, 0x15, 0xac, 0xe4, 0x24, 0x68, 0xb4,
-       0x4d, 0x2c, 0x67, 0x5c, 0x1e, 0xcc, 0x3b, 0xab, 0xfb, 0xb2, 0x6d, 0xb3,
-       0x6f, 0x73, 0x5e, 0xae, 0x9f, 0x7b, 0xe1, 0x1e, 0xe8, 0xa7, 0x36, 0x35,
-       0x8d, 0x36, 0x6a, 0xed, 0xfd, 0x01, 0x8d, 0x36, 0xf7, 0x11, 0xfb, 0x3f,
-       0xfb, 0x20, 0x9d, 0x0c, 0x1b, 0x41, 0x0e, 0x06, 0x9e, 0x35, 0x9e, 0xe7,
-       0xa7, 0xc0, 0xf7, 0x3b, 0xe9, 0xa7, 0xe9, 0x67, 0x0c, 0xe8, 0xe7, 0x91,
-       0x6d, 0xfa, 0x21, 0xdd, 0x74, 0xca, 0xd8, 0x35, 0x5b, 0x26, 0x8a, 0xfa,
-       0xbe, 0x81, 0x35, 0xe9, 0x3f, 0x3a, 0x0e, 0xba, 0x21, 0xad, 0x93, 0xb7,
-       0x4c, 0x29, 0x83, 0x8e, 0xca, 0x90, 0x4f, 0x65, 0xd0, 0x14, 0x31, 0x50,
-       0x19, 0xf2, 0xad, 0x5c, 0xb7, 0x9c, 0x2a, 0xf6, 0x4c, 0x9d, 0xbd, 0x02,
-       0x3a, 0xba, 0x5e, 0xe7, 0xfd, 0xeb, 0x35, 0x9b, 0xd4, 0x83, 0xb7, 0xb6,
-       0xef, 0xfe, 0xef, 0xb8, 0xfb, 0x43, 0x72, 0x03, 0x76, 0xcb, 0x9b, 0xa5,
-       0x61, 0xc8, 0x24, 0x21, 0x5e, 0x04, 0x6d, 0x8c, 0xca, 0x6a, 0xe9, 0xa4,
-       0xac, 0x41, 0x3f, 0xad, 0x2f, 0x0d, 0x00, 0x4f, 0x43, 0x8e, 0xbe, 0x72,
-       0x44, 0xde, 0x58, 0x52, 0x32, 0x63, 0x43, 0xbf, 0x2c, 0xd3, 0x07, 0x0f,
-       0x7a, 0x2e, 0x77, 0xea, 0x98, 0xfd, 0x58, 0x35, 0xf0, 0xc5, 0x8f, 0x57,
-       0xbb, 0x64, 0xa2, 0x6a, 0xca, 0x63, 0xd5, 0x1e, 0x79, 0xa2, 0x1a, 0x93,
-       0xd3, 0xb5, 0x84, 0x7c, 0xa3, 0x7a, 0x50, 0x4e, 0x55, 0x0f, 0xc9, 0x93,
-       0xb5, 0xa4, 0x7c, 0x13, 0x76, 0x61, 0xae, 0xe6, 0xc8, 0x64, 0x6d, 0x58,
-       0x1e, 0xaf, 0xd1, 0xc7, 0x8e, 0xf9, 0xf0, 0xcb, 0x6e, 0xfb, 0x2e, 0xb8,
-       0xae, 0x0e, 0xac, 0xcb, 0x51, 0xe3, 0x3a, 0x66, 0x29, 0xb9, 0xc0, 0xff,
-       0x21, 0x72, 0x0e, 0x7d, 0x2f, 0xbe, 0xa2, 0xa4, 0xa2, 0xe7, 0x6f, 0xfe,
-       0xdf, 0x48, 0x54, 0xdb, 0x46, 0xe7, 0xca, 0x07, 0xd1, 0xc6, 0xa6, 0x4d,
-       0x12, 0xfa, 0x41, 0x9a, 0xfe, 0xff, 0xa6, 0xed, 0x65, 0x68, 0x1f, 0xf6,
-       0x2d, 0xda, 0x5e, 0xfa, 0xec, 0x29, 0x3f, 0x68, 0xe7, 0xd0, 0xd6, 0xda,
-       0x19, 0xe7, 0x68, 0xce, 0x7b, 0x31, 0xf7, 0xf0, 0xff, 0xa7, 0x04, 0xf1,
-       0xaa, 0xb3, 0xb5, 0x83, 0xfc, 0x3f, 0x15, 0xac, 0xe5, 0x8b, 0xf3, 0xc5,
-       0x27, 0x4a, 0x63, 0xea, 0xb1, 0x12, 0x11, 0x8d, 0x2f, 0x17, 0xb7, 0x73,
-       0xf2, 0xbe, 0x2e, 0xcb, 0x6e, 0x54, 0xaf, 0x21, 0xf0, 0xdb, 0xa7, 0x75,
-       0x7e, 0xde, 0xd8, 0x10, 0xe9, 0x8f, 0x71, 0xb8, 0xae, 0x30, 0xb6, 0x00,
-       0x6c, 0xeb, 0x9a, 0x72, 0xa9, 0x1a, 0xf8, 0xaf, 0xe6, 0x34, 0xbd, 0xbc,
-       0x05, 0x9a, 0x63, 0xfc, 0x21, 0x78, 0xe6, 0xcb, 0x41, 0xdf, 0xec, 0x90,
-       0x43, 0x7b, 0x1c, 0xfb, 0x35, 0x7a, 0x38, 0x17, 0xff, 0x4f, 0x07, 0xe5,
-       0x70, 0xbd, 0xcc, 0x2f, 0xb6, 0x35, 0x2d, 0x06, 0x31, 0x5e, 0x47, 0x9e,
-       0xc3, 0x5d, 0x54, 0x4c, 0xae, 0xbf, 0x43, 0x2a, 0x0e, 0x6d, 0x5b, 0xca,
-       0xef, 0x21, 0x29, 0x63, 0x9e, 0x8a, 0xd3, 0xf4, 0x8d, 0x05, 0x72, 0xb6,
-       0x62, 0x3e, 0x98, 0x77, 0xba, 0xbc, 0x1f, 0xef, 0xa8, 0x73, 0x80, 0x99,
-       0xa6, 0xf8, 0x7e, 0x11, 0x65, 0xfa, 0x46, 0xe6, 0xf0, 0x4c, 0x84, 0x75,
-       0xaf, 0xf5, 0x6b, 0xac, 0x7e, 0xf2, 0x41, 0xbf, 0x99, 0xb2, 0x95, 0xcf,
-       0x44, 0xb6, 0x94, 0xf1, 0x8b, 0xf5, 0x7e, 0xca, 0xdc, 0xfd, 0x36, 0x7f,
-       0x51, 0xf9, 0x8b, 0xa9, 0x7d, 0x0a, 0xe1, 0xb7, 0x3d, 0xf2, 0x94, 0xc9,
-       0xdc, 0xf5, 0xb4, 0x1a, 0x2b, 0xfd, 0x34, 0xcc, 0xd3, 0xdd, 0x52, 0xfb,
-       0x2b, 0x6f, 0xf7, 0x07, 0x79, 0xee, 0x1c, 0x7b, 0x67, 0x6e, 0xfb, 0x4e,
-       0x3a, 0x61, 0x8e, 0x7b, 0x3b, 0x70, 0xab, 0x56, 0x62, 0xe0, 0x41, 0xc8,
-       0x3b, 0xbb, 0x45, 0xf3, 0x63, 0xa1, 0xf6, 0x2f, 0x7f, 0x43, 0xf3, 0x73,
-       0xd3, 0xc7, 0xf0, 0xdb, 0x7e, 0xda, 0xb6, 0x94, 0x1b, 0x97, 0x02, 0xbf,
-       0x91, 0xb6, 0xa1, 0x21, 0x2b, 0x50, 0x47, 0x5e, 0x05, 0x9f, 0x6c, 0xb7,
-       0xe5, 0xdf, 0x7f, 0x01, 0x99, 0xe7, 0xd3, 0x46, 0x40, 0x67, 0x00, 0x00,
-       0x00 };
-static u32 bnx2_RXP_b09FwData[(0x0/4) + 1] = { 0x0 };
-static u32 bnx2_RXP_b09FwRodata[(0x278/4) + 1] = {
-       0x08003fa4, 0x08003ea4, 0x08003f48, 0x08003f60, 0x08003f78, 0x08003f98,
-       0x08003fa4, 0x08003fa4, 0x08003eac, 0x00000000, 0x080049d4, 0x08004a0c,
-       0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004a44, 0x08004c08,
-       0x08004b50, 0x08004b88, 0x08004c08, 0x08004ad8, 0x08004c08, 0x08004c08,
-       0x08004b88, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-       0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004bc8,
-       0x08004c08, 0x08004bc8, 0x08004b50, 0x08004c08, 0x08004c08, 0x08004bc8,
-       0x08004bc8, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-       0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-       0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-       0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-       0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-       0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-       0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-       0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-       0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-       0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-       0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-       0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-       0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-       0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-       0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-       0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08,
-       0x08004ab4, 0x00000000, 0x0800602c, 0x08006044, 0x08006044, 0x08006044,
-       0x0800602c, 0x08006044, 0x08006044, 0x08006044, 0x0800602c, 0x08006044,
-       0x08006044, 0x08006044, 0x0800602c, 0x08006044, 0x08006044, 0x08006044,
-       0x08006038, 0x00000000, 0x00000000 };
-static u32 bnx2_RXP_b09FwBss[(0x13dc/4) + 1] = { 0x0 };
-static u32 bnx2_RXP_b09FwSbss[(0x2c/4) + 1] = { 0x0 };
+       0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xec, 0x5c,
+       0x5d, 0x6c, 0x1c, 0xd7, 0x75, 0x3e, 0xf3, 0x43, 0x6a, 0x49, 0xf1, 0x67,
+       0xb8, 0x5c, 0xb1, 0x2b, 0x99, 0x96, 0x77, 0xc9, 0x91, 0xc8, 0x58, 0x8a,
+       0x31, 0xa2, 0x09, 0x5b, 0x48, 0x17, 0xf6, 0x76, 0x76, 0x25, 0xb1, 0xb1,
+       0x03, 0x53, 0xb6, 0x62, 0x07, 0x45, 0x6a, 0xb0, 0x4b, 0xb9, 0x0e, 0x8c,
+       0x06, 0x90, 0xff, 0x52, 0xbf, 0xb0, 0xde, 0x2c, 0xa9, 0x58, 0x4d, 0x17,
+       0x9c, 0xb5, 0x4d, 0x9b, 0x0e, 0x60, 0xb7, 0x0b, 0x92, 0x12, 0xf5, 0xb0,
+       0xd0, 0xb2, 0xa9, 0xdb, 0xea, 0xc1, 0x8e, 0x09, 0x56, 0xb1, 0x53, 0xa0,
+       0x2d, 0x5c, 0x27, 0x69, 0xfc, 0x10, 0x14, 0xaa, 0xec, 0xc4, 0x42, 0xd1,
+       0xa2, 0x02, 0x12, 0xd8, 0x29, 0x22, 0x7b, 0xfa, 0x7d, 0x77, 0x66, 0xc8,
+       0x25, 0x2d, 0xdb, 0x41, 0x1f, 0xfa, 0xd2, 0xbd, 0xc0, 0x62, 0xee, 0xbd,
+       0x73, 0xee, 0xb9, 0xe7, 0x9e, 0xff, 0x73, 0x87, 0xd2, 0x1f, 0x74, 0x48,
+       0xbb, 0x84, 0xad, 0x13, 0xbf, 0xd4, 0x89, 0x27, 0x1e, 0xb9, 0x69, 0xf4,
+       0xa6, 0x9b, 0xd1, 0xbd, 0xd9, 0x30, 0x4c, 0x23, 0x9a, 0x6f, 0xb6, 0x66,
+       0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66,
+       0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66,
+       0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66,
+       0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66,
+       0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66,
+       0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0x6b, 0xb6, 0x66, 0xfb, 0xff, 0xde,
+       0x0c, 0x11, 0x8b, 0xcf, 0xce, 0xf0, 0x27, 0x31, 0x3d, 0x23, 0x0f, 0xb9,
+       0xb6, 0xc4, 0x8c, 0xcc, 0xd5, 0xa9, 0x49, 0x5b, 0x24, 0x5b, 0xdb, 0x97,
+       0xca, 0xc9, 0x87, 0x7e, 0x31, 0x61, 0x0a, 0xe7, 0xaf, 0xcf, 0x5c, 0xfd,
+       0x8b, 0x57, 0x6f, 0x4d, 0x5f, 0xa9, 0x1a, 0x12, 0xb3, 0x32, 0x33, 0x07,
+       0xac, 0xbd, 0x12, 0xeb, 0xc7, 0x9a, 0x17, 0x87, 0xfe, 0xa9, 0x4b, 0xba,
+       0x22, 0x5c, 0x22, 0x0b, 0xe5, 0xb4, 0x73, 0x18, 0xcf, 0x33, 0xb5, 0x7d,
+       0xce, 0x9a, 0x98, 0xb2, 0x6a, 0x05, 0x3b, 0x96, 0xca, 0x1a, 0xf1, 0x48,
+       0xa9, 0x16, 0x93, 0x8b, 0xea, 0xdf, 0x79, 0x60, 0x4f, 0x9b, 0xfd, 0xf3,
+       0x9a, 0x5b, 0xf7, 0xfd, 0xd3, 0x8e, 0xef, 0xbf, 0x8e, 0xdf, 0x7b, 0x0e,
+       0xc6, 0xde, 0x47, 0x7e, 0xd6, 0x34, 0x44, 0xb7, 0xff, 0x4c, 0x73, 0x17,
+       0x5b, 0xa5, 0x34, 0x2f, 0x32, 0xed, 0xc5, 0xe4, 0x94, 0x57, 0xd4, 0xf2,
+       0xf5, 0xb2, 0x76, 0x68, 0x79, 0x56, 0x3b, 0xbc, 0x7c, 0x4a, 0x3b, 0xb2,
+       0x5c, 0xd1, 0xdc, 0x65, 0x29, 0xea, 0x07, 0x3a, 0x24, 0x6b, 0x9d, 0xd5,
+       0x72, 0xf5, 0x3e, 0xcd, 0x9d, 0xbf, 0xea, 0xbb, 0x4e, 0xda, 0xfa, 0x3d,
+       0x31, 0xb3, 0xdc, 0xcf, 0x2d, 0xfb, 0x18, 0x9b, 0x92, 0x4d, 0xf8, 0xbe,
+       0x9e, 0xf1, 0x9f, 0x74, 0x47, 0x6d, 0x4b, 0xd7, 0x62, 0x52, 0xaa, 0xb7,
+       0x03, 0x6f, 0x87, 0x96, 0x9b, 0x37, 0xb5, 0xbc, 0xe7, 0xbf, 0xe6, 0x3a,
+       0xd2, 0x6f, 0x88, 0xef, 0xcf, 0x38, 0x7b, 0x92, 0xc7, 0xe5, 0x0c, 0xf0,
+       0xd6, 0x80, 0x4f, 0x2c, 0x3d, 0x43, 0xfa, 0x22, 0x9a, 0x8b, 0x5a, 0x6e,
+       0x28, 0xa2, 0x4f, 0x52, 0xa4, 0xbf, 0xb0, 0xa4, 0x83, 0xce, 0xed, 0x52,
+       0xa8, 0x5a, 0x32, 0xb1, 0xb4, 0x15, 0xfe, 0xa2, 0xff, 0xea, 0x50, 0x42,
+       0xfe, 0xb2, 0x9e, 0x3e, 0x55, 0x04, 0x2f, 0x66, 0xbc, 0x94, 0x80, 0xcf,
+       0x59, 0x77, 0xb4, 0x5f, 0x5e, 0xab, 0x27, 0xe5, 0xbb, 0x75, 0x3b, 0x59,
+       0x92, 0x6d, 0x52, 0x48, 0x58, 0xb2, 0x82, 0x35, 0xd3, 0xa0, 0x43, 0xb7,
+       0x6d, 0xab, 0x04, 0xd8, 0x52, 0xfd, 0x27, 0xfc, 0xb7, 0x32, 0xd6, 0xe4,
+       0xa8, 0x5a, 0x53, 0x04, 0xdd, 0x21, 0x2c, 0xcf, 0xa1, 0x60, 0xd5, 0x59,
+       0x02, 0x58, 0x29, 0x4e, 0x8e, 0x62, 0xae, 0xfe, 0x85, 0x50, 0x16, 0xad,
+       0x38, 0x2f, 0x9f, 0xbb, 0x71, 0xbe, 0xdd, 0xe0, 0x89, 0x24, 0x74, 0xd9,
+       0x93, 0x2c, 0x60, 0x66, 0xba, 0xde, 0x81, 0x31, 0x69, 0xf1, 0xfd, 0x23,
+       0x8e, 0x58, 0x25, 0xa7, 0x1b, 0xbc, 0x4b, 0x49, 0xc9, 0xe9, 0xc2, 0x9a,
+       0x16, 0xb1, 0x6c, 0x9e, 0x81, 0x78, 0xdb, 0x30, 0xef, 0x77, 0x1a, 0x19,
+       0xdf, 0x9f, 0x1c, 0x95, 0xae, 0x60, 0x6e, 0x1f, 0x70, 0x98, 0x32, 0x31,
+       0xae, 0x01, 0xee, 0x03, 0xd2, 0x17, 0x8b, 0x67, 0xd8, 0xe7, 0x73, 0x54,
+       0xdc, 0xd9, 0x54, 0xb8, 0x6f, 0x87, 0x94, 0xbc, 0xeb, 0xc3, 0x3e, 0x78,
+       0xed, 0xe1, 0xcc, 0xce, 0x4e, 0x8c, 0xb5, 0x1b, 0x80, 0xc7, 0x29, 0x09,
+       0xf7, 0xd8, 0x21, 0x6b, 0x09, 0xd1, 0x2f, 0x39, 0xbd, 0x21, 0x5c, 0x17,
+       0x68, 0x8d, 0x64, 0xde, 0x2e, 0x33, 0xf3, 0xad, 0x72, 0x72, 0x9e, 0xbc,
+       0x2d, 0x43, 0x16, 0x78, 0xde, 0x52, 0xd4, 0xb2, 0xf5, 0x53, 0xe8, 0x9b,
+       0x32, 0x69, 0xfb, 0xaf, 0xcd, 0x38, 0xb3, 0x5a, 0x6e, 0xf9, 0x8c, 0x96,
+       0x87, 0x0e, 0x1c, 0x5a, 0x3e, 0xaf, 0x1d, 0xae, 0xaf, 0x76, 0x4a, 0x7b,
+       0x1a, 0xda, 0x66, 0xca, 0x49, 0x4f, 0x13, 0xd2, 0xbb, 0x00, 0x7e, 0x65,
+       0x2d, 0x70, 0xde, 0xee, 0xd2, 0x0e, 0x03, 0x57, 0x8b, 0xfd, 0xad, 0x0e,
+       0xe9, 0x32, 0x64, 0x9b, 0x1d, 0xc1, 0xc6, 0xe4, 0x5b, 0xa0, 0x6d, 0xcd,
+       0x49, 0x00, 0x4e, 0xba, 0x83, 0x35, 0x3d, 0x21, 0x3d, 0xd4, 0x25, 0xea,
+       0x91, 0x9e, 0xcd, 0xcf, 0xfd, 0x69, 0x6f, 0x69, 0xff, 0x76, 0xc2, 0xc0,
+       0x3e, 0x52, 0x0f, 0x4d, 0xda, 0x6e, 0x8f, 0x29, 0x45, 0x4b, 0x97, 0xb4,
+       0x95, 0x93, 0x1b, 0x64, 0xc6, 0x11, 0xc9, 0x41, 0xbf, 0x75, 0xdb, 0x04,
+       0x8f, 0x6c, 0xf0, 0x68, 0xcf, 0xa9, 0x41, 0xfd, 0x0e, 0x49, 0xf5, 0x15,
+       0x35, 0x33, 0xe4, 0xe7, 0x82, 0xdc, 0xa6, 0xd6, 0xeb, 0x19, 0x07, 0x3a,
+       0xd9, 0xce, 0x3e, 0xf6, 0x8d, 0xa9, 0x7d, 0x8d, 0x8c, 0x9d, 0x5c, 0x14,
+       0xd1, 0xf4, 0xcc, 0x3e, 0xe0, 0xa3, 0xae, 0x12, 0xee, 0x29, 0xd0, 0x48,
+       0xda, 0xd9, 0xb7, 0xb1, 0x26, 0x26, 0xae, 0xd3, 0xd9, 0x40, 0x27, 0xe8,
+       0x49, 0x90, 0xe7, 0xe4, 0xa1, 0x3a, 0xa7, 0xb6, 0x71, 0xce, 0x5f, 0xfb,
+       0xdb, 0x46, 0x4c, 0x79, 0x5d, 0x9d, 0x97, 0x76, 0x45, 0x38, 0x75, 0x46,
+       0x21, 0x7f, 0xa6, 0x3d, 0xd1, 0x0a, 0x8e, 0xb5, 0x8e, 0x0b, 0x7a, 0xa1,
+       0x1b, 0x99, 0x0e, 0xc9, 0x29, 0xfa, 0x0e, 0x62, 0x2f, 0xda, 0x1b, 0xec,
+       0xc6, 0xe6, 0x59, 0x38, 0x97, 0x81, 0xed, 0xa6, 0x95, 0xfe, 0x14, 0x2a,
+       0xf4, 0x07, 0xa4, 0x6d, 0x35, 0xad, 0x4b, 0x80, 0xaf, 0xf4, 0x6c, 0x37,
+       0x68, 0xe3, 0x18, 0xb6, 0x67, 0xe3, 0xfd, 0x7e, 0xd8, 0xfa, 0xc1, 0x41,
+       0xf0, 0x87, 0x70, 0x76, 0x0a, 0xf2, 0xce, 0xba, 0xd8, 0xd3, 0x75, 0x6e,
+       0x56, 0x3c, 0xe8, 0xc1, 0x79, 0x06, 0x67, 0xc9, 0xaf, 0x76, 0xe8, 0xb3,
+       0x26, 0x05, 0x27, 0x9d, 0xa2, 0xfc, 0x03, 0xda, 0x75, 0xd9, 0x76, 0x4b,
+       0x23, 0xed, 0x91, 0xac, 0xa8, 0x8f, 0xa6, 0xc4, 0x47, 0x08, 0x4b, 0x38,
+       0xc2, 0xa7, 0x0f, 0x8a, 0xfe, 0x6b, 0xdf, 0xda, 0x74, 0x56, 0x5b, 0x06,
+       0x66, 0x41, 0x43, 0xc0, 0x5b, 0xf0, 0xe4, 0xb3, 0x60, 0xc9, 0xd7, 0xad,
+       0xfc, 0x23, 0x6c, 0x23, 0x1c, 0x74, 0xa2, 0x8f, 0x34, 0xac, 0x74, 0x04,
+       0xf6, 0x15, 0xd1, 0x14, 0xc9, 0x46, 0x0b, 0x71, 0x7c, 0xda, 0x39, 0x08,
+       0x0f, 0xbb, 0xf7, 0x60, 0xf7, 0x1e, 0x7c, 0x82, 0x07, 0x9b, 0xf7, 0xe8,
+       0x27, 0x52, 0xf2, 0xea, 0x10, 0xfc, 0xda, 0x86, 0x5f, 0x41, 0x1b, 0x43,
+       0x5f, 0x17, 0x03, 0x7e, 0x65, 0xba, 0xaa, 0xc3, 0x76, 0x61, 0x43, 0x4b,
+       0x9c, 0xb3, 0xf0, 0xcc, 0xe3, 0x69, 0xc3, 0x8f, 0x52, 0xaf, 0x22, 0xff,
+       0x49, 0x3f, 0x93, 0x84, 0x4f, 0xa1, 0xaf, 0xa1, 0x2f, 0x21, 0xac, 0xef,
+       0xe7, 0x1d, 0xae, 0xf5, 0x65, 0xdc, 0xa1, 0x1d, 0x75, 0x88, 0x1e, 0x2f,
+       0x6a, 0x47, 0x87, 0x60, 0x63, 0x37, 0xb6, 0x80, 0x56, 0xda, 0xda, 0x75,
+       0x74, 0x15, 0x68, 0xbf, 0xe8, 0x0c, 0xfe, 0x5d, 0xde, 0x36, 0xc0, 0x28,
+       0xa1, 0x76, 0x05, 0xe3, 0xb6, 0xd0, 0x9f, 0xf0, 0x7d, 0x3a, 0x95, 0x95,
+       0xdd, 0xe1, 0x98, 0xfd, 0x75, 0x7a, 0x1d, 0xfd, 0x96, 0x98, 0x0c, 0x9c,
+       0x09, 0xfc, 0xe0, 0xc0, 0x82, 0x25, 0xf6, 0x99, 0x80, 0xc6, 0x81, 0x73,
+       0x91, 0x3f, 0x6c, 0x01, 0x3e, 0xd0, 0xe7, 0x6d, 0xc4, 0x09, 0x91, 0xf7,
+       0x34, 0x98, 0x0a, 0xe6, 0xb6, 0xf2, 0x82, 0x3e, 0x98, 0xf6, 0x66, 0x35,
+       0xda, 0xdb, 0x01, 0xd8, 0x9b, 0xd3, 0x2a, 0x69, 0xe7, 0xef, 0x60, 0x6f,
+       0x4f, 0x39, 0x1a, 0x78, 0x23, 0x72, 0xa1, 0xdc, 0x01, 0x5b, 0x37, 0x93,
+       0xef, 0xc8, 0x9e, 0xd4, 0xb4, 0x68, 0x72, 0x9a, 0x73, 0x35, 0xcc, 0x29,
+       0xff, 0x1b, 0xd8, 0xf7, 0x45, 0xe3, 0x69, 0xd0, 0xe5, 0xfb, 0xd3, 0xc0,
+       0x59, 0xd8, 0x6f, 0x84, 0xb6, 0x15, 0xcd, 0xa7, 0x10, 0xf3, 0xdc, 0xcf,
+       0x19, 0x52, 0x1c, 0x6e, 0x91, 0xf4, 0xf0, 0x02, 0x70, 0x4f, 0x3a, 0x81,
+       0x1d, 0x53, 0xd7, 0x17, 0x81, 0x7f, 0xc6, 0x1b, 0x82, 0x1e, 0xd3, 0x0e,
+       0x40, 0x17, 0xf0, 0x2f, 0x02, 0xff, 0x4c, 0xbd, 0x45, 0xbe, 0x69, 0x46,
+       0xb1, 0x34, 0x3a, 0x4f, 0x1b, 0xc0, 0xa2, 0x7d, 0x4f, 0xc8, 0x17, 0xbd,
+       0xb8, 0xe6, 0x3e, 0x4b, 0x3f, 0x5b, 0x1a, 0x86, 0x9d, 0x68, 0x25, 0x87,
+       0x7b, 0x1b, 0xb2, 0xb8, 0x0e, 0x23, 0xd9, 0x52, 0x60, 0x83, 0x59, 0x77,
+       0xa8, 0x98, 0x34, 0x94, 0x2f, 0x11, 0x39, 0x5c, 0x36, 0x01, 0xc3, 0x31,
+       0xe7, 0x83, 0xb9, 0xb1, 0x72, 0x1f, 0x7c, 0x23, 0xc7, 0x57, 0xfd, 0x49,
+       0x27, 0x98, 0xfb, 0xdd, 0x72, 0x81, 0x32, 0x62, 0xdc, 0x4e, 0x95, 0x9c,
+       0x7f, 0xf7, 0xa1, 0xbf, 0x9b, 0xd6, 0x5c, 0x1b, 0x4f, 0x7a, 0x2c, 0x8c,
+       0xf5, 0xda, 0x11, 0x5b, 0xef, 0x6b, 0x0d, 0x7d, 0xd8, 0x11, 0x4c, 0x1e,
+       0x2a, 0x97, 0x7a, 0x5b, 0xe5, 0xaa, 0xc1, 0xd8, 0x79, 0x09, 0x46, 0xed,
+       0x96, 0xf7, 0x82, 0x1f, 0xa5, 0x9e, 0x86, 0xb9, 0x58, 0xbe, 0xec, 0xcb,
+       0x9a, 0x13, 0xac, 0xc1, 0xb8, 0x23, 0x57, 0xd6, 0xfb, 0x62, 0xb2, 0x3e,
+       0xb6, 0xb8, 0x66, 0x49, 0xf6, 0x0e, 0x2f, 0x8a, 0x5a, 0xdb, 0x1b, 0xdb,
+       0x58, 0x9b, 0xc8, 0x97, 0x4b, 0x3d, 0x0d, 0xe3, 0x64, 0x0e, 0xb8, 0xf4,
+       0x03, 0xeb, 0x6b, 0xfb, 0x37, 0xd6, 0xee, 0x90, 0x54, 0x0f, 0xd7, 0xeb,
+       0x7d, 0x6d, 0x1b, 0xb8, 0x53, 0x21, 0x3d, 0xbd, 0x6d, 0x1b, 0x38, 0x6c,
+       0xe2, 0x6c, 0x18, 0x0f, 0x13, 0xe7, 0xc0, 0x06, 0xce, 0xfd, 0x9b, 0xe9,
+       0x39, 0x21, 0xf0, 0x41, 0xb1, 0xd6, 0x8c, 0x1c, 0xb8, 0x50, 0x1e, 0x1c,
+       0xff, 0xa2, 0x20, 0xe6, 0xed, 0xdf, 0x16, 0xfa, 0x64, 0xf3, 0x80, 0x0b,
+       0x5e, 0x99, 0x42, 0x1f, 0xa7, 0x49, 0x09, 0x72, 0x7e, 0xa8, 0x26, 0x07,
+       0xd6, 0x6a, 0x12, 0xea, 0x12, 0x75, 0xe2, 0x32, 0x6c, 0x4c, 0x8a, 0xbb,
+       0x32, 0x1d, 0x13, 0x66, 0xc6, 0x82, 0xad, 0xc9, 0x78, 0x09, 0x3e, 0xd9,
+       0xc8, 0xec, 0x79, 0x3b, 0x67, 0x3c, 0xe9, 0x1b, 0x88, 0xdb, 0x39, 0xe9,
+       0x38, 0xe8, 0x8e, 0x62, 0xbe, 0x46, 0xdb, 0x82, 0x5f, 0xa9, 0x13, 0xf7,
+       0x7c, 0xb7, 0x74, 0x21, 0x2e, 0xd6, 0x5e, 0xda, 0x11, 0xd8, 0x8e, 0x98,
+       0x26, 0x7c, 0xed, 0xcc, 0x28, 0xe3, 0x78, 0x6b, 0x0c, 0xf0, 0x13, 0x46,
+       0x66, 0x6c, 0xe7, 0xf1, 0xda, 0x9d, 0x3b, 0x0b, 0xb5, 0xe2, 0xce, 0x42,
+       0xd9, 0xa2, 0x9d, 0xe8, 0xee, 0x28, 0xfa, 0x2a, 0x57, 0x4a, 0xc2, 0x26,
+       0x2e, 0xab, 0x3c, 0xe2, 0xb5, 0x7a, 0x1d, 0xf6, 0x47, 0xfb, 0x16, 0x19,
+       0xf7, 0xb0, 0xc7, 0xc8, 0x87, 0x90, 0x3b, 0x68, 0x83, 0x4f, 0xcb, 0xe2,
+       0xd4, 0xfa, 0xc8, 0xbf, 0x85, 0xf6, 0xc9, 0xfe, 0xfb, 0x7e, 0xe0, 0xef,
+       0xef, 0xe8, 0x0e, 0xe6, 0xde, 0x0a, 0x6d, 0x3a, 0xc2, 0x45, 0x3c, 0xc3,
+       0xda, 0x38, 0x72, 0x92, 0xf1, 0xba, 0xa9, 0xd1, 0x3f, 0xe7, 0x3c, 0xe6,
+       0x12, 0xcc, 0x23, 0xa6, 0x43, 0x3f, 0x27, 0xd9, 0x1c, 0xfc, 0x88, 0x8e,
+       0xdc, 0xa2, 0x00, 0xbb, 0x31, 0x33, 0x57, 0x64, 0x46, 0xf9, 0x48, 0x89,
+       0xb5, 0x64, 0x9e, 0x00, 0xcc, 0x7f, 0xc0, 0xe6, 0xda, 0xba, 0x43, 0x3d,
+       0x0c, 0x7d, 0xbc, 0xf2, 0xbb, 0x80, 0xbd, 0xbc, 0x05, 0xf6, 0xdd, 0x46,
+       0x58, 0xbc, 0xbf, 0xb8, 0xe5, 0xfd, 0x4f, 0x69, 0xbf, 0x78, 0xb7, 0x0a,
+       0x7f, 0xda, 0x1a, 0xda, 0xfe, 0x05, 0x29, 0xc0, 0xb7, 0x9a, 0x36, 0x73,
+       0xc7, 0xdb, 0xb0, 0x16, 0xe3, 0x1a, 0x68, 0x84, 0xbf, 0x40, 0xcc, 0x04,
+       0xbf, 0x11, 0x13, 0x12, 0x37, 0x30, 0x3f, 0xa2, 0x9f, 0x00, 0x2c, 0xfd,
+       0x2f, 0x61, 0x5f, 0xe9, 0x20, 0xcf, 0x0b, 0x35, 0xae, 0xa1, 0xaf, 0x12,
+       0xdf, 0x1d, 0x6d, 0x83, 0x46, 0xf9, 0xaf, 0x19, 0x76, 0x04, 0x1b, 0xe1,
+       0xdd, 0x0a, 0xcb, 0x7c, 0x85, 0xb8, 0xbb, 0xc3, 0x3c, 0x60, 0x4c, 0xb2,
+       0xf5, 0x2c, 0x7e, 0x45, 0x99, 0x7c, 0x16, 0xb9, 0x98, 0xdd, 0x42, 0x5e,
+       0x90, 0x35, 0x56, 0xc0, 0xa3, 0x68, 0xdd, 0x13, 0xbd, 0x9b, 0xc7, 0xf7,
+       0xc5, 0x37, 0x7c, 0x25, 0x2d, 0x4d, 0xb2, 0x88, 0x15, 0xe0, 0x71, 0x6a,
+       0x42, 0xcf, 0x24, 0x24, 0x57, 0x0b, 0xf8, 0x8b, 0x78, 0x0b, 0xff, 0xc8,
+       0x2e, 0x64, 0xb2, 0xee, 0x07, 0x23, 0x99, 0x53, 0xcf, 0xb2, 0x90, 0x4d,
+       0x0a, 0xba, 0x34, 0x86, 0xb5, 0x72, 0x02, 0x38, 0x18, 0x87, 0x1d, 0x3d,
+       0x13, 0x97, 0x82, 0xc5, 0x7c, 0x41, 0xe5, 0x7a, 0x59, 0xfa, 0x01, 0x3d,
+       0xd3, 0x86, 0x39, 0xf6, 0x1f, 0xee, 0x0e, 0x64, 0xdd, 0xc9, 0xf1, 0xb8,
+       0x9e, 0xe9, 0xde, 0x32, 0xff, 0x7a, 0x67, 0x40, 0x9b, 0x1a, 0x63, 0xfe,
+       0x5f, 0xb6, 0x8c, 0xbf, 0x1e, 0xdf, 0x3c, 0x7e, 0x60, 0x67, 0xa4, 0x0f,
+       0x7a, 0xe6, 0x89, 0x90, 0x5e, 0xea, 0xe9, 0x56, 0x5a, 0x7f, 0x13, 0x7d,
+       0x79, 0x0e, 0x38, 0x95, 0x8e, 0xff, 0x06, 0xfa, 0xb2, 0x0e, 0xfb, 0x09,
+       0xfa, 0xd2, 0x48, 0xc3, 0x7a, 0x5d, 0x51, 0xd1, 0x91, 0x93, 0xba, 0xa3,
+       0x7b, 0x90, 0x77, 0xa4, 0x24, 0x5f, 0x07, 0xef, 0xd6, 0xe3, 0xea, 0x3a,
+       0x4c, 0x71, 0x03, 0x26, 0x88, 0x3b, 0xf9, 0xba, 0x8f, 0x3c, 0xae, 0x31,
+       0x06, 0x0f, 0xa3, 0x5f, 0xc4, 0x59, 0x57, 0x64, 0xd2, 0x5b, 0xcb, 0xea,
+       0xf6, 0xa9, 0x20, 0x0f, 0xb5, 0xbf, 0xad, 0xe5, 0x17, 0x99, 0xa3, 0xc6,
+       0xd0, 0x57, 0xf5, 0x07, 0x62, 0xdc, 0x33, 0x5a, 0x76, 0x79, 0x0e, 0xf9,
+       0xe9, 0x12, 0x7e, 0x67, 0xf1, 0xab, 0xe1, 0x17, 0xd5, 0x01, 0x2f, 0xa0,
+       0x8e, 0x50, 0xfe, 0x1e, 0xb1, 0x29, 0xd8, 0xff, 0x67, 0x4b, 0xc8, 0x8f,
+       0xe7, 0x12, 0xf2, 0x94, 0xad, 0xf7, 0xea, 0x81, 0x8f, 0xcb, 0x22, 0xb7,
+       0xb6, 0x2e, 0xcb, 0x97, 0xc2, 0x1c, 0x4d, 0xe4, 0x9d, 0x0a, 0x64, 0xb9,
+       0xff, 0x48, 0xe8, 0x9f, 0xbe, 0xf6, 0xa0, 0xab, 0x7c, 0x79, 0x98, 0x83,
+       0xc1, 0xef, 0x64, 0x15, 0xd4, 0x1b, 0xe0, 0x8f, 0x26, 0xef, 0x41, 0x8f,
+       0xdf, 0xa9, 0xb4, 0x83, 0x1e, 0x5b, 0x0a, 0xc7, 0x90, 0xbb, 0x68, 0x83,
+       0xd6, 0x36, 0xad, 0x1d, 0x79, 0x18, 0xfc, 0x8e, 0x1a, 0x93, 0x67, 0x17,
+       0xa7, 0x16, 0xca, 0x3a, 0x60, 0xc1, 0xf3, 0x51, 0xf4, 0xa1, 0x7f, 0x97,
+       0x2a, 0x5c, 0xa7, 0xcb, 0xbb, 0x15, 0x43, 0x7e, 0x8e, 0xbc, 0xee, 0x3d,
+       0xfb, 0xe2, 0x14, 0x6c, 0xb0, 0x0f, 0xf1, 0x0a, 0xb5, 0xd0, 0x1e, 0xc6,
+       0x8c, 0x01, 0x13, 0xcf, 0x3c, 0x7e, 0x87, 0x91, 0xe7, 0x5d, 0x7b, 0xcd,
+       0x27, 0xc1, 0x93, 0xb6, 0x18, 0xd6, 0x10, 0xde, 0x04, 0x6d, 0x5d, 0xd0,
+       0xc1, 0xb4, 0x35, 0x21, 0xdd, 0x96, 0xca, 0x9d, 0x34, 0xce, 0x07, 0x7e,
+       0xf2, 0xe3, 0xf3, 0xe4, 0xb3, 0x01, 0x1d, 0xe2, 0x98, 0xef, 0xe8, 0xcf,
+       0x89, 0x2f, 0x7d, 0x30, 0x8b, 0xc3, 0x5c, 0xaa, 0x04, 0xfd, 0x68, 0x4e,
+       0xb4, 0x28, 0xa6, 0xd2, 0x4f, 0xe7, 0x61, 0xab, 0x1c, 0x8f, 0x8b, 0x92,
+       0xc1, 0x26, 0x79, 0x52, 0x8f, 0x56, 0xa7, 0x66, 0x6c, 0xca, 0xd5, 0x92,
+       0xe9, 0x72, 0x24, 0x57, 0xca, 0x08, 0x75, 0x66, 0xe5, 0xdb, 0x90, 0xab,
+       0x1e, 0xd6, 0x20, 0xf0, 0x03, 0x73, 0x94, 0x2f, 0xea, 0xc4, 0x0a, 0xf2,
+       0xb0, 0x8a, 0xc4, 0x83, 0x1a, 0xea, 0x19, 0xd4, 0x1d, 0x90, 0x5f, 0x79,
+       0x0e, 0x38, 0x12, 0x78, 0x2e, 0xe1, 0x99, 0xc4, 0xf3, 0x2c, 0x9e, 0xfd,
+       0x78, 0xd6, 0x68, 0x1f, 0x61, 0xde, 0xf3, 0x31, 0x7a, 0x60, 0x27, 0x79,
+       0xda, 0xb4, 0x7c, 0xaf, 0x9e, 0x91, 0xbf, 0xad, 0x1f, 0x94, 0xbf, 0xa9,
+       0x8f, 0xca, 0x5f, 0xd7, 0x1d, 0x79, 0xb9, 0xbe, 0x5f, 0xfe, 0xaa, 0x3e,
+       0xcc, 0x9a, 0x10, 0x39, 0x5c, 0x0a, 0xbe, 0xf9, 0xbc, 0x3c, 0xe8, 0xd5,
+       0xe1, 0x73, 0x28, 0xff, 0x8b, 0x53, 0xd9, 0xda, 0x75, 0x52, 0x78, 0xd6,
+       0x42, 0x9e, 0x69, 0xb0, 0x2e, 0x93, 0xc7, 0x9c, 0x3b, 0xe2, 0x94, 0xbd,
+       0x6e, 0xb3, 0x4e, 0x39, 0x49, 0x38, 0xd4, 0xbb, 0x1a, 0xf2, 0x97, 0x16,
+       0x99, 0x48, 0xa4, 0x57, 0x5c, 0x23, 0x19, 0xfa, 0xa3, 0x3b, 0x01, 0x87,
+       0x3d, 0xbd, 0x0e, 0x59, 0x7b, 0x1e, 0xb6, 0xe0, 0xa0, 0x56, 0x4e, 0xc4,
+       0xe0, 0xfb, 0x54, 0x7e, 0xa2, 0x7c, 0x4b, 0xe0, 0x4b, 0xa3, 0x9a, 0x91,
+       0x73, 0xd9, 0x70, 0x8e, 0xf1, 0xd1, 0x02, 0xec, 0x72, 0x18, 0x43, 0xb6,
+       0xe2, 0xa4, 0x6f, 0x3c, 0x16, 0xfa, 0xc7, 0x15, 0x39, 0xe1, 0x0d, 0x66,
+       0xaf, 0x20, 0xf6, 0x68, 0x2d, 0x51, 0x5e, 0xb4, 0x0b, 0xb4, 0xf9, 0xfe,
+       0xdd, 0xac, 0xbf, 0xe3, 0xa6, 0xfc, 0x70, 0x36, 0x6d, 0x3d, 0xa2, 0xcf,
+       0x40, 0xce, 0xbe, 0x7f, 0xd4, 0x4e, 0x9f, 0x9a, 0xd0, 0x3b, 0xe5, 0x27,
+       0xcf, 0x30, 0x26, 0xaf, 0x4e, 0x7d, 0x1f, 0x7a, 0x50, 0x5d, 0x6a, 0x95,
+       0x6a, 0xd5, 0x94, 0x4b, 0x23, 0x83, 0x6a, 0xdf, 0x6a, 0x2d, 0x8e, 0x3c,
+       0xaf, 0x4d, 0xa6, 0xfb, 0x94, 0xb2, 0xc3, 0x6f, 0x0f, 0x2b, 0xbf, 0xed,
+       0xda, 0x78, 0xd6, 0x92, 0xd6, 0x66, 0x5a, 0x5e, 0x96, 0x82, 0x07, 0x1d,
+       0x8b, 0xef, 0x02, 0x4f, 0xd8, 0x1f, 0xb4, 0x0a, 0x3a, 0x62, 0xa0, 0x39,
+       0x68, 0x3d, 0xa8, 0xff, 0xd2, 0xff, 0x1d, 0x93, 0x7c, 0x7c, 0x1b, 0xb1,
+       0x85, 0xb1, 0x52, 0x53, 0x7a, 0xb7, 0xb0, 0xf4, 0x53, 0x8b, 0xfe, 0x65,
+       0xa5, 0xb6, 0x2b, 0x1c, 0xd3, 0xbf, 0x73, 0xdc, 0x2e, 0x2f, 0x57, 0xb7,
+       0xcb, 0x62, 0x95, 0xef, 0x5b, 0x65, 0xa1, 0x3a, 0x78, 0xa5, 0x57, 0xef,
+       0x93, 0xd5, 0xeb, 0x6e, 0xb4, 0xee, 0xd7, 0xc1, 0x93, 0x63, 0x1f, 0xc9,
+       0x07, 0x23, 0xdd, 0xf2, 0xd6, 0x7d, 0xe9, 0x17, 0xfe, 0x44, 0x87, 0x3e,
+       0x8e, 0x74, 0xd0, 0xce, 0xd0, 0xe7, 0x7c, 0xfa, 0x4a, 0x56, 0xa7, 0x9e,
+       0xfd, 0x00, 0xfa, 0x95, 0xae, 0x04, 0x3a, 0x49, 0xdc, 0xc4, 0x0b, 0xf9,
+       0xd8, 0x6f, 0x00, 0x27, 0xde, 0xd5, 0x06, 0x81, 0xeb, 0x0d, 0xc5, 0x8b,
+       0xbb, 0x9d, 0xf4, 0x15, 0x84, 0x28, 0xff, 0x92, 0x3d, 0x38, 0x3c, 0xa0,
+       0xef, 0x92, 0x6a, 0xf2, 0x46, 0xeb, 0xbb, 0x88, 0x07, 0xd9, 0x44, 0xfa,
+       0xd4, 0x45, 0x59, 0x9d, 0xba, 0x60, 0x53, 0x17, 0x69, 0xc3, 0xff, 0x80,
+       0x9c, 0xd4, 0x92, 0x4a, 0x8d, 0xbe, 0x8b, 0xb8, 0x58, 0x17, 0xec, 0xb5,
+       0x4e, 0x80, 0x06, 0x77, 0x3f, 0xde, 0x61, 0xde, 0xf8, 0x3c, 0xe5, 0xd6,
+       0xc2, 0xb5, 0xc3, 0x59, 0xbd, 0x7f, 0x0b, 0x8f, 0x06, 0xad, 0x43, 0x3a,
+       0xf7, 0xfb, 0x2f, 0xec, 0xfb, 0x3e, 0x68, 0x1d, 0xc4, 0x5a, 0xc4, 0xd0,
+       0x64, 0xe3, 0x1e, 0x3f, 0x52, 0x7b, 0x3c, 0x5b, 0x43, 0x0e, 0xb8, 0xbe,
+       0x07, 0xe6, 0x6a, 0x3a, 0xce, 0x69, 0x2a, 0xb9, 0x5c, 0x1a, 0x21, 0x7f,
+       0x6f, 0xef, 0x61, 0x2c, 0x37, 0x32, 0x2f, 0x85, 0x79, 0x46, 0x4c, 0x7e,
+       0x8c, 0xba, 0x6b, 0x12, 0xfe, 0x7f, 0x61, 0xef, 0x20, 0x68, 0x40, 0x7d,
+       0x9a, 0x54, 0xf1, 0x7c, 0xca, 0x05, 0x8e, 0x9c, 0xc2, 0xfd, 0xa6, 0x2c,
+       0x01, 0xf7, 0x38, 0xf9, 0x00, 0xdc, 0x33, 0x9c, 0x57, 0x32, 0xc0, 0x7c,
+       0x2d, 0x05, 0xbc, 0xbd, 0xa1, 0xff, 0x8b, 0x43, 0x57, 0xf7, 0x59, 0x77,
+       0x4b, 0x2c, 0xf4, 0x7f, 0x71, 0x79, 0xeb, 0x79, 0xe8, 0x7d, 0x9c, 0xfa,
+       0x93, 0xe8, 0xd9, 0xd0, 0x9f, 0x46, 0xfc, 0xad, 0x92, 0xaf, 0xc4, 0x80,
+       0x17, 0x39, 0xf7, 0x28, 0xf1, 0x62, 0x5c, 0xa5, 0x2e, 0x17, 0x43, 0x5d,
+       0xee, 0x08, 0x71, 0xaf, 0x41, 0x97, 0xd3, 0xa9, 0x55, 0x9d, 0xf5, 0xd5,
+       0x4e, 0x55, 0xf3, 0x1a, 0xb0, 0xaf, 0x42, 0x99, 0xb1, 0x88, 0xb6, 0x75,
+       0x71, 0x6a, 0x12, 0x35, 0x6c, 0xa1, 0x7c, 0x50, 0x2f, 0xd4, 0x47, 0xf5,
+       0x82, 0x47, 0x7d, 0xdb, 0x6b, 0x2d, 0x28, 0x1e, 0x27, 0x65, 0xa1, 0xfe,
+       0x81, 0x5f, 0xda, 0xbb, 0x0d, 0x7d, 0xe8, 0xfe, 0x38, 0xe5, 0x7b, 0x3d,
+       0xe9, 0x42, 0x50, 0x27, 0xbf, 0x13, 0x72, 0x66, 0xe8, 0x7b, 0xdd, 0xcc,
+       0xd1, 0x96, 0x87, 0x88, 0x1f, 0x74, 0x24, 0x12, 0xb2, 0xe8, 0x71, 0x8f,
+       0xd5, 0x29, 0xf2, 0xb2, 0x30, 0x67, 0xc9, 0x09, 0x25, 0x3f, 0x9e, 0x9b,
+       0xf7, 0x47, 0x86, 0x4c, 0xc6, 0x07, 0xad, 0x47, 0x25, 0x7d, 0x65, 0xcd,
+       0x48, 0xbf, 0x30, 0x81, 0xb8, 0xba, 0x30, 0x6f, 0x88, 0xab, 0xea, 0x30,
+       0xca, 0x28, 0x5d, 0x81, 0x35, 0x86, 0x67, 0xbf, 0xa7, 0xe1, 0xec, 0x5d,
+       0x72, 0xe1, 0xf9, 0xcf, 0xc3, 0xee, 0x5f, 0x81, 0x2c, 0xcc, 0xd4, 0x71,
+       0xe4, 0x19, 0xcf, 0xc9, 0xa0, 0x55, 0x42, 0xfe, 0x0c, 0xbe, 0xa3, 0xbd,
+       0xa2, 0x6c, 0x60, 0x41, 0xc7, 0xb8, 0x9f, 0x7c, 0xe2, 0x78, 0xb7, 0x2c,
+       0xf4, 0x05, 0x36, 0xce, 0x77, 0x03, 0xc0, 0x11, 0xbc, 0xe3, 0xf8, 0xb7,
+       0x64, 0x40, 0xbd, 0xab, 0xaa, 0x75, 0x25, 0xe9, 0x0d, 0xe5, 0xf7, 0x18,
+       0xf6, 0x24, 0x8f, 0xa3, 0xf9, 0x4e, 0x09, 0x6c, 0x29, 0xe2, 0xbb, 0x25,
+       0x47, 0x6b, 0x09, 0xb9, 0xa7, 0x96, 0x94, 0x2f, 0xd7, 0xfa, 0x25, 0x0f,
+       0x39, 0x4e, 0x8e, 0x3e, 0xd9, 0xc3, 0xb3, 0xe5, 0x96, 0xd2, 0x2f, 0x88,
+       0x4e, 0x5a, 0xab, 0x72, 0xdc, 0x8b, 0xe8, 0xe9, 0x08, 0xe9, 0x33, 0xc3,
+       0x71, 0x2c, 0xa4, 0xa1, 0x11, 0x5f, 0x07, 0x70, 0x65, 0x81, 0xe7, 0xa5,
+       0x10, 0x0f, 0xfd, 0x08, 0x68, 0x3d, 0x96, 0x94, 0x25, 0x8f, 0x74, 0x6c,
+       0x97, 0x52, 0x82, 0xfd, 0x57, 0xa0, 0x6f, 0xc4, 0xb3, 0x8d, 0xf9, 0xcd,
+       0x26, 0x1e, 0x3f, 0x5c, 0x2b, 0x82, 0xc7, 0xe4, 0x2f, 0xe1, 0xe0, 0xaf,
+       0xbf, 0x40, 0xf9, 0xed, 0x43, 0x8e, 0x6f, 0x07, 0xba, 0x69, 0x6d, 0xec,
+       0x99, 0x9f, 0xeb, 0x82, 0xac, 0xb8, 0x6f, 0xbb, 0x1c, 0x83, 0xdd, 0xe7,
+       0xaa, 0xdc, 0xff, 0x18, 0xf4, 0xe8, 0x2d, 0xb5, 0x7f, 0x7e, 0xa9, 0x2f,
+       0x5c, 0xcf, 0xb5, 0x5d, 0x5b, 0xd6, 0xb6, 0xca, 0xa1, 0x8a, 0x75, 0x8d,
+       0xf5, 0xbf, 0x8f, 0xf5, 0xba, 0x9c, 0x1e, 0xe5, 0x7a, 0xe2, 0x01, 0x5c,
+       0x35, 0xf1, 0x29, 0x78, 0xe2, 0xaa, 0xde, 0xcf, 0x55, 0x5b, 0x25, 0x57,
+       0x89, 0x70, 0x11, 0xcf, 0x47, 0xa8, 0x87, 0xbf, 0xaa, 0x70, 0x4d, 0x2a,
+       0x5c, 0x78, 0x5f, 0xa5, 0xcf, 0xb9, 0x15, 0xeb, 0x3b, 0xe8, 0xff, 0xa5,
+       0x14, 0xef, 0x94, 0x92, 0xaa, 0xe9, 0xdb, 0x95, 0xaf, 0x29, 0xc5, 0xdb,
+       0xf0, 0xbe, 0x13, 0x36, 0xbf, 0x0f, 0xb9, 0x45, 0x17, 0xeb, 0xdc, 0x2d,
+       0x73, 0x5b, 0xe9, 0x8f, 0x6d, 0xa1, 0x3f, 0x06, 0xb8, 0x5e, 0xec, 0x19,
+       0xc0, 0xe5, 0x01, 0x37, 0x3d, 0x07, 0x3e, 0x3b, 0xf4, 0x2b, 0x8c, 0x93,
+       0xd7, 0x29, 0x5a, 0xa6, 0x97, 0xfe, 0x1b, 0xe7, 0xea, 0xc3, 0xda, 0x68,
+       0x1c, 0xf0, 0xe1, 0x69, 0xe0, 0x99, 0xab, 0xaa, 0xbb, 0x0b, 0xc8, 0x60,
+       0x7b, 0x9c, 0x67, 0x2f, 0x55, 0x3f, 0x8b, 0x67, 0xd7, 0x35, 0xf0, 0x8b,
+       0xbc, 0x22, 0xbd, 0xa4, 0x95, 0xf7, 0x48, 0xb0, 0x37, 0x07, 0x7a, 0x1c,
+       0x37, 0x24, 0x3f, 0x6a, 0x21, 0x3f, 0xe7, 0x3d, 0x2c, 0xed, 0xd2, 0xe2,
+       0xdd, 0x67, 0x4c, 0xb7, 0x19, 0x6b, 0x4d, 0x75, 0xf6, 0xe3, 0x4b, 0xbc,
+       0x8b, 0x4d, 0xf1, 0xee, 0x6e, 0x98, 0xd7, 0x18, 0x8f, 0x2c, 0xd9, 0xf2,
+       0x78, 0x6d, 0x58, 0x1e, 0xad, 0xa5, 0xad, 0xfb, 0xe1, 0x03, 0x0a, 0xeb,
+       0x77, 0xb4, 0x43, 0x71, 0xfa, 0x2f, 0x13, 0x79, 0x60, 0x8b, 0x1d, 0xe4,
+       0x05, 0x25, 0xd6, 0x6c, 0x73, 0x69, 0xde, 0xe3, 0x58, 0x55, 0xd9, 0x9a,
+       0x3b, 0xfc, 0x5f, 0xe6, 0x0d, 0xdc, 0x9f, 0xfe, 0x1a, 0x79, 0x82, 0x87,
+       0x3c, 0xc1, 0x43, 0x9e, 0xe0, 0x21, 0x4f, 0xf0, 0x90, 0x27, 0x78, 0xc8,
+       0x13, 0x3c, 0xe4, 0x09, 0x1e, 0xf2, 0x04, 0xc4, 0xee, 0xa0, 0x5e, 0x18,
+       0x43, 0xfe, 0x0b, 0xff, 0xe5, 0xdd, 0x06, 0x3e, 0xf1, 0xfe, 0x92, 0x31,
+       0x87, 0xb1, 0x99, 0x73, 0xab, 0xdb, 0x5c, 0xca, 0x4d, 0xf9, 0xbe, 0x3b,
+       0x31, 0x37, 0x1e, 0xe6, 0x23, 0x84, 0x89, 0x62, 0x37, 0xe1, 0xe4, 0xa0,
+       0xeb, 0x68, 0xb0, 0x31, 0xe6, 0x2b, 0x41, 0xcc, 0x0a, 0x72, 0xe5, 0xb7,
+       0x91, 0xb3, 0xa4, 0x90, 0xb3, 0xf4, 0x23, 0x3f, 0xe1, 0x9d, 0x75, 0x74,
+       0xc7, 0x94, 0xd5, 0x8e, 0x7a, 0x63, 0xda, 0x3d, 0x1e, 0x73, 0x69, 0x3b,
+       0x55, 0xd0, 0xf5, 0xb9, 0x5e, 0xf1, 0x25, 0x37, 0xf2, 0x4d, 0xe4, 0xad,
+       0xcf, 0xa9, 0xfb, 0xb4, 0xf1, 0x21, 0xca, 0xbc, 0xf2, 0x09, 0xb9, 0x6b,
+       0xc4, 0xdf, 0xe0, 0x1e, 0x50, 0x5f, 0x20, 0xff, 0x44, 0x7a, 0xce, 0x81,
+       0xe1, 0xe7, 0x62, 0x12, 0x3f, 0xb3, 0x1d, 0x73, 0x96, 0xf4, 0xaa, 0xbb,
+       0x24, 0x88, 0xf2, 0xdc, 0x55, 0xc8, 0xcb, 0x16, 0xfd, 0x1c, 0x6f, 0x1c,
+       0x88, 0x97, 0xfe, 0x75, 0x65, 0x2a, 0x57, 0x5d, 0x51, 0x3a, 0x75, 0xb4,
+       0x96, 0x47, 0x7d, 0xd4, 0xd3, 0x2b, 0xed, 0x26, 0x6a, 0xab, 0x08, 0x37,
+       0x71, 0xfe, 0x32, 0xae, 0x6a, 0x9e, 0x73, 0xeb, 0xf2, 0x84, 0xac, 0xb9,
+       0xcf, 0xca, 0x54, 0xa9, 0x92, 0x4e, 0xb2, 0x56, 0xce, 0x5a, 0x2b, 0x53,
+       0x27, 0x81, 0x63, 0x11, 0xb9, 0x81, 0xa1, 0xf6, 0x5e, 0x99, 0x9a, 0xae,
+       0x04, 0xf7, 0x59, 0x01, 0x0d, 0x8c, 0x57, 0xed, 0x62, 0x2c, 0x04, 0xf7,
+       0x5a, 0xba, 0x5a, 0xcb, 0x75, 0x5c, 0x6f, 0x62, 0x1d, 0xe5, 0x36, 0x8c,
+       0xb5, 0x94, 0x1d, 0x69, 0x58, 0x99, 0x2a, 0x56, 0x1b, 0x69, 0x20, 0x1e,
+       0xe2, 0x8d, 0xce, 0xc3, 0xb3, 0xc4, 0x45, 0x3f, 0xe3, 0xfb, 0x85, 0x91,
+       0xfe, 0x30, 0xef, 0x3a, 0x89, 0xfc, 0xce, 0x0c, 0xf4, 0x5c, 0x8d, 0xbf,
+       0xa3, 0xe2, 0x54, 0x4a, 0xe7, 0x3c, 0x9f, 0x78, 0x37, 0xba, 0x80, 0x39,
+       0x8c, 0x17, 0x23, 0x58, 0x3d, 0x84, 0xed, 0x6c, 0xe0, 0x67, 0x4b, 0xb8,
+       0x1f, 0x69, 0xe2, 0x39, 0x2f, 0x61, 0x2f, 0xd2, 0x45, 0x98, 0x38, 0x68,
+       0x83, 0x2c, 0xbd, 0xff, 0x2d, 0xef, 0x1b, 0xcf, 0x44, 0x9e, 0x9a, 0x58,
+       0x43, 0x78, 0xe2, 0x88, 0xd6, 0xe0, 0xc5, 0xb9, 0x60, 0x9d, 0xbe, 0x7e,
+       0xff, 0xf7, 0x69, 0xfb, 0x36, 0xd2, 0x1a, 0xed, 0x1f, 0xe1, 0x19, 0x0e,
+       0xe4, 0xb6, 0xbe, 0x5e, 0xfd, 0x9f, 0x61, 0x78, 0x42, 0x17, 0x3f, 0x76,
+       0x8f, 0x3a, 0xdc, 0x50, 0x87, 0x46, 0xf7, 0x17, 0xbc, 0x0f, 0x60, 0x7d,
+       0xcf, 0x6f, 0x07, 0x8d, 0xb5, 0xe2, 0xcb, 0x61, 0x2c, 0xdb, 0x29, 0x59,
+       0x93, 0x75, 0xc3, 0xf9, 0x70, 0xbc, 0x03, 0xb1, 0x8d, 0xe3, 0x3a, 0xf8,
+       0x0b, 0x5d, 0x76, 0xda, 0xc3, 0xba, 0x25, 0x1e, 0x7c, 0xe3, 0x19, 0xa6,
+       0x1d, 0xb1, 0xee, 0x6b, 0x0b, 0xe7, 0x22, 0x3b, 0xa2, 0x1f, 0x36, 0xc3,
+       0x39, 0xfa, 0x5b, 0x1d, 0xb5, 0x0b, 0xfb, 0xc0, 0xb3, 0xd8, 0x68, 0x4b,
+       0xd1, 0x33, 0x2e, 0x67, 0xe7, 0x23, 0xbf, 0x05, 0x9f, 0x32, 0x64, 0x86,
+       0xbe, 0xbf, 0x03, 0xbe, 0xaf, 0x4b, 0x0e, 0xc1, 0x67, 0x1d, 0x86, 0xcf,
+       0x3a, 0x82, 0x7a, 0x71, 0x6c, 0xa9, 0xf1, 0x9e, 0x97, 0x35, 0x6a, 0x97,
+       0x76, 0x5c, 0xc9, 0xbf, 0xe8, 0x1b, 0xf6, 0x47, 0xd0, 0x01, 0xd6, 0x5d,
+       0x91, 0x4e, 0xc0, 0xdf, 0x3a, 0x71, 0xe8, 0xc4, 0xd6, 0xfb, 0xe4, 0x61,
+       0xd8, 0x46, 0x7b, 0x56, 0xc5, 0x86, 0xa5, 0x80, 0xf7, 0xa5, 0x6a, 0xc0,
+       0x7b, 0xf8, 0x65, 0xe0, 0x37, 0xa5, 0x58, 0xb3, 0xa4, 0x88, 0x7d, 0x8b,
+       0xd8, 0xb7, 0x88, 0x3a, 0x6f, 0xba, 0xd6, 0xf8, 0x1d, 0xab, 0x33, 0xa4,
+       0x9d, 0x6b, 0xa3, 0xbe, 0xd5, 0x70, 0xfe, 0xe8, 0x79, 0x0a, 0xfc, 0x7f,
+       0x0c, 0xfc, 0x3f, 0x81, 0xfa, 0xe6, 0x8f, 0x50, 0xdf, 0x7c, 0x0d, 0xf5,
+       0xcd, 0x71, 0xd4, 0x37, 0x13, 0xa8, 0x6f, 0xbe, 0x0a, 0xff, 0xf1, 0x15,
+       0xf8, 0x8f, 0x63, 0xf0, 0x1f, 0xe3, 0xea, 0xee, 0xe9, 0xa8, 0xb7, 0xf5,
+       0x4e, 0x25, 0xda, 0x8b, 0xed, 0x67, 0x22, 0x76, 0x11, 0x67, 0x1a, 0x93,
+       0x6a, 0x9d, 0xf5, 0x8d, 0x23, 0xee, 0x41, 0xd6, 0x37, 0xc7, 0xb4, 0x09,
+       0xe4, 0xef, 0xf7, 0xef, 0x67, 0xdd, 0x13, 0xd7, 0x72, 0xaa, 0xee, 0x49,
+       0x9f, 0x77, 0x91, 0x22, 0x21, 0xf7, 0xc3, 0x99, 0xd3, 0x67, 0x73, 0xa0,
+       0x25, 0xc8, 0xf9, 0x7a, 0x42, 0xbf, 0xd7, 0x21, 0x8b, 0xb3, 0xa8, 0x19,
+       0xbc, 0x1f, 0x6b, 0x05, 0xe5, 0x1b, 0x2d, 0x8c, 0x51, 0x2b, 0x7b, 0xff,
+       0x1c, 0x8e, 0x47, 0x64, 0x72, 0x1e, 0xb5, 0xed, 0xf3, 0xff, 0xa8, 0xe5,
+       0xd4, 0xd8, 0xc1, 0x18, 0xf9, 0xee, 0xf3, 0x7f, 0x1f, 0x8e, 0x8b, 0xa1,
+       0x3e, 0x84, 0xb4, 0x5a, 0x0e, 0x9e, 0xdd, 0x61, 0xce, 0xf1, 0x6a, 0xef,
+       0xe6, 0xff, 0xd3, 0x8e, 0xad, 0x45, 0x13, 0xfb, 0x1b, 0x3b, 0x82, 0xfa,
+       0xac, 0x71, 0xbe, 0xab, 0x61, 0xfe, 0x8a, 0xfa, 0xce, 0x5a, 0x28, 0xb7,
+       0xfd, 0x0a, 0x1e, 0x58, 0x96, 0x86, 0x98, 0xe7, 0x7d, 0xe4, 0xf3, 0xfb,
+       0x9f, 0xab, 0xb7, 0xab, 0x6f, 0x72, 0xae, 0xca, 0xb7, 0x61, 0xe7, 0x23,
+       0xa5, 0x1d, 0x81, 0x2f, 0x60, 0x3f, 0xa1, 0x05, 0xfe, 0xfd, 0x8f, 0x81,
+       0x07, 0xbc, 0xf6, 0x1a, 0x6b, 0x38, 0x2b, 0xbc, 0x4b, 0xb9, 0x32, 0xc5,
+       0xdc, 0xba, 0xa4, 0x70, 0xb3, 0xd6, 0x63, 0xdd, 0x17, 0xc5, 0x80, 0x08,
+       0xd7, 0xcf, 0x13, 0x01, 0xdd, 0xe3, 0xa8, 0xe9, 0x08, 0x13, 0x8d, 0x1b,
+       0xeb, 0xbf, 0x8e, 0xf0, 0x1e, 0xee, 0x4a, 0x90, 0x57, 0x29, 0x7c, 0x66,
+       0x88, 0xef, 0x3f, 0xfd, 0xc0, 0xf7, 0x70, 0xbd, 0xd5, 0xb0, 0xfe, 0x3c,
+       0x72, 0x3d, 0xde, 0x99, 0xec, 0x52, 0xdf, 0x19, 0xdf, 0x9f, 0xed, 0x94,
+       0x5f, 0x3c, 0xe3, 0xfb, 0xe3, 0x4e, 0x7a, 0xf8, 0x4d, 0xd4, 0x1e, 0x67,
+       0x68, 0x27, 0x23, 0xa4, 0x73, 0x30, 0x35, 0x2d, 0x03, 0xbd, 0x41, 0x2e,
+       0xfe, 0x75, 0xed, 0xe3, 0x74, 0xeb, 0xe1, 0x3e, 0x3f, 0x6c, 0xd8, 0x27,
+       0xd5, 0xb0, 0xcf, 0x0a, 0x6d, 0xb6, 0x7a, 0x2f, 0xce, 0x5c, 0xdc, 0x75,
+       0xa3, 0x95, 0x08, 0xeb, 0xb2, 0x47, 0x47, 0xda, 0xa4, 0xd2, 0x97, 0x5e,
+       0xf9, 0x11, 0xf2, 0xf5, 0xc2, 0x08, 0xe6, 0x12, 0x83, 0x78, 0xc7, 0xf9,
+       0x74, 0x15, 0xb9, 0xe8, 0x4a, 0x55, 0x86, 0xb0, 0x3e, 0x5d, 0x14, 0xe1,
+       0x3c, 0xfb, 0x8a, 0xb6, 0x6a, 0xe8, 0x03, 0x92, 0x6b, 0x38, 0xf3, 0x04,
+       0xea, 0xaf, 0x13, 0xeb, 0xf5, 0x30, 0xf7, 0xb9, 0x59, 0x5b, 0x53, 0xb9,
+       0xf1, 0x01, 0xad, 0x98, 0x08, 0xce, 0xf8, 0x87, 0xf0, 0x17, 0x86, 0xce,
+       0xb5, 0xef, 0x03, 0xb7, 0x26, 0x0b, 0xcf, 0x18, 0xea, 0x0e, 0xb6, 0x30,
+       0x42, 0x59, 0xf3, 0x79, 0x2d, 0xde, 0x45, 0x67, 0xfa, 0xf3, 0xf0, 0x4c,
+       0xd9, 0xb0, 0x9e, 0x8e, 0xce, 0x14, 0x93, 0x77, 0x67, 0x2d, 0xac, 0xfd,
+       0x1c, 0xf8, 0x91, 0x97, 0xa5, 0x7a, 0xea, 0x33, 0xf0, 0x94, 0x1b, 0x78,
+       0x63, 0x6e, 0x91, 0x61, 0x71, 0xa3, 0x86, 0x1f, 0x4f, 0xc2, 0x0e, 0xbf,
+       0xd1, 0x1b, 0xdd, 0x0d, 0x1b, 0xb6, 0xcf, 0xba, 0x07, 0x8d, 0xf3, 0xfd,
+       0xb0, 0xc5, 0x14, 0xec, 0x93, 0x39, 0x53, 0x9e, 0xb5, 0x0a, 0xed, 0xc9,
+       0x72, 0x8d, 0xb4, 0x75, 0x4c, 0x86, 0x51, 0xef, 0xf0, 0xfc, 0x19, 0x59,
+       0xac, 0x47, 0x34, 0x8c, 0xc2, 0x1e, 0x0f, 0xe2, 0xb7, 0x1f, 0xef, 0x1c,
+       0xfc, 0x58, 0x2b, 0xad, 0xc8, 0xe3, 0x2a, 0x17, 0x47, 0xae, 0x3d, 0x44,
+       0xfa, 0xee, 0x04, 0x3c, 0xf5, 0x99, 0x7a, 0x7a, 0xa7, 0xb8, 0x7d, 0xf4,
+       0x15, 0x49, 0xe0, 0xc6, 0x1a, 0xef, 0x22, 0x6c, 0xbd, 0x1f, 0xcf, 0xb4,
+       0x55, 0x20, 0x6f, 0x15, 0x7e, 0xdf, 0x37, 0x46, 0xf9, 0x8d, 0xe2, 0x7c,
+       0x38, 0x1e, 0xb4, 0xbe, 0x4c, 0xdd, 0x4b, 0xee, 0x96, 0x95, 0xf9, 0x28,
+       0x0e, 0x9e, 0x86, 0x0d, 0xf2, 0xce, 0x76, 0x0c, 0x7c, 0xe1, 0x58, 0x0b,
+       0xe3, 0x21, 0xe6, 0x17, 0x97, 0x71, 0xee, 0x8c, 0x9c, 0x41, 0xfd, 0x2f,
+       0x7d, 0x7c, 0xa6, 0x80, 0x7f, 0x7b, 0xa8, 0xef, 0x9b, 0xd7, 0x1b, 0x36,
+       0xfb, 0x63, 0xa0, 0xcf, 0x6c, 0x58, 0xcf, 0x35, 0x41, 0x7d, 0xb2, 0x26,
+       0x88, 0xc7, 0x49, 0xff, 0x76, 0x3d, 0xf3, 0xa2, 0x3c, 0xa0, 0xce, 0x54,
+       0x93, 0xe3, 0xf3, 0xbe, 0xef, 0x8e, 0x0e, 0x0e, 0x2f, 0x4a, 0x7a, 0xf8,
+       0xa4, 0xec, 0xb3, 0x0e, 0xb1, 0x1e, 0xb3, 0x88, 0xc7, 0xbf, 0xbd, 0x25,
+       0xe3, 0xfb, 0xa7, 0x41, 0xfb, 0xf7, 0xd5, 0x3e, 0x2f, 0x82, 0x7e, 0xf0,
+       0x4a, 0xd5, 0x24, 0xa4, 0x15, 0xcf, 0x04, 0xe9, 0x2d, 0xcb, 0xf1, 0xfa,
+       0x85, 0x50, 0x36, 0x8f, 0x89, 0xeb, 0x5d, 0x36, 0x5c, 0xbb, 0x0c, 0xd8,
+       0x85, 0x90, 0xb6, 0x0c, 0xe8, 0xc5, 0xfe, 0xf5, 0xb7, 0x13, 0xf4, 0x0d,
+       0x94, 0xb9, 0x8b, 0xac, 0xd1, 0x1d, 0x41, 0x1e, 0x95, 0xf8, 0x24, 0x3f,
+       0x10, 0x97, 0xcd, 0x7e, 0x80, 0xeb, 0xe2, 0xd7, 0xd0, 0x15, 0xd2, 0x51,
+       0x54, 0xfe, 0x53, 0xc5, 0x2d, 0x85, 0xcf, 0xd8, 0xe2, 0x0b, 0x2a, 0xea,
+       0xb9, 0x6a, 0xd0, 0x37, 0x31, 0xfe, 0x51, 0x87, 0xbb, 0xe0, 0xff, 0xa0,
+       0x83, 0xb0, 0xe3, 0xdc, 0x3c, 0xef, 0x27, 0x86, 0x78, 0xaf, 0x74, 0x36,
+       0x0f, 0xd9, 0x2e, 0xf0, 0xfb, 0x63, 0x22, 0xa8, 0x31, 0x83, 0xfa, 0x2b,
+       0x45, 0x5f, 0x88, 0xb6, 0xa4, 0xfc, 0x64, 0x5e, 0x7d, 0x6f, 0x8c, 0x03,
+       0xc6, 0xa7, 0xef, 0x6c, 0xf8, 0x9b, 0x89, 0x1f, 0x64, 0x83, 0xbf, 0x99,
+       0x08, 0xbf, 0xfd, 0x56, 0x83, 0x3c, 0xe2, 0xe1, 0x9a, 0x29, 0x13, 0xb5,
+       0xe8, 0x6f, 0x28, 0x28, 0x07, 0xf8, 0xe6, 0x5a, 0x94, 0x3b, 0xf8, 0x41,
+       0x4d, 0xb3, 0x49, 0x96, 0x4b, 0x61, 0x4e, 0xc4, 0x1a, 0x80, 0x3c, 0xc4,
+       0x78, 0x31, 0xaa, 0x2f, 0x07, 0x20, 0x3f, 0xf0, 0x1c, 0x74, 0xbd, 0x3b,
+       0x1b, 0xd4, 0xb9, 0x25, 0xfa, 0xc5, 0xfe, 0xa8, 0xee, 0xdd, 0x25, 0xa5,
+       0x63, 0x7c, 0x1f, 0x93, 0x77, 0x66, 0x63, 0xea, 0x7d, 0x41, 0x62, 0xe1,
+       0x7b, 0x8e, 0xe3, 0x52, 0x50, 0xef, 0xab, 0x21, 0x3e, 0xd4, 0x69, 0x5f,
+       0x89, 0xc6, 0xa6, 0x76, 0xbc, 0x1e, 0xac, 0x9b, 0xac, 0x57, 0xe5, 0xf1,
+       0xfa, 0x2a, 0xce, 0xaf, 0x49, 0x6e, 0xbc, 0x28, 0xbb, 0x6d, 0x4b, 0xc5,
+       0x7d, 0x37, 0x4e, 0x1d, 0xa3, 0x7e, 0x8d, 0xa9, 0xba, 0xb3, 0x88, 0x7c,
+       0xa1, 0x30, 0xc2, 0x6f, 0x3c, 0xbf, 0xba, 0xab, 0x50, 0x4e, 0x5b, 0x59,
+       0xf9, 0xd0, 0x77, 0x4d, 0x8e, 0x45, 0x47, 0x3d, 0x74, 0xd7, 0xc3, 0xb5,
+       0x0b, 0x77, 0x05, 0x67, 0xc5, 0xfb, 0x1a, 0x61, 0x0d, 0xf5, 0x6d, 0xf6,
+       0x5f, 0x6f, 0x35, 0x65, 0xed, 0x56, 0xdf, 0xbf, 0xdf, 0xb1, 0xc4, 0x0d,
+       0x6b, 0x57, 0x4b, 0xd5, 0xae, 0xed, 0x2a, 0x07, 0x71, 0x47, 0x52, 0x5a,
+       0x1e, 0xf6, 0x7a, 0xc6, 0x43, 0x9d, 0xa3, 0xa7, 0x0f, 0xae, 0xea, 0x16,
+       0x62, 0x6e, 0x3a, 0x35, 0x27, 0x6e, 0x2f, 0xbf, 0x37, 0xcf, 0x38, 0x84,
+       0xd9, 0x19, 0xdc, 0x75, 0xdd, 0x34, 0xae, 0xfc, 0xac, 0x48, 0x18, 0x7b,
+       0x6e, 0x6a, 0xb4, 0x89, 0xc6, 0xdc, 0x92, 0xb6, 0x20, 0x13, 0x26, 0x68,
+       0x29, 0x95, 0xa3, 0x3c, 0x8d, 0x7f, 0x1b, 0xb0, 0x7a, 0xd7, 0xd3, 0xa0,
+       0x73, 0x1a, 0x74, 0xf2, 0x1c, 0xd3, 0xb5, 0x48, 0xe7, 0xa2, 0x5a, 0x81,
+       0x7d, 0xc4, 0x7c, 0x0f, 0x31, 0xdf, 0x43, 0xcc, 0xf7, 0x10, 0xf3, 0x3d,
+       0xc4, 0x7c, 0x0f, 0x31, 0xdf, 0x43, 0xcc, 0xf7, 0x10, 0xf3, 0xbd, 0xf1,
+       0x30, 0x4f, 0x7b, 0x62, 0x3d, 0x4f, 0x5b, 0xa9, 0xf3, 0x3b, 0x94, 0xa2,
+       0xa5, 0x58, 0x94, 0x20, 0xcf, 0x15, 0x9d, 0x39, 0x4d, 0x94, 0xe7, 0x5e,
+       0xfb, 0x9b, 0x48, 0xb0, 0x8e, 0x39, 0x1e, 0xd7, 0x15, 0x35, 0xdd, 0xe6,
+       0xba, 0x20, 0xcf, 0x63, 0x6d, 0xb5, 0x79, 0x0d, 0xf2, 0xb5, 0x0c, 0xfd,
+       0x19, 0xed, 0x22, 0x11, 0xd4, 0x8b, 0x99, 0xf3, 0xf7, 0xba, 0x88, 0xbf,
+       0x85, 0x9a, 0x8a, 0xc1, 0xbc, 0x17, 0xbc, 0x97, 0x7f, 0xb7, 0x00, 0x39,
+       0xf0, 0xdd, 0x7d, 0xac, 0x27, 0x0a, 0xb5, 0xa4, 0x14, 0x17, 0xa3, 0xfc,
+       0x07, 0xeb, 0xbc, 0x7d, 0x5a, 0xbe, 0x42, 0xd9, 0xea, 0x32, 0x9d, 0x00,
+       0x53, 0xec, 0xc6, 0xbc, 0xee, 0x4d, 0x55, 0x23, 0xad, 0xd4, 0x49, 0xcf,
+       0x7e, 0xd0, 0x16, 0xdd, 0xe3, 0x8a, 0x18, 0xb3, 0x09, 0xd1, 0x67, 0x91,
+       0xd3, 0xda, 0x43, 0xea, 0x6f, 0x1d, 0x7a, 0xb0, 0x8f, 0x3e, 0x3b, 0x10,
+       0xfd, 0x2d, 0x06, 0xeb, 0xae, 0xec, 0xc6, 0xfd, 0x2b, 0xcf, 0x91, 0x80,
+       0xbd, 0x7e, 0x69, 0x27, 0xce, 0x06, 0xb9, 0x5e, 0xde, 0xa1, 0xf2, 0x6e,
+       0xf8, 0xce, 0xd3, 0x43, 0xe9, 0x3e, 0xe9, 0xda, 0x25, 0x67, 0x86, 0x58,
+       0xa3, 0xb5, 0x01, 0x1f, 0x61, 0x79, 0xe7, 0xb4, 0x4b, 0x96, 0xe7, 0xe1,
+       0x5b, 0xe7, 0xd3, 0x0e, 0xff, 0xbe, 0x60, 0x01, 0x21, 0x6d, 0xa1, 0x3e,
+       0xd6, 0xc7, 0x98, 0xbc, 0x58, 0xa7, 0xae, 0xf4, 0x60, 0x7d, 0x3f, 0x74,
+       0x71, 0x1b, 0x6c, 0x48, 0xc7, 0xfe, 0x11, 0xee, 0xf7, 0x14, 0xee, 0x1e,
+       0xfb, 0xb7, 0x77, 0x2a, 0xdd, 0xd0, 0xd3, 0x56, 0x4a, 0x07, 0xed, 0x1f,
+       0xab, 0x2d, 0x1d, 0xe1, 0xf7, 0xc2, 0x69, 0xaf, 0xf1, 0xbb, 0xe1, 0x3e,
+       0xad, 0x50, 0xe1, 0xdf, 0x38, 0x0c, 0xc9, 0x21, 0x8b, 0x7f, 0xff, 0xb3,
+       0x4f, 0x7b, 0xa0, 0x4a, 0x18, 0x1b, 0x7d, 0xd6, 0xe1, 0xcb, 0xb0, 0xe5,
+       0xff, 0x29, 0xdc, 0xea, 0x62, 0xdb, 0x3a, 0xcb, 0xf0, 0xfb, 0x1d, 0xe7,
+       0xc7, 0x4d, 0xdd, 0xe4, 0x34, 0x71, 0x12, 0x27, 0xca, 0xc0, 0xc7, 0x39,
+       0x49, 0x3d, 0x39, 0xd5, 0x4e, 0xa2, 0x14, 0x22, 0x88, 0x84, 0xe5, 0xfc,
+       0xcc, 0x63, 0x14, 0x3c, 0xc8, 0xa6, 0x4e, 0x42, 0x55, 0x94, 0x74, 0x5b,
+       0x27, 0xee, 0xb8, 0x40, 0x5c, 0x80, 0x6a, 0x39, 0x69, 0xe9, 0x86, 0x3d,
+       0xa7, 0x5b, 0xba, 0x00, 0x57, 0x9e, 0xe3, 0xa4, 0x4d, 0xe7, 0xcc, 0x1a,
+       0x03, 0x69, 0x70, 0x41, 0x23, 0x33, 0x6d, 0xe3, 0x66, 0x37, 0x48, 0x5c,
+       0x57, 0x29, 0x83, 0x02, 0x6b, 0x2b, 0xb8, 0xe1, 0xef, 0xe2, 0xf0, 0x3c,
+       0xdf, 0x39, 0x76, 0xd3, 0xc0, 0x44, 0x24, 0xeb, 0x7c, 0xe7, 0x3b, 0xdf,
+       0xff, 0xf7, 0xbe, 0xcf, 0xfb, 0x9b, 0x6e, 0xb9, 0x08, 0x3a, 0xce, 0x8d,
+       0xb5, 0xfa, 0xfe, 0xd6, 0x0e, 0x9f, 0x87, 0x07, 0xfb, 0x7c, 0x19, 0xa5,
+       0x75, 0xc9, 0x9c, 0xd6, 0xa7, 0xbb, 0x0e, 0x7d, 0x7b, 0x16, 0x6b, 0x8a,
+       0xe0, 0x1c, 0x1e, 0xe9, 0xd3, 0x78, 0x64, 0xf0, 0xbd, 0xff, 0xd0, 0x7b,
+       0xdf, 0xa1, 0xf7, 0xde, 0xff, 0xd1, 0x9e, 0xe5, 0xc3, 0xf4, 0xc0, 0x75,
+       0x5a, 0x53, 0x1a, 0xfd, 0xf2, 0x93, 0x6a, 0x39, 0x6f, 0x25, 0xa9, 0x0b,
+       0xcc, 0x88, 0xab, 0x66, 0x9c, 0x36, 0x60, 0x5c, 0x9b, 0xac, 0xae, 0x83,
+       0xe6, 0xb1, 0x8f, 0x76, 0x9b, 0xf1, 0xf2, 0x89, 0x3e, 0xf2, 0x4c, 0x10,
+       0xd7, 0x60, 0xd8, 0xc3, 0x11, 0xb4, 0x73, 0x5f, 0x74, 0x12, 0xe6, 0x39,
+       0xed, 0xbf, 0xa1, 0x0e, 0xe3, 0xaa, 0x9c, 0xce, 0xfd, 0x60, 0x9b, 0x16,
+       0xb9, 0x6d, 0xa7, 0xba, 0xfd, 0xdc, 0x20, 0xd8, 0xbb, 0xa9, 0x3e, 0xea,
+       0x17, 0x2f, 0x38, 0xcd, 0x3a, 0x73, 0x5f, 0x98, 0x77, 0x05, 0xa2, 0x79,
+       0x4a, 0xa4, 0x54, 0x11, 0xb9, 0x86, 0xdf, 0x6f, 0x2a, 0x7e, 0xfc, 0x42,
+       0xd1, 0xd6, 0x9e, 0x96, 0x1b, 0xc5, 0x2f, 0x48, 0x15, 0x32, 0x67, 0xc7,
+       0x71, 0xdd, 0x3b, 0x4e, 0x54, 0x9f, 0xf9, 0x0f, 0xf2, 0x4a, 0x62, 0xe3,
+       0x94, 0x69, 0x6d, 0xf2, 0xc3, 0x75, 0xe6, 0xd5, 0x59, 0xe6, 0x1d, 0x61,
+       0x7e, 0x5b, 0x44, 0xd2, 0xe1, 0x80, 0xd6, 0x4b, 0xe5, 0x69, 0x68, 0x12,
+       0xf8, 0xf6, 0x87, 0xf5, 0xb3, 0x7d, 0xf4, 0xb9, 0x7c, 0xbc, 0xce, 0x77,
+       0x03, 0x4f, 0x43, 0xea, 0x76, 0x00, 0xfa, 0x2b, 0x80, 0xc7, 0xe4, 0xb9,
+       0x73, 0xbf, 0xcf, 0x73, 0x6d, 0xa8, 0xa3, 0x0d, 0xdb, 0x26, 0xb9, 0x11,
+       0xe0, 0xa0, 0x1a, 0xd6, 0xf9, 0x47, 0xf5, 0xb0, 0xc6, 0xe5, 0x40, 0x99,
+       0x7e, 0x7b, 0xf3, 0xa8, 0xc6, 0xe8, 0xd4, 0xee, 0xf7, 0xf4, 0x5e, 0x50,
+       0xce, 0x96, 0x1d, 0xd2, 0xaa, 0x29, 0x3b, 0xe0, 0xb5, 0xeb, 0xb5, 0x37,
+       0xfa, 0x79, 0x57, 0x37, 0x6a, 0xdf, 0xef, 0xf3, 0x6c, 0x34, 0xd6, 0x5d,
+       0xe8, 0xf3, 0xea, 0xa2, 0xbe, 0xcd, 0x45, 0xdb, 0xac, 0x84, 0xbd, 0x7d,
+       0x5b, 0x6a, 0x1b, 0xdf, 0x95, 0x77, 0x8b, 0xdf, 0x91, 0x5f, 0x6c, 0x9c,
+       0x81, 0xce, 0x61, 0x95, 0xb2, 0x90, 0x27, 0x6f, 0xd7, 0x5c, 0xf7, 0x6d,
+       0x67, 0x01, 0xf6, 0x81, 0xeb, 0xfe, 0xd6, 0xd9, 0x93, 0xd8, 0xc4, 0x37,
+       0xb1, 0xe7, 0x0c, 0x78, 0x88, 0x58, 0x98, 0x06, 0xbd, 0x7d, 0xb1, 0x5f,
+       0x3a, 0x42, 0x9a, 0x4e, 0x86, 0x27, 0x5a, 0xb1, 0x07, 0xc3, 0xd7, 0xc3,
+       0xb9, 0x97, 0xe9, 0x7e, 0xd2, 0x8c, 0x51, 0xfb, 0x09, 0xe6, 0x6f, 0x05,
+       0x5f, 0x1c, 0xc5, 0x4f, 0xc9, 0x9d, 0x71, 0xac, 0x75, 0x9c, 0xb4, 0xd7,
+       0x2a, 0xb1, 0xc7, 0xb0, 0x8f, 0x4c, 0x8b, 0xdc, 0xcb, 0x6f, 0xf6, 0xd1,
+       0x9f, 0x77, 0x2f, 0xcf, 0xb2, 0xf1, 0xb9, 0x4e, 0x71, 0xa5, 0x05, 0xf2,
+       0x7b, 0x75, 0xd2, 0xd3, 0x95, 0x7e, 0xad, 0x4e, 0xa0, 0xbd, 0x9d, 0x7d,
+       0x4f, 0x51, 0xb7, 0xcb, 0xba, 0xad, 0xd0, 0xc5, 0xe7, 0xa0, 0x03, 0xa5,
+       0x6a, 0x17, 0xa4, 0x3e, 0x1e, 0x42, 0x1b, 0xea, 0x28, 0x1a, 0x4b, 0x64,
+       0x26, 0xcf, 0x7c, 0x2d, 0xe6, 0x4e, 0x61, 0x8d, 0x0b, 0xc4, 0x0d, 0xae,
+       0xb1, 0x8d, 0x31, 0x38, 0xbf, 0xce, 0x06, 0x8d, 0xb0, 0x8e, 0xf4, 0x9d,
+       0x04, 0x4f, 0x26, 0x29, 0x37, 0x31, 0xde, 0x18, 0xc6, 0x63, 0xb9, 0x13,
+       0xe3, 0x5d, 0x90, 0x94, 0xd3, 0x18, 0x73, 0x0a, 0x6d, 0x88, 0x33, 0x53,
+       0xd0, 0x1f, 0x86, 0xd4, 0xec, 0x7a, 0x18, 0xf2, 0xbb, 0x4f, 0x66, 0xcd,
+       0x23, 0x07, 0xf6, 0x98, 0xd5, 0xf6, 0x81, 0x61, 0x8c, 0xf9, 0x6b, 0xea,
+       0x3c, 0xb0, 0x26, 0xf6, 0xc7, 0x0f, 0xb6, 0x71, 0x6a, 0x7d, 0x0d, 0x38,
+       0xb5, 0xf6, 0x61, 0xca, 0x39, 0x2b, 0x33, 0x61, 0xae, 0x89, 0xf5, 0x61,
+       0xac, 0x99, 0x7e, 0xac, 0x67, 0x81, 0x43, 0x47, 0xfc, 0x3a, 0xb6, 0x15,
+       0x23, 0x85, 0xb3, 0xf7, 0xec, 0x5a, 0xd6, 0x7d, 0x56, 0x52, 0x6b, 0x19,
+       0x99, 0xd7, 0xfd, 0x78, 0x86, 0x83, 0x5a, 0xf7, 0x20, 0xaf, 0xc6, 0x7a,
+       0x70, 0x96, 0x89, 0x07, 0x36, 0x70, 0xb4, 0x47, 0xcb, 0xcc, 0x7e, 0x8f,
+       0x67, 0xf1, 0xad, 0x87, 0x77, 0xd4, 0x26, 0xb1, 0x6f, 0x40, 0x46, 0xe6,
+       0x1b, 0xf5, 0x21, 0xf9, 0x24, 0xdf, 0xd1, 0xcf, 0x38, 0xcb, 0xdd, 0xbc,
+       0x29, 0x1f, 0xe7, 0x75, 0x2c, 0x74, 0x31, 0x20, 0xd6, 0x79, 0xcf, 0x3e,
+       0x1f, 0x59, 0x5c, 0x55, 0xfc, 0x3e, 0x72, 0x7e, 0x4b, 0x05, 0xd1, 0x36,
+       0x84, 0x76, 0x5c, 0x87, 0x29, 0x73, 0xf9, 0xbf, 0xb9, 0x4b, 0xa3, 0xae,
+       0x3b, 0xaf, 0xf3, 0xc3, 0x12, 0xe6, 0xaa, 0x6a, 0xe8, 0xe4, 0x71, 0xc9,
+       0x87, 0xdb, 0x31, 0x57, 0xc2, 0xdc, 0x52, 0x23, 0x58, 0x0f, 0xcb, 0x3d,
+       0xe4, 0x89, 0xc8, 0x9e, 0x70, 0x7c, 0x2b, 0xbd, 0xa9, 0x12, 0xd1, 0x61,
+       0x65, 0x25, 0x73, 0xf8, 0xb5, 0x28, 0x1d, 0x47, 0x8c, 0x44, 0x15, 0x78,
+       0x17, 0x7b, 0xb2, 0x4f, 0xba, 0x6e, 0xda, 0x66, 0x7d, 0xc2, 0x0c, 0x29,
+       0xfa, 0x5b, 0x3a, 0x74, 0xbc, 0xf1, 0x72, 0x6f, 0xc2, 0x3c, 0xa9, 0x8e,
+       0xfb, 0xef, 0x53, 0xc0, 0xcc, 0xe6, 0x78, 0x67, 0x36, 0x95, 0x29, 0x2f,
+       0xe5, 0x13, 0xd1, 0x65, 0x65, 0x65, 0x30, 0x66, 0x66, 0x56, 0x11, 0x37,
+       0x12, 0x66, 0x87, 0xa2, 0x4f, 0xb4, 0x5d, 0xef, 0x3b, 0x8d, 0xfe, 0x09,
+       0xd5, 0xe2, 0xaf, 0x87, 0xf7, 0xf5, 0xe3, 0x7e, 0x8f, 0x67, 0x88, 0x39,
+       0xa3, 0xc0, 0x4c, 0xe6, 0x9a, 0xe9, 0xdc, 0x86, 0x64, 0x6c, 0x62, 0x54,
+       0x63, 0xe8, 0xfd, 0x53, 0x7f, 0x47, 0x1d, 0xca, 0x25, 0xd6, 0xc5, 0x7d,
+       0x7e, 0x1b, 0xd5, 0x3a, 0xf3, 0xfd, 0x53, 0x59, 0x9d, 0xc7, 0x58, 0x57,
+       0x31, 0x7f, 0xdf, 0xcd, 0x3b, 0x8b, 0xa6, 0x9c, 0x47, 0x38, 0xce, 0x5a,
+       0x60, 0xba, 0x5d, 0x98, 0x23, 0x3a, 0x57, 0x6c, 0xd0, 0x06, 0xfd, 0x01,
+       0xcc, 0x17, 0x68, 0xc4, 0xbd, 0x2f, 0x88, 0x31, 0x11, 0x3c, 0x40, 0x27,
+       0xd0, 0x35, 0xa1, 0xa3, 0x56, 0x30, 0x4e, 0x6e, 0x5d, 0xb2, 0x5e, 0x7f,
+       0x09, 0x32, 0x27, 0x35, 0x57, 0xf9, 0xb4, 0x31, 0x38, 0x37, 0xe6, 0xc0,
+       0xfb, 0xfd, 0x53, 0xa4, 0x4f, 0x9e, 0x4d, 0x54, 0xcd, 0x6d, 0x70, 0x3d,
+       0x83, 0x32, 0xbf, 0x3e, 0x24, 0xcb, 0xf8, 0xad, 0xae, 0x7b, 0xf7, 0xb6,
+       0x0d, 0xdd, 0x7a, 0x3e, 0x6f, 0x6a, 0x7e, 0x5d, 0x76, 0x18, 0x33, 0x01,
+       0xaf, 0xe8, 0x9c, 0x2a, 0xf6, 0x65, 0x5e, 0xe1, 0x10, 0xe5, 0xa3, 0x53,
+       0x87, 0x5c, 0xdd, 0xae, 0x51, 0x4f, 0x65, 0xbd, 0x35, 0x15, 0x0d, 0x74,
+       0xc9, 0x2a, 0xf0, 0xae, 0x0c, 0xd9, 0x99, 0x7b, 0x25, 0x24, 0xcb, 0x79,
+       0x1d, 0x4f, 0x8e, 0xfe, 0x5e, 0x39, 0x52, 0xad, 0x4d, 0xca, 0x6e, 0x2d,
+       0xae, 0xbf, 0x51, 0xae, 0xe5, 0x5e, 0x37, 0xe4, 0xf9, 0x51, 0x9d, 0x57,
+       0x17, 0x2f, 0x4b, 0xef, 0x00, 0x75, 0x9e, 0x2d, 0x9d, 0x63, 0x07, 0xec,
+       0x80, 0xce, 0xf1, 0x33, 0xe8, 0x1c, 0xef, 0x40, 0xe7, 0xf8, 0x69, 0x11,
+       0xf8, 0x52, 0x4c, 0xfb, 0xf8, 0xbf, 0x08, 0x1c, 0xa2, 0xac, 0xb6, 0xce,
+       0xe0, 0x4e, 0x17, 0xb3, 0xa0, 0xc1, 0x5b, 0x92, 0x06, 0xde, 0xa6, 0xe4,
+       0xfa, 0xc6, 0xbc, 0xec, 0x6c, 0x78, 0x79, 0xc8, 0x1f, 0x30, 0x07, 0x6c,
+       0x9c, 0xf7, 0x14, 0x07, 0x0e, 0x1d, 0x91, 0xd8, 0x49, 0xe2, 0x47, 0x50,
+       0x36, 0x0b, 0xef, 0x68, 0x1c, 0xda, 0x2c, 0xb0, 0x1c, 0x10, 0x9d, 0x4f,
+       0xb6, 0xb0, 0x27, 0x65, 0xe7, 0x97, 0xa8, 0x3f, 0xa6, 0x7d, 0x40, 0x9e,
+       0x4f, 0x9e, 0x78, 0xf9, 0x67, 0xff, 0xee, 0x95, 0xce, 0xb3, 0x5b, 0x32,
+       0xbb, 0xd0, 0xae, 0x81, 0x5d, 0xc3, 0x5e, 0xcc, 0x5b, 0xfd, 0x05, 0x6d,
+       0x30, 0x47, 0xb1, 0x4b, 0xb6, 0x21, 0x43, 0xea, 0xf1, 0x2e, 0xad, 0xfb,
+       0xd5, 0xe3, 0x43, 0x3a, 0x17, 0x97, 0xe3, 0xe4, 0x0a, 0xb6, 0xac, 0x14,
+       0xac, 0x68, 0x16, 0xf4, 0xb7, 0x0b, 0x5b, 0xed, 0x3a, 0xee, 0x60, 0x07,
+       0x67, 0x70, 0xa3, 0x46, 0x39, 0x7f, 0x57, 0x63, 0xef, 0x66, 0xed, 0x4f,
+       0x18, 0xc7, 0x3a, 0x93, 0x94, 0x3f, 0xf6, 0x13, 0x03, 0xe9, 0x8f, 0x9a,
+       0xd1, 0xfd, 0xbd, 0x7e, 0xd7, 0xd1, 0x76, 0xa7, 0x46, 0x3c, 0x16, 0xb9,
+       0x94, 0xb7, 0x21, 0x4b, 0x5e, 0x8f, 0x50, 0x07, 0x28, 0xa9, 0x46, 0x3f,
+       0xd7, 0x5f, 0xb3, 0xeb, 0x1e, 0xb5, 0xb9, 0xae, 0xb8, 0x8f, 0xdb, 0x94,
+       0xfd, 0x7b, 0x5a, 0xee, 0xe7, 0x8b, 0x67, 0xe5, 0x2d, 0xdc, 0xb7, 0xa7,
+       0xe3, 0x64, 0xe4, 0x4d, 0xe8, 0x78, 0xb5, 0x62, 0x23, 0x6f, 0x7b, 0x1a,
+       0xe7, 0x64, 0xa9, 0x95, 0x2b, 0x2f, 0xcb, 0xe5, 0xab, 0xfb, 0xea, 0xa5,
+       0xab, 0x31, 0xf5, 0xf2, 0x95, 0x61, 0x95, 0xbb, 0xe2, 0xba, 0xff, 0x74,
+       0x96, 0xe4, 0xdd, 0x0d, 0x57, 0x4e, 0x3b, 0xc6, 0x40, 0x40, 0x1a, 0xb9,
+       0x75, 0xae, 0x1b, 0x04, 0x36, 0xdf, 0xe8, 0x75, 0xdd, 0x47, 0xc7, 0xc7,
+       0x25, 0xde, 0x4b, 0x1d, 0xe5, 0xf3, 0x11, 0xe6, 0xbb, 0x12, 0x73, 0x52,
+       0xb6, 0x7d, 0xbe, 0xac, 0x14, 0xf0, 0xad, 0xcb, 0xd3, 0x5f, 0x1e, 0x3b,
+       0xe6, 0xc7, 0x4a, 0x7e, 0xf4, 0x22, 0x7d, 0xc9, 0x91, 0xff, 0xf2, 0x25,
+       0x9b, 0x72, 0xae, 0xf0, 0x19, 0xf4, 0x0f, 0xcb, 0xb7, 0x0a, 0xa1, 0x43,
+       0x65, 0x13, 0xcf, 0x31, 0x95, 0x2b, 0xdc, 0x73, 0x87, 0x75, 0xcc, 0x00,
+       0x3a, 0x89, 0xe9, 0xba, 0xcb, 0x0e, 0xe7, 0xeb, 0xc2, 0x7c, 0x7b, 0xe6,
+       0x31, 0xc8, 0xff, 0xd3, 0x5a, 0x3e, 0x9f, 0x53, 0xb0, 0x7d, 0xc1, 0xdf,
+       0x61, 0x99, 0x2d, 0x40, 0xc6, 0x2b, 0xe6, 0x9c, 0x52, 0x57, 0xb0, 0x22,
+       0xcb, 0xc0, 0x8e, 0x25, 0xe0, 0xcd, 0x93, 0x3a, 0xb6, 0xda, 0xa3, 0xb1,
+       0x67, 0x85, 0xe5, 0x8c, 0x24, 0xcb, 0x4e, 0xb7, 0x3e, 0xbf, 0xfd, 0xdd,
+       0x57, 0x23, 0xde, 0x9d, 0x83, 0x8f, 0x33, 0x4a, 0xda, 0x60, 0x03, 0xcd,
+       0x6c, 0x2d, 0x80, 0x27, 0x22, 0x38, 0xdb, 0x56, 0xcd, 0x0f, 0x75, 0xc8,
+       0xef, 0xba, 0xf6, 0x23, 0x7a, 0xf1, 0x8a, 0xba, 0xc9, 0x76, 0xcf, 0xa0,
+       0x5f, 0xbb, 0xa4, 0xae, 0xb4, 0x69, 0x5c, 0x7d, 0xb8, 0x2e, 0x09, 0x3d,
+       0xe4, 0x69, 0x94, 0x03, 0xa8, 0x8b, 0xfa, 0x65, 0x03, 0xe5, 0x45, 0x94,
+       0x5b, 0xf0, 0x64, 0x9b, 0x11, 0xe8, 0x15, 0x78, 0xbe, 0x81, 0xf1, 0xc6,
+       0xb1, 0xe6, 0x8c, 0x29, 0x1f, 0x9d, 0xa2, 0x2c, 0x19, 0x53, 0xcc, 0x4b,
+       0x5e, 0xb6, 0xf1, 0xac, 0x0e, 0xab, 0x99, 0x35, 0x96, 0xf1, 0x2c, 0x79,
+       0xdf, 0x1f, 0xc2, 0x24, 0xf4, 0x49, 0x5d, 0xf5, 0x30, 0xe9, 0xa3, 0x26,
+       0x26, 0xb1, 0xae, 0x5d, 0x66, 0xaf, 0x90, 0xd7, 0x4d, 0xd0, 0x5b, 0x87,
+       0xcc, 0x5c, 0x0d, 0x6b, 0x7d, 0xb4, 0x0c, 0x5a, 0xdc, 0x06, 0x5d, 0x6d,
+       0x82, 0xa6, 0x52, 0x05, 0x6b, 0x6a, 0x51, 0x45, 0xb5, 0x2f, 0xe0, 0x09,
+       0xd0, 0x6b, 0xf0, 0x15, 0xea, 0xa2, 0xe4, 0xe5, 0x38, 0x68, 0x4f, 0xdc,
+       0xa0, 0x6d, 0xa7, 0xe3, 0xca, 0x06, 0x0d, 0x82, 0x2e, 0x0b, 0x1e, 0x4f,
+       0xbf, 0xa7, 0x34, 0xae, 0x4e, 0xdd, 0x96, 0x44, 0xf2, 0xb6, 0x58, 0xc0,
+       0x02, 0xcb, 0xf9, 0x50, 0x1c, 0x8c, 0x39, 0x29, 0xd7, 0x30, 0x8f, 0x01,
+       0xfe, 0x1e, 0x3d, 0xa1, 0xf9, 0x7b, 0x4a, 0x02, 0x87, 0x79, 0x1c, 0xf4,
+       0x06, 0x0c, 0xf2, 0x78, 0x3a, 0xe9, 0xd3, 0xe8, 0xd7, 0xc1, 0xbf, 0x16,
+       0x2c, 0xb1, 0xb0, 0xac, 0x82, 0xff, 0xb7, 0xf1, 0xfd, 0x66, 0x6d, 0x44,
+       0xad, 0xac, 0x29, 0x3f, 0x97, 0xe4, 0x19, 0xe8, 0xc9, 0xb7, 0x70, 0x76,
+       0x9d, 0x5a, 0x77, 0x8f, 0x8d, 0x33, 0x7e, 0x96, 0x56, 0x97, 0xed, 0x93,
+       0xb2, 0x3f, 0x36, 0x89, 0xf2, 0x31, 0x3c, 0x0d, 0x9c, 0x43, 0x48, 0xc7,
+       0xbf, 0x37, 0xf3, 0x8e, 0xf2, 0xfe, 0x67, 0x61, 0x42, 0xe7, 0xe7, 0x1b,
+       0x76, 0x2f, 0xbe, 0xd3, 0x17, 0xc3, 0xbd, 0x41, 0x67, 0x52, 0x11, 0x9d,
+       0x6f, 0x5a, 0x86, 0x2e, 0xb1, 0x85, 0xf1, 0xde, 0xa7, 0x2f, 0xaf, 0x0a,
+       0x1e, 0x1e, 0xfb, 0x97, 0x9b, 0x0c, 0x33, 0x47, 0xfd, 0x6e, 0xc4, 0x93,
+       0x7f, 0x9f, 0xb8, 0xfb, 0xf6, 0xca, 0x94, 0x81, 0x97, 0x5b, 0x66, 0x18,
+       0x6d, 0x21, 0xcb, 0x20, 0x8b, 0x4a, 0x9a, 0x7e, 0xd9, 0xce, 0xeb, 0x9b,
+       0xab, 0x26, 0xcc, 0x0f, 0xc4, 0xeb, 0xbb, 0x6a, 0x53, 0xee, 0xb4, 0x03,
+       0x5f, 0xa2, 0x5a, 0xaf, 0x7c, 0xdf, 0xce, 0x02, 0x15, 0xac, 0x68, 0x1a,
+       0x34, 0xda, 0x26, 0x56, 0x7c, 0x4e, 0x1e, 0xcc, 0xbb, 0xac, 0xfb, 0xb2,
+       0x6d, 0xa3, 0x6f, 0x63, 0x5e, 0xae, 0x9f, 0x7b, 0xe1, 0x1e, 0xe8, 0x9b,
+       0x36, 0x35, 0x8d, 0xd6, 0xab, 0xdd, 0x03, 0x1e, 0x8d, 0x36, 0xf6, 0x11,
+       0xfe, 0x3f, 0xfb, 0x20, 0x9d, 0x38, 0xca, 0xcb, 0xbb, 0xc0, 0xb3, 0xca,
+       0xf3, 0x1c, 0x01, 0x6d, 0x1c, 0xa4, 0x9f, 0x86, 0x6f, 0xd1, 0xa3, 0x9f,
+       0x47, 0x9b, 0xf4, 0x43, 0xba, 0xe9, 0x90, 0xd9, 0xab, 0xb6, 0xcc, 0x17,
+       0xf4, 0x7d, 0x43, 0xd7, 0xa4, 0xcf, 0x68, 0x12, 0x74, 0x43, 0x5a, 0x27,
+       0x6f, 0x99, 0x52, 0x02, 0x1d, 0x95, 0x80, 0x4f, 0x25, 0xd0, 0x54, 0x19,
+       0xf8, 0x56, 0x02, 0xbe, 0x95, 0x6a, 0x56, 0xbc, 0x82, 0x3d, 0x53, 0x66,
+       0x6f, 0x81, 0x8e, 0xb6, 0x6b, 0xbc, 0x7f, 0xbd, 0x66, 0x93, 0x72, 0xf0,
+       0x66, 0xf3, 0xee, 0xff, 0x81, 0xbb, 0x1f, 0x92, 0x5d, 0xd8, 0x2d, 0x6f,
+       0x15, 0xc7, 0x80, 0x49, 0x02, 0x8c, 0x72, 0x40, 0x1b, 0x53, 0x72, 0xbd,
+       0x38, 0x2d, 0x3b, 0x90, 0x4f, 0x37, 0x36, 0x62, 0xd0, 0xa7, 0x23, 0xb2,
+       0xf2, 0xda, 0xa8, 0xbc, 0xb9, 0xa1, 0x64, 0x09, 0xf4, 0x9b, 0xdb, 0xa4,
+       0xdf, 0x1d, 0xf4, 0x5c, 0xea, 0xd0, 0x71, 0xfa, 0xd9, 0x8a, 0xe7, 0x7f,
+       0x9f, 0xab, 0x74, 0xca, 0x7c, 0xc5, 0x94, 0xc7, 0x2b, 0xdd, 0xf2, 0xe5,
+       0x4a, 0x58, 0x4e, 0xc3, 0x0e, 0xfc, 0x4a, 0x65, 0x50, 0x9e, 0xac, 0x0c,
+       0xc9, 0x57, 0xab, 0x51, 0xf9, 0x5a, 0xd5, 0x96, 0x4c, 0x35, 0x2e, 0xe9,
+       0xea, 0x98, 0x3c, 0x51, 0xa5, 0x5f, 0x1d, 0xf3, 0xe1, 0x37, 0xd3, 0xf4,
+       0x57, 0x70, 0x5d, 0x41, 0xac, 0x2b, 0xae, 0xe6, 0x74, 0x9c, 0x52, 0x32,
+       0x9e, 0xcf, 0x43, 0xe4, 0x39, 0x8c, 0x75, 0xf1, 0x35, 0x25, 0x65, 0x3d,
+       0x7f, 0xe3, 0xff, 0x46, 0x42, 0xda, 0x36, 0x7a, 0xae, 0x34, 0x88, 0x36,
+       0x90, 0x7b, 0xf9, 0x86, 0xef, 0xa3, 0xe1, 0xf3, 0x6f, 0xd8, 0x5e, 0x86,
+       0xf6, 0x5b, 0xdf, 0xa4, 0xed, 0xa5, 0xcf, 0x9e, 0xf8, 0x41, 0x3b, 0xe7,
+       0x9a, 0xf6, 0x9b, 0x3c, 0x88, 0x6d, 0x34, 0xe6, 0xbd, 0x98, 0x79, 0xf8,
+       0xff, 0x53, 0xbc, 0x18, 0xd5, 0xb9, 0xea, 0x20, 0xff, 0x4f, 0x05, 0x6b,
+       0xf9, 0xf4, 0xdc, 0xf1, 0xf9, 0xe2, 0xac, 0x7a, 0xbc, 0x48, 0x8d, 0xc6,
+       0x95, 0x8b, 0xcd, 0x9c, 0xb8, 0x2f, 0xc9, 0xa6, 0x13, 0xd2, 0x6b, 0xf0,
+       0xf3, 0x1f, 0x75, 0x7e, 0xdc, 0xec, 0x09, 0xd2, 0x1f, 0x63, 0x6f, 0x9d,
+       0x7e, 0x3c, 0x01, 0xba, 0xad, 0x63, 0xca, 0xa5, 0x8a, 0xe7, 0xb3, 0x5a,
+       0xd1, 0xf4, 0xf2, 0x2b, 0xd0, 0x1c, 0x63, 0x0e, 0xde, 0x33, 0x5b, 0xf2,
+       0xfa, 0xce, 0xe0, 0xde, 0x60, 0x8f, 0x63, 0xbf, 0x46, 0x37, 0xe7, 0xe2,
+       0xff, 0xe9, 0xa0, 0xec, 0xaf, 0x97, 0xb9, 0xc6, 0xb6, 0xa6, 0x45, 0x2f,
+       0xae, 0x1b, 0x97, 0x17, 0x70, 0x7e, 0x65, 0x93, 0xeb, 0x0f, 0x4a, 0x39,
+       0x4e, 0xdb, 0x96, 0xf8, 0x7d, 0x42, 0x4a, 0x98, 0xa7, 0x1c, 0x6f, 0xf8,
+       0xc3, 0x3c, 0x9c, 0x2d, 0x9b, 0x0f, 0xe6, 0x5d, 0x2c, 0x1d, 0xc7, 0x3b,
+       0xea, 0xe2, 0xd0, 0x99, 0x16, 0xf8, 0x7e, 0x11, 0x65, 0xfa, 0x46, 0x56,
+       0xf0, 0x8c, 0xf8, 0x75, 0xd5, 0x01, 0xad, 0xab, 0x4f, 0x3f, 0xe8, 0xb7,
+       0x54, 0xb2, 0xb2, 0xa9, 0x40, 0x42, 0x19, 0xaf, 0xfe, 0x7c, 0x80, 0x98,
+       0x7b, 0xdc, 0xe6, 0x2f, 0x24, 0x7f, 0x35, 0xb5, 0x4f, 0xc1, 0xff, 0x76,
+       0x44, 0x9e, 0x32, 0x99, 0xc7, 0x9e, 0x54, 0xb3, 0xc5, 0x9c, 0x9f, 0xe3,
+       0x9b, 0x50, 0xc7, 0xcb, 0x37, 0x07, 0xbc, 0x9c, 0x77, 0x8e, 0x7d, 0x30,
+       0xcf, 0xfd, 0x20, 0x9d, 0x30, 0xdf, 0xbd, 0xbd, 0xf9, 0x3f, 0x52, 0xe5,
+       0x3c, 0xf0, 0xce, 0x6e, 0xd1, 0xfc, 0x98, 0xab, 0xfe, 0xdb, 0xdd, 0xd3,
+       0xfc, 0xdc, 0xf0, 0x31, 0xfc, 0x6e, 0x80, 0xb6, 0x2d, 0x71, 0xe3, 0x92,
+       0x97, 0x3b, 0xaa, 0x6d, 0x68, 0x60, 0x05, 0xea, 0xc8, 0xab, 0xe0, 0x93,
+       0x66, 0x5b, 0xfe, 0xfd, 0x07, 0x69, 0x3f, 0x51, 0x42, 0x6c, 0x67, 0x00,
+       0x00, 0x00 };
+
+static const u32 bnx2_RXP_b09FwData[(0x0/4) + 1] = { 0x0 };
+static const u32 bnx2_RXP_b09FwRodata[(0x278/4) + 1] = {
+       0x08004050, 0x08003f50, 0x08003ff4, 0x0800400c, 0x08004024, 0x08004044,
+       0x08004050, 0x08004050, 0x08003f58, 0x00000000, 0x08004a0c, 0x08004a44,
+       0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004a7c, 0x08004c40,
+       0x08004b88, 0x08004bc0, 0x08004c40, 0x08004b10, 0x08004c40, 0x08004c40,
+       0x08004bc0, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+       0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c00,
+       0x08004c40, 0x08004c00, 0x08004b88, 0x08004c40, 0x08004c40, 0x08004c00,
+       0x08004c00, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+       0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+       0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+       0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+       0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+       0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+       0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+       0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+       0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+       0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+       0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+       0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+       0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+       0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+       0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+       0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40, 0x08004c40,
+       0x08004aec, 0x00000000, 0x08006058, 0x08006070, 0x08006070, 0x08006070,
+       0x08006058, 0x08006070, 0x08006070, 0x08006070, 0x08006058, 0x08006070,
+       0x08006070, 0x08006070, 0x08006058, 0x08006070, 0x08006070, 0x08006070,
+       0x08006064, 0x00000000, 0x00000000 };
+static const u32 bnx2_RXP_b09FwBss[(0x13dc/4) + 1] = { 0x0 };
+static const u32 bnx2_RXP_b09FwSbss[(0x20/4) + 1] = { 0x0 };
 
 static struct fw_info bnx2_rxp_fw_09 = {
-       .ver_major                      = 0x1,
-       .ver_minor                      = 0x0,
-       .ver_fix                        = 0x0,
+       .ver_major                      = 0x3,
+       .ver_minor                      = 0x4,
+       .ver_fix                        = 0x3,
 
        .start_addr                     = 0x08003184,
 
        .text_addr                      = 0x08000000,
-       .text_len                       = 0x673c,
+       .text_len                       = 0x6768,
        .text_index                     = 0x0,
        .gz_text                        = bnx2_RXP_b09FwText,
        .gz_text_len                    = sizeof(bnx2_RXP_b09FwText),
 
-       .data_addr                      = 0x080069e0,
+       .data_addr                      = 0x08006a00,
        .data_len                       = 0x0,
        .data_index                     = 0x0,
        .data                           = bnx2_RXP_b09FwData,
 
-       .sbss_addr                      = 0x080069e0,
-       .sbss_len                       = 0x2c,
+       .sbss_addr                      = 0x08006a00,
+       .sbss_len                       = 0x20,
        .sbss_index                     = 0x0,
        .sbss                           = bnx2_RXP_b09FwSbss,
 
-       .bss_addr                       = 0x08006a10,
+       .bss_addr                       = 0x08006a20,
        .bss_len                        = 0x13dc,
        .bss_index                      = 0x0,
        .bss                            = bnx2_RXP_b09FwBss,
 
-       .rodata_addr                    = 0x08006740,
+       .rodata_addr                    = 0x08006768,
        .rodata_len                     = 0x278,
        .rodata_index                   = 0x0,
        .rodata                         = bnx2_RXP_b09FwRodata,
 };
 
 static u8 bnx2_TPAT_b09FwText[] = {
-       0x1f, 0x8b, 0x08, 0x08, 0xdb, 0xfd, 0x2f, 0x45, 0x00, 0x03, 0x74, 0x65,
-       0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xc5, 0x58, 0x5d, 0x6c,
-       0x1c, 0x57, 0x15, 0x3e, 0xf3, 0xbb, 0x13, 0x77, 0xed, 0xbd, 0x49, 0x97,
-       0x6a, 0x13, 0xb9, 0x74, 0xc6, 0x1e, 0x3b, 0x8b, 0x1c, 0x35, 0x93, 0xb0,
-       0x24, 0x16, 0x5a, 0xd1, 0xc9, 0xcc, 0xae, 0x6b, 0xe5, 0x29, 0x86, 0xbc,
-       0xf1, 0xb2, 0xac, 0xed, 0x46, 0x54, 0x48, 0x4d, 0x51, 0x84, 0x22, 0x81,
-       0x94, 0x65, 0x76, 0x53, 0x40, 0x5a, 0x65, 0xc1, 0xa0, 0x04, 0x21, 0x84,
-       0x22, 0x9b, 0x66, 0x91, 0x58, 0x3c, 0x4d, 0xe9, 0x6b, 0x94, 0xbc, 0x90,
-       0x96, 0x17, 0x9e, 0x4b, 0x9e, 0xac, 0x02, 0x12, 0x0f, 0xa8, 0x8a, 0x78,
-       0x40, 0x15, 0x0d, 0x1e, 0xbe, 0x33, 0x3f, 0x9b, 0x5d, 0xd7, 0x29, 0x79,
-       0xa8, 0x84, 0xa5, 0xf1, 0xcc, 0xfd, 0x39, 0xf7, 0xe7, 0x7c, 0xdf, 0x77,
-       0xee, 0xb9, 0x5b, 0x92, 0x69, 0x82, 0xd2, 0xbf, 0x49, 0x3c, 0x97, 0xbe,
-       0x71, 0xf1, 0xd2, 0xe2, 0x8b, 0x27, 0x4d, 0x3a, 0x71, 0xe2, 0x45, 0xe9,
-       0x19, 0x43, 0xa6, 0xcf, 0xe0, 0x4f, 0x21, 0x12, 0xd9, 0xf8, 0xfc, 0x90,
-       0x21, 0x57, 0x6f, 0x4e, 0x7b, 0x36, 0x19, 0x4a, 0xd5, 0x79, 0x61, 0xd5,
-       0x26, 0x72, 0x07, 0x0b, 0xa6, 0x4f, 0xff, 0x89, 0x5a, 0x45, 0x95, 0xb8,
-       0xfe, 0xf9, 0xea, 0xa3, 0xe3, 0x77, 0x4e, 0x5b, 0x0f, 0x6f, 0x2a, 0x64,
-       0x88, 0x6a, 0xc3, 0x10, 0xf3, 0x64, 0x4c, 0xc3, 0xe6, 0x97, 0x47, 0x57,
-       0x34, 0x9a, 0xca, 0xc6, 0x12, 0x14, 0xf4, 0x0c, 0xaa, 0x77, 0x31, 0x8e,
-       0x7d, 0x59, 0xf2, 0x43, 0x55, 0xf2, 0x6f, 0x18, 0x24, 0x57, 0x5d, 0xc9,
-       0x0b, 0x6d, 0xb4, 0x49, 0xe4, 0x39, 0x39, 0x72, 0x45, 0x14, 0x7d, 0xd3,
-       0x91, 0x49, 0xb6, 0x77, 0xa3, 0xd9, 0xb9, 0x25, 0xc9, 0xeb, 0x2f, 0x4b,
-       0x7e, 0xdf, 0xe3, 0x7d, 0x63, 0x1d, 0x4b, 0x92, 0xdb, 0xe7, 0x77, 0xd5,
-       0xf0, 0xbb, 0x53, 0xd4, 0x28, 0x52, 0x41, 0xb6, 0xd9, 0xd6, 0x24, 0xdf,
-       0x59, 0x28, 0x29, 0x34, 0x8b, 0xe7, 0x00, 0xad, 0x3b, 0x94, 0xf7, 0x1c,
-       0x52, 0x15, 0x5b, 0x26, 0xbf, 0x28, 0xd1, 0xaf, 0x2b, 0x1a, 0x9e, 0xb3,
-       0x52, 0xad, 0xbf, 0x96, 0x8e, 0x53, 0xa4, 0x36, 0xd6, 0xd2, 0x2c, 0xf2,
-       0xda, 0x12, 0x7b, 0xcf, 0x59, 0x10, 0x32, 0xcd, 0xe2, 0x99, 0xc4, 0x77,
-       0x13, 0xfd, 0x34, 0xf2, 0x2a, 0x7b, 0xdb, 0x0e, 0xe0, 0x1b, 0xeb, 0xc4,
-       0x58, 0x5e, 0xbc, 0x0e, 0x13, 0xeb, 0xb0, 0xa9, 0xd3, 0x5b, 0xc6, 0x3e,
-       0xe6, 0x4a, 0x4d, 0xd2, 0xa9, 0x13, 0xaf, 0x7d, 0x92, 0x02, 0xa1, 0x50,
-       0x70, 0x4c, 0x23, 0xf7, 0x9c, 0x8a, 0xf2, 0x21, 0x6a, 0x09, 0x09, 0x7d,
-       0x3a, 0x29, 0x7e, 0x39, 0xb4, 0xeb, 0xa8, 0x2f, 0x50, 0x50, 0x3c, 0x28,
-       0xc9, 0xd5, 0xef, 0xa1, 0x7e, 0x4e, 0x34, 0xe9, 0xbb, 0x78, 0x4b, 0x28,
-       0x1f, 0xe4, 0xf1, 0x50, 0x96, 0x48, 0xb1, 0x49, 0x78, 0xa1, 0x49, 0xed,
-       0x30, 0xb3, 0xe5, 0xfa, 0xa4, 0xae, 0x15, 0xee, 0xc5, 0x0e, 0xfd, 0x7a,
-       0x75, 0x6a, 0x08, 0x6a, 0xa9, 0x55, 0xf4, 0xe9, 0xd9, 0xa2, 0x06, 0x9c,
-       0xdc, 0x18, 0xcf, 0x97, 0xb8, 0x9e, 0xff, 0x50, 0x6f, 0x92, 0x52, 0xb5,
-       0x85, 0x4f, 0x5f, 0xa6, 0xa4, 0x8d, 0xf7, 0x29, 0x63, 0x6f, 0xa7, 0xd2,
-       0x72, 0x51, 0x78, 0x37, 0xbe, 0x48, 0x6e, 0xec, 0x1f, 0x03, 0xdf, 0x02,
-       0x7b, 0xd4, 0x81, 0x75, 0xe0, 0xca, 0xd4, 0x2a, 0x19, 0x64, 0x2d, 0xae,
-       0xa1, 0xe5, 0x6f, 0x5d, 0x05, 0x7e, 0x67, 0xdc, 0xd4, 0xd4, 0x8e, 0x71,
-       0xfe, 0x23, 0xd6, 0xd9, 0x12, 0x06, 0xf0, 0x6e, 0x9c, 0x8f, 0xa2, 0x37,
-       0x9d, 0x28, 0xd2, 0xab, 0x76, 0xf9, 0x16, 0x2d, 0x94, 0x34, 0x9a, 0x17,
-       0x78, 0xc3, 0x8f, 0x36, 0x7c, 0xa5, 0x65, 0xeb, 0xc9, 0x78, 0x86, 0xbf,
-       0xcb, 0x12, 0x96, 0x42, 0x1f, 0x74, 0xdf, 0x63, 0x7f, 0x94, 0x97, 0x62,
-       0x9b, 0x28, 0xda, 0x5c, 0xfc, 0x34, 0x9b, 0xef, 0xa7, 0x36, 0x51, 0x54,
-       0xaf, 0xf0, 0xbc, 0x16, 0xf6, 0xcc, 0x5c, 0x25, 0xaa, 0x0f, 0x1c, 0xa3,
-       0xd9, 0xc5, 0xfa, 0x6c, 0xbc, 0x07, 0x25, 0xec, 0xc1, 0x2a, 0x9b, 0x92,
-       0x41, 0x81, 0x1d, 0xbd, 0x00, 0x7e, 0xb8, 0xbe, 0x6d, 0xbd, 0xef, 0x2b,
-       0x05, 0xda, 0x72, 0xf2, 0xd4, 0x09, 0x4b, 0x14, 0x84, 0x1d, 0xf2, 0x42,
-       0x19, 0x73, 0x14, 0x68, 0xd3, 0x7e, 0x18, 0xd5, 0x1d, 0x07, 0x7e, 0x21,
-       0xb6, 0x2b, 0xd5, 0x69, 0x1a, 0xed, 0x0b, 0x62, 0x8d, 0x1c, 0x60, 0x21,
-       0xc3, 0x37, 0xb3, 0xf1, 0x77, 0x10, 0x3a, 0x68, 0xa7, 0x96, 0x5c, 0xb1,
-       0x44, 0x40, 0x56, 0xc9, 0x53, 0x48, 0xc8, 0x55, 0x81, 0x3e, 0x2d, 0xaa,
-       0x85, 0x06, 0xed, 0x28, 0x97, 0x63, 0x7e, 0xb7, 0x7b, 0x3b, 0xd1, 0x9d,
-       0xa3, 0x25, 0xba, 0x1b, 0x16, 0xe9, 0x76, 0x48, 0x72, 0xd3, 0x01, 0x37,
-       0x8a, 0x82, 0xde, 0x0a, 0x47, 0xf7, 0xf2, 0x1b, 0xec, 0x25, 0x38, 0xa2,
-       0x40, 0x83, 0xab, 0xce, 0x3d, 0x30, 0xc8, 0x02, 0x46, 0x2d, 0xec, 0x3d,
-       0x7b, 0xf3, 0xbe, 0x76, 0xa6, 0x57, 0x6d, 0xeb, 0x87, 0x3e, 0xa3, 0x76,
-       0x4d, 0x43, 0xed, 0x5e, 0x7f, 0x0c, 0x30, 0x86, 0xa0, 0xab, 0xd0, 0x93,
-       0x0c, 0xbf, 0xcc, 0x6c, 0x1b, 0xd4, 0xef, 0xe6, 0xc8, 0xdc, 0x54, 0xa9,
-       0xd9, 0x2b, 0x92, 0x33, 0x6f, 0x99, 0x24, 0xcb, 0x45, 0x99, 0x54, 0x9a,
-       0xd9, 0x8c, 0x68, 0x09, 0xeb, 0xb8, 0x6f, 0xff, 0x48, 0xa7, 0xa9, 0xc0,
-       0xd1, 0x89, 0xfb, 0x18, 0x34, 0x73, 0xcb, 0x90, 0xfc, 0x1e, 0xef, 0x83,
-       0x7d, 0x6e, 0xa4, 0x3e, 0x57, 0x25, 0xef, 0x46, 0x8e, 0x66, 0x37, 0xfe,
-       0x11, 0x79, 0x36, 0x7c, 0x0d, 0x9e, 0xaf, 0x56, 0xbe, 0xa0, 0xd0, 0x04,
-       0xea, 0x36, 0xb9, 0xed, 0x61, 0x5a, 0xcf, 0x63, 0x44, 0x91, 0xe7, 0x3c,
-       0x4b, 0x1e, 0xf3, 0xff, 0x3c, 0xdb, 0xe4, 0x68, 0x66, 0x83, 0x75, 0x83,
-       0xf7, 0x26, 0x97, 0x79, 0x6d, 0x07, 0xa8, 0x89, 0x1d, 0x35, 0xcb, 0x45,
-       0xf8, 0x41, 0x8e, 0x35, 0xd2, 0xc4, 0x8e, 0x65, 0x7b, 0x02, 0x6f, 0x9e,
-       0xef, 0xac, 0x92, 0xf0, 0x9d, 0xe3, 0x46, 0x9e, 0x7c, 0xe0, 0xab, 0x62,
-       0x3d, 0x6b, 0x34, 0x57, 0x5a, 0x8f, 0xdb, 0x50, 0x37, 0xe0, 0x36, 0xb1,
-       0xa7, 0x0d, 0xe5, 0x41, 0xb6, 0x06, 0x70, 0xda, 0x6e, 0x63, 0x16, 0x2d,
-       0xde, 0x6b, 0xdd, 0xe1, 0xfe, 0xdc, 0xb7, 0x55, 0xd6, 0xc8, 0x2a, 0x6f,
-       0x62, 0xf4, 0x7e, 0x17, 0xfb, 0xbd, 0xce, 0xb1, 0xc8, 0x36, 0xff, 0x4a,
-       0xdc, 0x7f, 0x16, 0x7b, 0x9e, 0x5b, 0x6c, 0x73, 0xdb, 0x40, 0x23, 0x7b,
-       0xa3, 0x25, 0x54, 0xf8, 0x5f, 0x86, 0xf3, 0xfd, 0x1f, 0xff, 0x2b, 0xd2,
-       0xaa, 0xe0, 0x74, 0xa5, 0x00, 0x7c, 0x2c, 0xb3, 0x0d, 0xbd, 0xdb, 0x18,
-       0x37, 0x70, 0x14, 0xd8, 0x25, 0x38, 0x71, 0xbf, 0xa5, 0x6e, 0x44, 0xed,
-       0x78, 0xae, 0x2b, 0x3c, 0x17, 0x62, 0x92, 0xbd, 0xf8, 0x07, 0x70, 0xa3,
-       0x49, 0x79, 0x9a, 0xdf, 0xce, 0xd3, 0x85, 0x41, 0x9e, 0x66, 0xae, 0xe9,
-       0xf0, 0x43, 0x14, 0x75, 0x2a, 0xac, 0x51, 0xe0, 0x6d, 0x73, 0x3f, 0xab,
-       0xa4, 0xc8, 0xbc, 0x0e, 0xb4, 0x6f, 0x13, 0xad, 0x0d, 0x74, 0xf8, 0x4d,
-       0x1d, 0x19, 0x5b, 0xa6, 0x97, 0x7f, 0x46, 0xf4, 0xf2, 0x80, 0x6d, 0x79,
-       0xfc, 0xc4, 0xa6, 0x89, 0x3d, 0xcb, 0xc0, 0xfc, 0xc2, 0x40, 0x46, 0xbc,
-       0x40, 0x3c, 0xed, 0x7b, 0x88, 0x93, 0x35, 0x3c, 0x4b, 0x88, 0x9d, 0x8c,
-       0x0d, 0xc7, 0x91, 0x5d, 0xe0, 0xb3, 0x8c, 0xb6, 0xb3, 0xa8, 0x4b, 0xf4,
-       0xae, 0xd8, 0x3a, 0xd5, 0x9c, 0x49, 0x6a, 0x67, 0xb1, 0x4a, 0x70, 0xac,
-       0x3a, 0x08, 0x4e, 0x1d, 0x40, 0xfc, 0xf9, 0x9d, 0x32, 0x1e, 0xab, 0x10,
-       0xd3, 0x8a, 0x87, 0x11, 0x9b, 0xfa, 0xa8, 0xe7, 0xf1, 0x6e, 0xe1, 0x7d,
-       0x00, 0xe5, 0xc3, 0xe8, 0x3b, 0x1a, 0xa7, 0x32, 0xbb, 0x27, 0xc5, 0x28,
-       0xf0, 0x6e, 0xc3, 0x40, 0x7f, 0x13, 0xba, 0x61, 0x7f, 0xe7, 0x10, 0x3f,
-       0xd8, 0xe7, 0x39, 0xf8, 0x54, 0xc7, 0xdc, 0x82, 0x66, 0xb7, 0xa9, 0xa5,
-       0xa4, 0xf1, 0xcb, 0x1f, 0xc6, 0xaf, 0x52, 0xcc, 0x83, 0x20, 0x14, 0xb0,
-       0x61, 0xfd, 0x66, 0x7a, 0x65, 0xec, 0xc8, 0xf5, 0xa0, 0x65, 0x4f, 0x89,
-       0xa2, 0x55, 0xa7, 0x40, 0x4d, 0xe0, 0xee, 0x42, 0xc3, 0x4d, 0x68, 0xd8,
-       0x1f, 0xd1, 0xb0, 0xff, 0x3f, 0x35, 0x0c, 0x7d, 0x42, 0x23, 0xb7, 0xc1,
-       0xa9, 0xb7, 0x7a, 0xfb, 0xe9, 0x99, 0xb5, 0xcc, 0x9a, 0x36, 0xe9, 0xce,
-       0xd1, 0xa7, 0xd5, 0x74, 0x49, 0x7e, 0x4a, 0x4d, 0xb7, 0x58, 0xd3, 0x2a,
-       0x6b, 0xba, 0xb8, 0x57, 0xd3, 0xd3, 0x18, 0x23, 0xd1, 0xe6, 0x19, 0xb5,
-       0x48, 0xda, 0x3c, 0xf0, 0xd8, 0xc8, 0x93, 0x72, 0xed, 0x31, 0xef, 0x98,
-       0xcb, 0xfe, 0x00, 0xff, 0xb6, 0x35, 0xb4, 0x49, 0xe3, 0xf5, 0x88, 0x81,
-       0x6a, 0xd5, 0x2a, 0xad, 0xc5, 0x7d, 0x54, 0xd2, 0xe1, 0xff, 0xd7, 0x8f,
-       0x5a, 0xa6, 0x29, 0x8f, 0x6a, 0x1f, 0xea, 0xdf, 0x88, 0xae, 0x68, 0x55,
-       0x9e, 0xa7, 0x65, 0x82, 0xf3, 0xe6, 0x4f, 0x80, 0x55, 0xbb, 0xcb, 0x7c,
-       0xb7, 0x45, 0x3d, 0xe6, 0x19, 0xca, 0xd0, 0x84, 0x06, 0xde, 0xe6, 0xd0,
-       0x4f, 0xdd, 0x48, 0x74, 0x74, 0x1b, 0xe3, 0x6e, 0x75, 0x99, 0x67, 0x06,
-       0xe9, 0xd7, 0xed, 0xd2, 0x85, 0x38, 0x06, 0xcf, 0x8a, 0x25, 0x62, 0x0d,
-       0xf2, 0xb9, 0x88, 0xf6, 0x41, 0x8e, 0x94, 0x58, 0xf7, 0x13, 0xa9, 0xee,
-       0x9f, 0x87, 0xaf, 0x26, 0x50, 0x66, 0xed, 0x1f, 0x4e, 0xb5, 0x3f, 0x85,
-       0x37, 0xd7, 0xad, 0xa8, 0x09, 0x87, 0xc0, 0xc7, 0x0d, 0xc6, 0x37, 0x8f,
-       0x58, 0xc7, 0xf3, 0xff, 0x33, 0x5a, 0xb5, 0x19, 0x63, 0xdb, 0xfc, 0x01,
-       0xcd, 0x41, 0x7f, 0xa8, 0xdf, 0xe6, 0xbe, 0x6c, 0x93, 0xf5, 0x15, 0x69,
-       0xdf, 0x0f, 0xf7, 0xf4, 0x45, 0xfd, 0x36, 0xf7, 0x63, 0x7d, 0x1c, 0x22,
-       0xe5, 0x3a, 0x9f, 0xdb, 0x1e, 0xeb, 0x03, 0x76, 0x35, 0xd4, 0x71, 0x6e,
-       0xc1, 0xf6, 0x7c, 0x86, 0xf3, 0x3a, 0x39, 0xef, 0xe0, 0x73, 0x7e, 0xcf,
-       0x79, 0x3e, 0xd4, 0xc8, 0x19, 0xf0, 0xfe, 0x3b, 0xea, 0x27, 0x35, 0xb2,
-       0x02, 0x4d, 0x5c, 0x54, 0x13, 0x8d, 0xbc, 0x86, 0xf7, 0x19, 0x94, 0x57,
-       0xf6, 0x68, 0x24, 0xb3, 0x7b, 0xf2, 0x39, 0x1e, 0xf4, 0x4a, 0xf1, 0x99,
-       0xcb, 0xf3, 0x29, 0x1b, 0xd4, 0xd2, 0x52, 0x3d, 0xd4, 0x87, 0x7a, 0x98,
-       0x40, 0xcc, 0xc8, 0xa5, 0x5c, 0xc7, 0xdb, 0xfe, 0x48, 0xf1, 0x1d, 0x4b,
-       0xb4, 0x89, 0xb5, 0x31, 0x7a, 0x9e, 0xfd, 0xbf, 0xf4, 0x41, 0xe0, 0x51,
-       0x3c, 0x37, 0x72, 0x11, 0x3e, 0x17, 0xa2, 0xe8, 0x15, 0x07, 0xed, 0x59,
-       0x4e, 0x12, 0x63, 0x9f, 0xc3, 0xd9, 0xcb, 0x78, 0x20, 0x0f, 0xb4, 0x67,
-       0xa1, 0x07, 0x8e, 0x05, 0xbb, 0xd1, 0x96, 0xed, 0xa1, 0xae, 0x06, 0xff,
-       0x33, 0x26, 0xcb, 0xd2, 0x52, 0xdf, 0x60, 0x3b, 0xe8, 0x6d, 0xbf, 0x5c,
-       0x4c, 0x87, 0xae, 0x1e, 0xe3, 0xc4, 0x3c, 0x6a, 0x8e, 0xe0, 0xd4, 0x88,
-       0x71, 0xda, 0x19, 0xe2, 0xd4, 0x4c, 0x71, 0x6a, 0xc6, 0x38, 0x3d, 0x48,
-       0x71, 0xfa, 0xf3, 0x13, 0x70, 0xda, 0x79, 0x0a, 0x9c, 0x0c, 0xda, 0xb2,
-       0x4b, 0x38, 0x6f, 0xf5, 0x38, 0x77, 0xbd, 0xef, 0xec, 0x97, 0x7b, 0xb1,
-       0xdf, 0xc7, 0xb0, 0x8a, 0x18, 0xab, 0x2d, 0x1a, 0xcd, 0x43, 0x2c, 0xf3,
-       0x1e, 0x15, 0x70, 0x6e, 0xe4, 0xe9, 0xea, 0x9e, 0x5c, 0x24, 0x00, 0x4e,
-       0xb5, 0x14, 0xa7, 0xab, 0xc0, 0xa9, 0x96, 0xe2, 0xb4, 0x3e, 0x82, 0xd3,
-       0xfa, 0x18, 0x4e, 0x1c, 0x53, 0x2a, 0xc6, 0x7a, 0x37, 0xc3, 0x28, 0xc3,
-       0x47, 0xa7, 0x9b, 0x62, 0x0a, 0xfb, 0x3f, 0x4e, 0xed, 0x9f, 0xaa, 0x9c,
-       0xff, 0x02, 0xbb, 0x97, 0x54, 0x39, 0x3e, 0x17, 0xf8, 0xfb, 0x71, 0xbe,
-       0x82, 0xb9, 0x5c, 0xcf, 0xe1, 0x3d, 0x21, 0xcf, 0xb5, 0x47, 0x63, 0xd1,
-       0x07, 0x88, 0x45, 0x5c, 0xc7, 0xfd, 0x54, 0xa9, 0x06, 0xcd, 0x2b, 0xc8,
-       0xe1, 0xfd, 0x61, 0x0e, 0x9f, 0xf8, 0xe1, 0x6a, 0x9a, 0xc3, 0x6f, 0xd9,
-       0x9c, 0xc3, 0x9f, 0xd0, 0x68, 0x62, 0x39, 0xc5, 0x93, 0x79, 0x3d, 0x89,
-       0xb6, 0xb3, 0x31, 0xee, 0x6d, 0xc4, 0xf2, 0x55, 0xf8, 0xa0, 0x19, 0xf3,
-       0x13, 0x79, 0x57, 0xca, 0x5d, 0xe4, 0xbb, 0xe4, 0x87, 0x09, 0x4f, 0x3f,
-       0xdb, 0x5c, 0xec, 0xef, 0x88, 0xd9, 0x46, 0x43, 0xc5, 0x1d, 0xe0, 0x6e,
-       0x18, 0xc7, 0xea, 0x73, 0x41, 0x97, 0x5a, 0x47, 0xaa, 0x57, 0x22, 0xe0,
-       0xee, 0x7e, 0xfd, 0x34, 0x9f, 0x39, 0xf9, 0x45, 0xaf, 0x82, 0xfa, 0x81,
-       0x41, 0xc8, 0x83, 0x70, 0xa7, 0xa1, 0x96, 0x77, 0x5a, 0x42, 0xbe, 0x83,
-       0x32, 0x6c, 0x82, 0x70, 0xba, 0x21, 0x57, 0x4b, 0xe0, 0x43, 0x8b, 0x5c,
-       0xac, 0xd3, 0x0d, 0xe3, 0x7b, 0x4d, 0x43, 0xa9, 0x1a, 0xc8, 0x37, 0xc9,
-       0xc0, 0x99, 0x0f, 0x9f, 0x98, 0x46, 0x7b, 0x80, 0x9c, 0x08, 0x79, 0x80,
-       0xb7, 0x08, 0xbf, 0x1c, 0x03, 0x76, 0xa1, 0x0a, 0xdb, 0x6f, 0xe9, 0xc9,
-       0x9d, 0x88, 0xc8, 0x8b, 0xfd, 0xf5, 0x71, 0xca, 0x91, 0x38, 0xe7, 0x92,
-       0x6a, 0x3d, 0x32, 0x9b, 0x0e, 0xb8, 0x8e, 0x33, 0xa5, 0x13, 0x72, 0x5e,
-       0x7d, 0xcc, 0x90, 0xaf, 0x71, 0x3c, 0x7f, 0x00, 0x1f, 0xe2, 0x7b, 0x9b,
-       0xcf, 0x19, 0x85, 0x73, 0x73, 0xdc, 0x7d, 0xca, 0x88, 0x37, 0x34, 0x89,
-       0xd8, 0x87, 0xd8, 0x3b, 0xcd, 0x58, 0xb9, 0xc9, 0x19, 0xc4, 0xe3, 0x1d,
-       0x97, 0x93, 0x79, 0xfe, 0xa4, 0x25, 0x1c, 0xc6, 0x7d, 0x07, 0xfe, 0x5b,
-       0xed, 0x39, 0x1c, 0x73, 0x3f, 0xaf, 0xd0, 0x43, 0x8a, 0x39, 0x29, 0x4e,
-       0x20, 0x16, 0x9f, 0x86, 0x8d, 0x1b, 0xeb, 0x31, 0xc9, 0xbd, 0x32, 0x9b,
-       0x0f, 0xf7, 0x8c, 0xf1, 0x17, 0x65, 0xbc, 0xec, 0x82, 0xd3, 0x95, 0x74,
-       0xbe, 0x51, 0x8e, 0x2c, 0x20, 0xe5, 0x79, 0xa0, 0x0d, 0xf3, 0xb7, 0xa2,
-       0x8e, 0x7e, 0xbc, 0x46, 0xd6, 0x25, 0xdb, 0x1c, 0xd1, 0xc6, 0xc7, 0x99,
-       0xdd, 0x67, 0x8c, 0xea, 0xc8, 0x18, 0x45, 0xde, 0x9b, 0x68, 0x3a, 0xcf,
-       0xa4, 0xf7, 0x0c, 0x8e, 0x2d, 0x02, 0x3a, 0x95, 0x9f, 0x93, 0xb1, 0x0f,
-       0x0f, 0x7b, 0xf6, 0xe3, 0xfa, 0x5f, 0xe9, 0xe3, 0xe3, 0xfe, 0x56, 0x4d,
-       0xca, 0xc7, 0x12, 0x6e, 0xda, 0x78, 0x87, 0x0f, 0x46, 0xd6, 0xae, 0xed,
-       0x33, 0xef, 0xd7, 0x38, 0x5d, 0x43, 0xbc, 0x21, 0x57, 0xc1, 0x1d, 0xcc,
-       0x27, 0x7c, 0x87, 0xaf, 0x67, 0x3e, 0x04, 0x6f, 0xe8, 0x5c, 0x3b, 0xe5,
-       0x8b, 0x9c, 0xf0, 0x85, 0xf3, 0xba, 0xc5, 0x55, 0xf0, 0xa5, 0x0d, 0xbe,
-       0xc0, 0xae, 0xa1, 0x55, 0xa7, 0xc1, 0x05, 0x8e, 0x4d, 0x28, 0x87, 0xcc,
-       0x1d, 0xe6, 0x0a, 0xf3, 0xe6, 0x31, 0x5f, 0x5e, 0xe9, 0x1a, 0xc6, 0xe6,
-       0xa7, 0x70, 0xe5, 0x8d, 0x98, 0x2b, 0xcc, 0xd9, 0x24, 0x7e, 0x74, 0x80,
-       0x55, 0x90, 0xc6, 0x8f, 0x00, 0xf1, 0xa3, 0xc6, 0xf9, 0x4f, 0x1c, 0x0b,
-       0x12, 0xfd, 0xac, 0x41, 0x3f, 0x35, 0x85, 0xf3, 0x23, 0xd6, 0x0e, 0xdb,
-       0xb1, 0x7e, 0xd8, 0xae, 0x90, 0xda, 0x8d, 0xc7, 0x91, 0x76, 0xcf, 0x32,
-       0xb3, 0x38, 0xd2, 0x86, 0x76, 0x3a, 0xa9, 0x8e, 0xda, 0xa9, 0x8e, 0xd0,
-       0xa7, 0xa5, 0x54, 0xf8, 0x4c, 0xb0, 0x4c, 0x1f, 0xf1, 0xa3, 0x13, 0x8f,
-       0xd9, 0xa2, 0xe4, 0x2e, 0xc3, 0xda, 0xe6, 0xb8, 0x3b, 0x12, 0x6f, 0xd3,
-       0x7b, 0x6e, 0x23, 0xbe, 0xe7, 0x7e, 0x45, 0x1f, 0x8f, 0xb7, 0x38, 0x6b,
-       0xe2, 0x7b, 0xee, 0x29, 0x9d, 0xef, 0xb9, 0x01, 0x7d, 0x49, 0x1f, 0xbd,
-       0xe7, 0x06, 0x63, 0xf7, 0xdc, 0xcc, 0x96, 0xeb, 0xf7, 0x8b, 0xbb, 0x99,
-       0x4f, 0x38, 0xf6, 0x32, 0x9f, 0xf6, 0xcb, 0x15, 0xb3, 0x3e, 0x1c, 0x93,
-       0x58, 0xef, 0x1c, 0xcb, 0x92, 0xdc, 0xec, 0x6e, 0x98, 0xe9, 0xe2, 0x55,
-       0xcc, 0x83, 0x72, 0x6f, 0x3f, 0x5d, 0x18, 0xa9, 0x2e, 0x26, 0x13, 0x9b,
-       0xde, 0xa8, 0x36, 0x5e, 0xd5, 0xc7, 0xb5, 0x91, 0x8d, 0x93, 0x69, 0x23,
-       0x19, 0x73, 0x47, 0x29, 0xe1, 0x0c, 0x2c, 0x23, 0x1e, 0x09, 0xbe, 0xa3,
-       0x21, 0x5e, 0x54, 0xf3, 0xb8, 0xa7, 0x14, 0x78, 0xec, 0x76, 0xf8, 0x2c,
-       0x35, 0x8a, 0x8c, 0x0b, 0xaf, 0xff, 0x61, 0x7c, 0x7f, 0xc0, 0xba, 0x0b,
-       0x01, 0xff, 0xfe, 0xf1, 0x09, 0x3e, 0xbe, 0x06, 0x3e, 0x66, 0xfb, 0x19,
-       0xad, 0xbf, 0x34, 0x52, 0x5f, 0x4e, 0x31, 0x4f, 0x7c, 0x7e, 0x2f, 0xd5,
-       0xc8, 0x26, 0x72, 0xb7, 0xfb, 0xc8, 0x8b, 0xde, 0x44, 0xfc, 0x0e, 0x06,
-       0x1f, 0x47, 0xf7, 0x8a, 0x2a, 0x75, 0x86, 0x36, 0xbf, 0xc0, 0xba, 0x2d,
-       0x71, 0x13, 0x5f, 0x6f, 0x0c, 0xb2, 0xb1, 0xb9, 0x9d, 0xeb, 0xfe, 0x8d,
-       0xf3, 0x19, 0x79, 0xdf, 0xb0, 0xef, 0xfb, 0x11, 0xe7, 0xbb, 0x77, 0x81,
-       0xc5, 0x3b, 0xe1, 0x34, 0xfd, 0x1e, 0x1c, 0x7b, 0x3b, 0xce, 0x79, 0x93,
-       0x5c, 0x17, 0xfe, 0xc3, 0x99, 0xc7, 0x67, 0xbd, 0xf7, 0x39, 0x99, 0x2e,
-       0xd3, 0x57, 0x1d, 0xae, 0x93, 0xa9, 0x7e, 0x2a, 0x8a, 0x2e, 0xe2, 0xdc,
-       0x5f, 0x19, 0x3b, 0xf7, 0x71, 0x07, 0x3c, 0xc9, 0xf9, 0x7f, 0x96, 0xf3,
-       0xef, 0x46, 0x33, 0xf3, 0xd6, 0x4d, 0x97, 0x5c, 0xa9, 0xde, 0xe7, 0x7c,
-       0x6c, 0x98, 0x8b, 0x11, 0x1d, 0x7a, 0x14, 0xc9, 0xf3, 0x7c, 0x36, 0xbd,
-       0x9b, 0xfa, 0x1c, 0x6d, 0x37, 0x1e, 0xe1, 0x1e, 0x53, 0x8b, 0x7f, 0x17,
-       0x72, 0xfb, 0x3c, 0x0f, 0x97, 0xf1, 0x0e, 0x39, 0x47, 0x78, 0xd2, 0x6f,
-       0x35, 0x2a, 0xf0, 0xb5, 0xcc, 0x75, 0x85, 0xe2, 0x7b, 0x21, 0xee, 0x6e,
-       0x3f, 0x6f, 0x53, 0x12, 0x3b, 0x6a, 0xce, 0x39, 0xac, 0x05, 0x98, 0x88,
-       0x06, 0x30, 0x9e, 0x47, 0xac, 0xb2, 0xcc, 0x93, 0x72, 0xf2, 0x5b, 0xd5,
-       0x1a, 0xc6, 0x56, 0x4e, 0x72, 0x2e, 0xf9, 0x51, 0xb4, 0x36, 0x88, 0xcf,
-       0x44, 0x87, 0xb9, 0xe6, 0x87, 0x07, 0x65, 0x7e, 0xbb, 0x21, 0x7f, 0xeb,
-       0x98, 0xc7, 0x7c, 0x02, 0x0f, 0x8b, 0xa2, 0x76, 0xc3, 0x14, 0xf5, 0x9e,
-       0x29, 0x96, 0x7a, 0x32, 0x54, 0x52, 0xc8, 0xd1, 0x14, 0xe7, 0x08, 0x3a,
-       0xd1, 0x73, 0x58, 0xcb, 0x2d, 0x53, 0xf8, 0xc8, 0xa3, 0xbe, 0xad, 0x58,
-       0x62, 0x85, 0x76, 0xb1, 0xc7, 0x47, 0x51, 0x72, 0xa7, 0x35, 0x45, 0x6d,
-       0x38, 0xf7, 0x23, 0xcc, 0xcd, 0x6b, 0x62, 0x2d, 0xf3, 0x79, 0xb6, 0x2c,
-       0x9d, 0x83, 0x8f, 0xce, 0xf7, 0x77, 0x11, 0x43, 0xf9, 0x3c, 0xcb, 0x23,
-       0xe6, 0x59, 0x26, 0x5f, 0xf6, 0xef, 0x62, 0xff, 0xef, 0xf4, 0x80, 0x0f,
-       0x72, 0xc7, 0xb7, 0x87, 0x79, 0x1a, 0x63, 0x58, 0x06, 0x17, 0xd9, 0x3e,
-       0x8a, 0x82, 0xc5, 0x38, 0x47, 0xc1, 0x5a, 0xe6, 0xca, 0xb7, 0x90, 0xa7,
-       0xd7, 0x69, 0xa1, 0x5c, 0x8f, 0xdf, 0x11, 0x72, 0x12, 0xfe, 0x5d, 0xc0,
-       0x12, 0x4d, 0x7c, 0xd7, 0xd2, 0xef, 0x80, 0x73, 0xf8, 0x45, 0x1e, 0x83,
-       0x73, 0x79, 0xd6, 0xe1, 0x7f, 0x01, 0x17, 0xc6, 0xf1, 0xb2, 0x84, 0x14,
-       0x00, 0x00, 0x00 };
-static u32 bnx2_TPAT_b09FwData[(0x0/4) + 1] = { 0x0 };
-static u32 bnx2_TPAT_b09FwRodata[(0x0/4) + 1] = { 0x0 };
-static u32 bnx2_TPAT_b09FwBss[(0x250/4) + 1] = { 0x0 };
-static u32 bnx2_TPAT_b09FwSbss[(0x34/4) + 1] = { 0x0 };
+       0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xcd, 0x58,
+       0x5d, 0x68, 0x1c, 0xd7, 0x15, 0x3e, 0xf3, 0xb7, 0x3b, 0x52, 0x24, 0xeb,
+       0x5a, 0xd9, 0xa6, 0xeb, 0xa0, 0x34, 0x33, 0xda, 0x91, 0xac, 0x22, 0x13,
+       0x4f, 0x9d, 0x25, 0x16, 0x65, 0x21, 0x93, 0xd9, 0x91, 0xac, 0x98, 0x3c,
+       0x28, 0xc5, 0x90, 0x87, 0x52, 0x50, 0x57, 0x32, 0x09, 0x79, 0x69, 0xda,
+       0xc6, 0x90, 0x3e, 0x79, 0x3b, 0x2b, 0xc7, 0x0e, 0x6c, 0xbc, 0x8d, 0x52,
+       0xe4, 0x52, 0xfa, 0x60, 0xd6, 0xb1, 0x05, 0xcd, 0x46, 0x93, 0xd4, 0x7e,
+       0x35, 0x36, 0x4e, 0x93, 0xa7, 0x42, 0x9f, 0x52, 0xf4, 0x18, 0xd2, 0x12,
+       0xda, 0x52, 0x8a, 0x69, 0xa1, 0x09, 0x8d, 0xeb, 0xdb, 0xef, 0xdc, 0x99,
+       0x91, 0x57, 0xb6, 0xec, 0xa4, 0x25, 0x85, 0x0a, 0x56, 0x77, 0xe6, 0xce,
+       0x3d, 0xe7, 0x9e, 0x7b, 0xee, 0x77, 0xbe, 0x73, 0xee, 0x2d, 0xeb, 0x34,
+       0x48, 0xd9, 0xdf, 0x30, 0x7e, 0x2f, 0x7e, 0xf7, 0x85, 0x17, 0xab, 0x8f,
+       0x3c, 0xea, 0x10, 0x3d, 0xfa, 0x88, 0x66, 0x98, 0x06, 0x7d, 0x09, 0x7f,
+       0x50, 0x22, 0x72, 0xfd, 0xfc, 0x23, 0x5b, 0xaf, 0x9d, 0x72, 0x42, 0x8f,
+       0x6c, 0xa3, 0x26, 0xbe, 0xbe, 0xe4, 0x11, 0x05, 0xbd, 0x69, 0xa7, 0x4e,
+       0xff, 0x92, 0xcd, 0x92, 0x49, 0xdc, 0xff, 0x50, 0xed, 0xc6, 0xfe, 0xcb,
+       0x07, 0xdd, 0xeb, 0x67, 0x0d, 0xb2, 0x45, 0x6d, 0xd1, 0x16, 0x93, 0x64,
+       0x8f, 0xd5, 0x9a, 0xce, 0x2f, 0xf6, 0x1e, 0x28, 0xd0, 0xae, 0x5c, 0x97,
+       0xa0, 0xb8, 0x43, 0x4d, 0xab, 0x66, 0x53, 0xd4, 0x7e, 0x49, 0x0b, 0x3b,
+       0x9e, 0x98, 0x85, 0x8e, 0xa0, 0x04, 0xfd, 0x1e, 0xde, 0x13, 0x53, 0x8b,
+       0xce, 0xd8, 0xa4, 0xd7, 0x02, 0x3c, 0x4f, 0x51, 0xab, 0x23, 0xe5, 0x2b,
+       0xbe, 0x46, 0x4b, 0xbe, 0x4d, 0x8b, 0xc2, 0x0d, 0x1c, 0xed, 0xa6, 0xac,
+       0x4c, 0x48, 0xf9, 0x9c, 0xaf, 0x93, 0xee, 0xcd, 0x69, 0xe1, 0xfa, 0xbc,
+       0x56, 0x5f, 0x9f, 0x67, 0x7f, 0xc0, 0xbe, 0x39, 0x2d, 0x58, 0xe7, 0xb6,
+       0x66, 0xd7, 0xdb, 0xbb, 0x68, 0xb1, 0x44, 0x23, 0xba, 0x37, 0x85, 0xf9,
+       0x4a, 0xd0, 0xe3, 0x50, 0xe8, 0x4f, 0x0b, 0x9d, 0x2a, 0xf8, 0x0d, 0xd0,
+       0xac, 0x4f, 0x03, 0xba, 0xa7, 0x53, 0xa3, 0xa4, 0xd1, 0x1b, 0x55, 0x0b,
+       0xbf, 0xc3, 0x5a, 0xb4, 0xfe, 0x7c, 0xa6, 0x87, 0xc7, 0xdb, 0xf8, 0xc6,
+       0x36, 0xb3, 0x7c, 0xbf, 0xec, 0x30, 0x9e, 0x9f, 0xc3, 0x38, 0x8b, 0xc2,
+       0xea, 0xed, 0xdf, 0x06, 0xf0, 0xac, 0xa1, 0xff, 0x30, 0xec, 0x62, 0x3d,
+       0x0e, 0xec, 0x28, 0xd3, 0x4a, 0x67, 0x1e, 0xeb, 0x29, 0x50, 0x53, 0x4c,
+       0x4c, 0x35, 0xc8, 0x84, 0x8c, 0x41, 0x41, 0xe9, 0x8a, 0xd4, 0x6b, 0x52,
+       0x86, 0x55, 0x6f, 0xaa, 0xab, 0xe6, 0xd0, 0xc9, 0xf0, 0x0a, 0x14, 0xf9,
+       0xc3, 0xd4, 0x12, 0x06, 0xc5, 0xfb, 0x2c, 0x0a, 0x16, 0x4c, 0xac, 0x71,
+       0x14, 0x72, 0x1a, 0xe4, 0x5f, 0xcb, 0xf6, 0xbc, 0x48, 0xb1, 0x28, 0xa0,
+       0x7f, 0x84, 0xe2, 0xd2, 0x6e, 0x4d, 0xaf, 0xbd, 0x82, 0xfe, 0x09, 0xd1,
+       0xa5, 0x53, 0x68, 0x35, 0xbc, 0xef, 0xc6, 0x58, 0x7e, 0xd7, 0xa0, 0x8f,
+       0x44, 0x98, 0x78, 0xd4, 0x4a, 0x72, 0x59, 0xee, 0x4f, 0xfb, 0x9a, 0xc9,
+       0xed, 0xfb, 0xed, 0xc1, 0x4e, 0x41, 0x27, 0x3a, 0xb3, 0x98, 0x8f, 0x9a,
+       0x46, 0x0d, 0xe3, 0xb0, 0x37, 0xbc, 0xbf, 0x81, 0xc2, 0xc1, 0xe3, 0xdc,
+       0xcf, 0x7f, 0xe8, 0x77, 0xc8, 0xa8, 0xf1, 0xb7, 0x6f, 0x52, 0xfa, 0x2d,
+       0xb5, 0x3f, 0xf4, 0x1f, 0xcb, 0xde, 0x4b, 0x22, 0x3c, 0xf3, 0x28, 0xd6,
+       0xa8, 0x60, 0x83, 0xe7, 0x02, 0xf0, 0x11, 0xcf, 0xe8, 0xd4, 0x2c, 0x17,
+       0xc9, 0xf5, 0x8f, 0xa2, 0xf7, 0xd7, 0x6d, 0x83, 0xea, 0xec, 0x2b, 0xdf,
+       0xcc, 0x64, 0x18, 0x1b, 0x1f, 0x64, 0x76, 0x0a, 0x5a, 0x3c, 0x22, 0xe5,
+       0x8a, 0x2f, 0xa5, 0x55, 0xf3, 0x9c, 0x13, 0x34, 0x5d, 0x36, 0x69, 0x52,
+       0xa0, 0x85, 0x8f, 0xbd, 0x72, 0x83, 0x2c, 0x60, 0xa1, 0x1f, 0xff, 0xfc,
+       0xf7, 0xa6, 0x86, 0x25, 0xd0, 0xb5, 0x36, 0xeb, 0x98, 0x70, 0x66, 0x95,
+       0x8c, 0x94, 0xf1, 0xcc, 0xbd, 0x64, 0x2e, 0x65, 0x32, 0x52, 0x46, 0x55,
+       0x81, 0x3d, 0x6f, 0x0a, 0xd8, 0x87, 0x75, 0x31, 0xc6, 0x89, 0xa2, 0x9e,
+       0x6f, 0x37, 0xda, 0xb0, 0xd1, 0x43, 0xdb, 0x13, 0xf0, 0x0f, 0x51, 0x0b,
+       0x63, 0xf5, 0xea, 0x7d, 0x8c, 0x0d, 0xec, 0xef, 0x82, 0x1d, 0xb5, 0xdd,
+       0xf2, 0x29, 0x5a, 0xb0, 0xeb, 0xbd, 0xe9, 0xf2, 0x32, 0x3d, 0xc4, 0x73,
+       0xd8, 0x56, 0xed, 0x88, 0xdd, 0x55, 0x72, 0x88, 0xc4, 0x41, 0x3c, 0xf7,
+       0x88, 0xe2, 0x36, 0x69, 0xa1, 0x7f, 0x1f, 0xaf, 0x15, 0x72, 0xf3, 0x99,
+       0xdc, 0x7c, 0x26, 0x37, 0x92, 0xc9, 0x3d, 0xd5, 0x27, 0xf7, 0x14, 0xcb,
+       0x61, 0x6c, 0x90, 0x8d, 0x0d, 0xb2, 0xb1, 0x66, 0x36, 0x36, 0xca, 0xc6,
+       0xa2, 0xed, 0x8d, 0xc1, 0x36, 0x77, 0xca, 0xd1, 0x6c, 0x8a, 0x3d, 0xf9,
+       0x70, 0xe8, 0x53, 0x50, 0xf7, 0xdc, 0xcd, 0xba, 0x31, 0x42, 0xe7, 0xfc,
+       0x21, 0x5a, 0x49, 0xc6, 0x28, 0x4e, 0x56, 0x28, 0x4c, 0x74, 0xc8, 0x8e,
+       0x50, 0xd7, 0xbb, 0x2e, 0x67, 0x7d, 0x1f, 0x7b, 0x66, 0xb3, 0x5c, 0x79,
+       0x96, 0x1c, 0x7c, 0x9f, 0x16, 0xcb, 0xe4, 0x03, 0x2b, 0x3a, 0xf6, 0xad,
+       0xa2, 0x9e, 0xe3, 0xc4, 0xe7, 0x35, 0x37, 0xf5, 0xaa, 0x2b, 0x62, 0x72,
+       0xcb, 0xa1, 0x41, 0x42, 0xaf, 0xc1, 0x4f, 0x49, 0x93, 0xa2, 0xc4, 0xa6,
+       0x0f, 0x8d, 0x97, 0x54, 0x8c, 0xc6, 0x9d, 0x4d, 0x79, 0x79, 0xaf, 0x43,
+       0x57, 0x30, 0xcf, 0xc5, 0xa4, 0x4c, 0xbf, 0x4a, 0x4a, 0xf4, 0x4e, 0x42,
+       0x7a, 0xe8, 0x03, 0xc3, 0x25, 0x41, 0x6f, 0x27, 0xfd, 0x3e, 0xff, 0x88,
+       0x7d, 0x6e, 0xdf, 0x5f, 0x23, 0x7b, 0xb4, 0xc6, 0x38, 0x4b, 0x39, 0xa0,
+       0x9e, 0x72, 0x80, 0xc2, 0x52, 0xab, 0x13, 0x3f, 0x68, 0x80, 0x7f, 0x96,
+       0xfc, 0x60, 0xb7, 0xa1, 0xf6, 0xa3, 0x89, 0x3d, 0xcc, 0x5b, 0xde, 0x9b,
+       0xab, 0xce, 0x92, 0xe7, 0x9e, 0xaa, 0x33, 0x6a, 0x4f, 0x5b, 0x39, 0x2e,
+       0xfb, 0xe6, 0xf8, 0x33, 0xe6, 0x18, 0xa2, 0x06, 0xe2, 0xec, 0x09, 0x13,
+       0xb1, 0xe3, 0xfd, 0xdd, 0x60, 0x5c, 0x39, 0x1b, 0x8c, 0x6f, 0xa2, 0xf1,
+       0x0d, 0x9b, 0xd6, 0xdb, 0x45, 0x72, 0xba, 0x43, 0xb4, 0xd4, 0x19, 0xa4,
+       0xca, 0x05, 0x13, 0x63, 0xef, 0xa3, 0xca, 0xaa, 0x5e, 0xe2, 0x38, 0xae,
+       0xc3, 0xc7, 0xe3, 0x5d, 0x09, 0x7c, 0x0e, 0xd2, 0xf8, 0x9a, 0xab, 0xb0,
+       0xb3, 0xe4, 0xb5, 0x7c, 0x83, 0x7e, 0x4c, 0xd7, 0xf6, 0x15, 0xb0, 0xa6,
+       0x12, 0xf9, 0x93, 0xfd, 0xf3, 0xe9, 0x80, 0x18, 0xf7, 0xc5, 0x45, 0xda,
+       0xe5, 0x3a, 0xa4, 0xb3, 0x3e, 0x9b, 0xc6, 0x2f, 0xd8, 0x5a, 0xbd, 0xc3,
+       0x3e, 0x63, 0xfc, 0xd9, 0x19, 0xfe, 0x4c, 0x2d, 0x3c, 0x53, 0xc4, 0x5c,
+       0x7f, 0x91, 0xa1, 0x27, 0xb1, 0x0f, 0x3a, 0x2d, 0x55, 0x7f, 0x04, 0xfb,
+       0xd0, 0xd7, 0xe5, 0x6f, 0xd7, 0xb3, 0x7e, 0xd6, 0x01, 0x7e, 0xf0, 0xef,
+       0xa7, 0x90, 0xb9, 0xe0, 0x08, 0xcb, 0x14, 0x69, 0x7c, 0x95, 0xf9, 0x05,
+       0x6d, 0x97, 0xdf, 0x79, 0x6d, 0x03, 0xd4, 0x80, 0x57, 0x1a, 0x53, 0x25,
+       0xd8, 0xa5, 0x2b, 0xbe, 0x68, 0x80, 0x3f, 0x74, 0x6f, 0x10, 0x2d, 0xcf,
+       0xf7, 0x73, 0x23, 0x8f, 0xa9, 0xb8, 0x33, 0x44, 0x75, 0xe0, 0xd7, 0x84,
+       0x3d, 0xcb, 0x34, 0x51, 0x3e, 0xaa, 0xbe, 0xa1, 0xaf, 0xc7, 0xdf, 0xc4,
+       0x6d, 0xdf, 0xf0, 0xde, 0xcb, 0x6d, 0x40, 0x6c, 0x7b, 0x2d, 0xcc, 0x62,
+       0x65, 0x7e, 0xe1, 0xf1, 0xcd, 0x32, 0xf6, 0x06, 0x7c, 0x46, 0xf0, 0x25,
+       0x51, 0xb7, 0x6d, 0x82, 0x6f, 0xf4, 0xaf, 0xea, 0x2c, 0x57, 0x62, 0x3d,
+       0x58, 0xff, 0x9a, 0xa9, 0xd5, 0xcf, 0x78, 0xce, 0x1f, 0x88, 0xe5, 0x2b,
+       0xf0, 0xc1, 0xc4, 0x4c, 0x8b, 0xc7, 0xf7, 0x2c, 0xf2, 0x56, 0x9b, 0xc2,
+       0xc4, 0x9e, 0xc2, 0x73, 0x54, 0xff, 0xc9, 0x08, 0xf6, 0xda, 0x75, 0x5a,
+       0xf4, 0x5b, 0xd8, 0x53, 0x20, 0xaf, 0x6b, 0xd2, 0x1b, 0x6d, 0xf6, 0x85,
+       0x4d, 0x95, 0x35, 0x29, 0x4f, 0xfa, 0xbc, 0x27, 0xbf, 0x83, 0x5f, 0x08,
+       0x2b, 0x9c, 0x98, 0xf9, 0x08, 0xfb, 0xb3, 0xde, 0xe3, 0xbd, 0xb1, 0x94,
+       0x4f, 0xbc, 0xd5, 0x29, 0xec, 0xeb, 0x54, 0x66, 0x23, 0xef, 0x97, 0x49,
+       0x2b, 0x55, 0x9d, 0xce, 0x57, 0x3f, 0x93, 0xba, 0xc7, 0xfc, 0x5a, 0x80,
+       0x6f, 0x31, 0xae, 0x8b, 0x71, 0x49, 0x01, 0x3e, 0xfc, 0x07, 0x78, 0x45,
+       0xca, 0xf3, 0x55, 0xf4, 0xaf, 0x1e, 0x87, 0xad, 0x06, 0x64, 0x53, 0x8c,
+       0xb1, 0x3d, 0x73, 0xed, 0x7c, 0x7d, 0xde, 0xcc, 0x7b, 0x4a, 0xdf, 0x10,
+       0x4d, 0x6e, 0x0c, 0xd1, 0xb3, 0xbd, 0x21, 0x1a, 0x3f, 0xcd, 0x32, 0xe0,
+       0xa6, 0xaa, 0x27, 0x22, 0xc6, 0xa8, 0xa7, 0xfc, 0x50, 0x36, 0x74, 0x5e,
+       0x27, 0xbe, 0x6f, 0x10, 0x2d, 0xf7, 0x78, 0x0e, 0xb3, 0x4f, 0xa7, 0x4e,
+       0x87, 0x7e, 0x4a, 0x74, 0xa8, 0xc7, 0xb2, 0x5b, 0xbe, 0x83, 0x5e, 0x01,
+       0x9d, 0x82, 0x38, 0x0f, 0x19, 0x1e, 0xf2, 0xdd, 0x7a, 0x88, 0xfc, 0x15,
+       0xe1, 0x37, 0x87, 0x9c, 0xc6, 0xeb, 0x9f, 0x42, 0xfc, 0x31, 0x8f, 0xdf,
+       0xc4, 0xda, 0x0b, 0xb4, 0xe2, 0xcf, 0x63, 0x0c, 0xef, 0xf1, 0x61, 0x7c,
+       0x1f, 0x46, 0x1e, 0xc8, 0xf2, 0x84, 0xe0, 0x3c, 0xb1, 0x1b, 0x71, 0x30,
+       0x00, 0xee, 0xdf, 0x63, 0x6e, 0xcf, 0x13, 0x18, 0x57, 0xda, 0x83, 0xbc,
+       0x70, 0x3f, 0xfa, 0x59, 0xd7, 0x28, 0xda, 0x01, 0xbc, 0xef, 0xc1, 0xd8,
+       0xfe, 0x1c, 0x91, 0xcb, 0xdd, 0x2d, 0x3f, 0x20, 0x26, 0x56, 0x11, 0x2b,
+       0x6b, 0x9c, 0x27, 0x38, 0x16, 0x79, 0x4f, 0x8b, 0xe0, 0x6f, 0x1b, 0x3a,
+       0x78, 0x6f, 0x8b, 0xd8, 0x43, 0xce, 0x71, 0x82, 0x2a, 0x1b, 0x3b, 0xe5,
+       0x0f, 0x5e, 0x0f, 0x38, 0xec, 0x34, 0xaf, 0xc5, 0x15, 0x0d, 0xf0, 0x59,
+       0xb8, 0x31, 0x8d, 0xef, 0xc8, 0x85, 0x22, 0xb2, 0x1b, 0xa7, 0x53, 0x2e,
+       0x6b, 0x6c, 0x8c, 0x29, 0x9c, 0xc6, 0x89, 0xc0, 0x3b, 0x73, 0x59, 0xce,
+       0x5d, 0x8c, 0x25, 0x0a, 0x20, 0xbb, 0x19, 0x1a, 0x52, 0x2e, 0xf9, 0x23,
+       0xd4, 0x00, 0x2e, 0x03, 0xf0, 0x59, 0x03, 0x7c, 0x56, 0xef, 0xe3, 0xb3,
+       0xfa, 0xe7, 0xf2, 0x19, 0xb8, 0xaa, 0x03, 0xae, 0xea, 0x80, 0xab, 0x50,
+       0x1b, 0xbc, 0x03, 0xec, 0xbf, 0xdd, 0xd9, 0x89, 0xe3, 0x98, 0xdf, 0x98,
+       0xe7, 0xa6, 0xe8, 0xf2, 0xde, 0xff, 0x94, 0xe7, 0x8e, 0x83, 0x13, 0x6c,
+       0xfa, 0xfe, 0xde, 0x7b, 0x73, 0xdd, 0x09, 0x70, 0x9d, 0xf5, 0xf9, 0x5c,
+       0xd7, 0x64, 0xae, 0x33, 0x81, 0xbd, 0x26, 0x78, 0x40, 0x5f, 0xed, 0x9f,
+       0xe7, 0x24, 0xe6, 0xe1, 0x3e, 0x33, 0xcb, 0xa5, 0x3a, 0x75, 0x81, 0x7b,
+       0xc3, 0xe3, 0x79, 0x60, 0x73, 0x92, 0x72, 0xd1, 0x13, 0x66, 0x89, 0xac,
+       0x49, 0xe0, 0x61, 0x75, 0x88, 0x8c, 0xd3, 0xb7, 0xf0, 0x8e, 0x7a, 0x00,
+       0x71, 0x8e, 0x7f, 0x1b, 0xb9, 0x8e, 0x41, 0x70, 0x8d, 0x49, 0x85, 0x55,
+       0x0b, 0xef, 0xda, 0xb6, 0x71, 0x87, 0x90, 0x6f, 0x8c, 0x9a, 0x3b, 0xf3,
+       0x7b, 0x7e, 0xee, 0xf1, 0x98, 0x41, 0xd2, 0xd7, 0x5c, 0xc7, 0xd1, 0x5d,
+       0xff, 0x1a, 0xb8, 0xe1, 0x7d, 0x8f, 0xf9, 0x2f, 0x06, 0x0a, 0x0a, 0x64,
+       0xae, 0xca, 0xe3, 0x56, 0x8d, 0xe7, 0x6e, 0x3a, 0x88, 0x73, 0xe7, 0x35,
+       0xe0, 0x87, 0x73, 0xe7, 0xf9, 0x2a, 0xd7, 0x7b, 0x69, 0x8c, 0xb6, 0x7a,
+       0xf9, 0x9c, 0xa3, 0xb0, 0xdb, 0x82, 0x4c, 0xff, 0x58, 0xc6, 0x8b, 0x94,
+       0xcf, 0x62, 0x4d, 0x06, 0xe6, 0xb1, 0xd6, 0x6c, 0x2a, 0xac, 0xb1, 0x5f,
+       0x5c, 0xc8, 0x57, 0xc4, 0x1c, 0x6d, 0x6e, 0xe3, 0x83, 0x93, 0xbd, 0x0f,
+       0x4c, 0xe6, 0x50, 0x03, 0xb1, 0x59, 0xc4, 0xbc, 0xd6, 0x96, 0x2e, 0xca,
+       0x74, 0xb1, 0xbc, 0x57, 0x7e, 0x76, 0x4b, 0x9e, 0x79, 0x6d, 0xa2, 0xcc,
+       0xfc, 0xc5, 0x76, 0x18, 0x8a, 0x4b, 0x07, 0x33, 0x2e, 0xad, 0x60, 0x3f,
+       0x07, 0x55, 0x5c, 0xea, 0xde, 0xc3, 0x19, 0x9f, 0xee, 0x46, 0xcb, 0x7d,
+       0x37, 0xb2, 0x38, 0x31, 0x61, 0x2f, 0xeb, 0x1d, 0x24, 0x03, 0x76, 0x45,
+       0x6a, 0x4d, 0x7f, 0x93, 0x4b, 0x1e, 0x73, 0x04, 0xe3, 0x53, 0x71, 0x29,
+       0xfa, 0x27, 0x60, 0x33, 0xf3, 0x02, 0xcb, 0xb1, 0xfc, 0x4e, 0x72, 0x7f,
+       0x85, 0x9c, 0xd8, 0x41, 0x0e, 0x7d, 0x1b, 0x2c, 0xc3, 0xdc, 0x30, 0x8a,
+       0xf1, 0x21, 0xf3, 0x02, 0x7c, 0xc6, 0xb2, 0xe5, 0x2c, 0x0e, 0x23, 0x7c,
+       0xe3, 0xba, 0x97, 0xe3, 0x23, 0x20, 0xab, 0xc6, 0xeb, 0xe0, 0x9a, 0x98,
+       0xf3, 0x22, 0xd7, 0xa1, 0x5c, 0x6f, 0xe6, 0xf5, 0xa9, 0x37, 0x35, 0x7b,
+       0xb7, 0x5a, 0x53, 0xf4, 0xd7, 0x9a, 0xe8, 0xd8, 0xb1, 0xd6, 0xf4, 0xac,
+       0xb4, 0xd6, 0xac, 0x58, 0x77, 0xaf, 0x35, 0x73, 0xd9, 0x7b, 0xd7, 0x9a,
+       0x71, 0x87, 0xf7, 0x08, 0xb9, 0x54, 0xf0, 0x5a, 0xa8, 0x69, 0x66, 0x7c,
+       0x11, 0xdd, 0xc6, 0x17, 0xd1, 0x69, 0xb7, 0x7c, 0x8e, 0x38, 0xa6, 0xdd,
+       0x72, 0x8b, 0x6b, 0xa0, 0x0d, 0xae, 0x81, 0x0c, 0xe4, 0xd2, 0x7e, 0xce,
+       0xc8, 0x7d, 0xc2, 0xbe, 0x1c, 0x04, 0x27, 0xb3, 0x1f, 0x8b, 0x19, 0x3f,
+       0xa0, 0xf5, 0x3e, 0x05, 0x3f, 0xe4, 0xbc, 0xc2, 0x3e, 0xfb, 0x7f, 0xe2,
+       0x15, 0xb2, 0x07, 0xc0, 0x0f, 0x36, 0xea, 0xcd, 0x46, 0x47, 0xd9, 0x02,
+       0x5f, 0x48, 0x39, 0xe7, 0x33, 0xf6, 0x53, 0xbe, 0x50, 0x3e, 0x51, 0x78,
+       0x2c, 0xd2, 0xbb, 0x3e, 0x63, 0x01, 0xe7, 0x23, 0x8f, 0x73, 0x22, 0xf3,
+       0xef, 0x4d, 0xf9, 0xae, 0x17, 0xa2, 0x2f, 0xc2, 0x9e, 0x33, 0x0e, 0xe6,
+       0xb5, 0x43, 0xeb, 0x36, 0xe4, 0x18, 0x0b, 0xe5, 0x3b, 0xce, 0x3d, 0xe9,
+       0xf9, 0x84, 0x6b, 0xe1, 0xff, 0x16, 0x1b, 0x17, 0xef, 0x82, 0x8d, 0x37,
+       0x33, 0x6c, 0xfc, 0xf2, 0x1e, 0xd8, 0xb8, 0xf8, 0x05, 0xb1, 0xe1, 0x3a,
+       0x1f, 0xa3, 0x5e, 0x7a, 0xcf, 0x63, 0x7c, 0x48, 0xf9, 0xb1, 0xbf, 0x53,
+       0x3e, 0x09, 0x6c, 0xe3, 0xd5, 0x9b, 0x32, 0xce, 0x72, 0x89, 0xfe, 0xd6,
+       0xad, 0x5c, 0x32, 0xfe, 0x6a, 0x8a, 0x8b, 0xf1, 0xb7, 0xa4, 0x3c, 0xb7,
+       0x03, 0x0e, 0xb8, 0x56, 0xbe, 0x0a, 0x1e, 0x68, 0xd1, 0xff, 0xa2, 0x56,
+       0x66, 0xce, 0xae, 0xda, 0x47, 0xdb, 0xf9, 0xbe, 0xe7, 0x7b, 0x5e, 0xa0,
+       0xb3, 0x62, 0x17, 0xfc, 0xb5, 0x9f, 0x5a, 0xaf, 0x9b, 0x7c, 0x7e, 0x00,
+       0x1e, 0x1e, 0x37, 0x39, 0x56, 0x71, 0x56, 0xc4, 0x73, 0x7f, 0x3d, 0x0d,
+       0x3c, 0xfa, 0xbc, 0x76, 0xb5, 0xee, 0x3e, 0xae, 0xff, 0x1e, 0x4a, 0x92,
+       0x3b, 0xf2, 0xc8, 0xb6, 0x73, 0xb3, 0x81, 0x73, 0x73, 0x5d, 0xe9, 0xe0,
+       0xb3, 0x55, 0xea, 0xbf, 0x13, 0xea, 0xac, 0x7c, 0x53, 0x9e, 0x53, 0xe7,
+       0xe5, 0xd1, 0x02, 0x0d, 0xce, 0x67, 0x58, 0x61, 0x5f, 0x0c, 0xab, 0x7a,
+       0x82, 0x31, 0xd5, 0x42, 0xbe, 0x5d, 0x82, 0x3f, 0x1a, 0x2a, 0x16, 0xb0,
+       0xf6, 0xcc, 0x1f, 0x2d, 0xf8, 0xa3, 0x9e, 0xa4, 0x31, 0xf1, 0xe5, 0x9e,
+       0x1d, 0xfe, 0x88, 0x7c, 0x6a, 0x2f, 0x9a, 0x38, 0x6f, 0x5f, 0x49, 0x54,
+       0xfe, 0x5c, 0x68, 0xb5, 0xa9, 0xf9, 0x60, 0xed, 0x38, 0xd7, 0x6d, 0x5c,
+       0x77, 0xcd, 0x2c, 0x55, 0xd1, 0xd7, 0xb3, 0x29, 0x84, 0x4f, 0xbe, 0x7d,
+       0x90, 0x16, 0x8d, 0x1a, 0xe3, 0x17, 0xef, 0x09, 0x35, 0xc3, 0x83, 0xa8,
+       0xa5, 0x92, 0xb1, 0x45, 0xbd, 0x36, 0x06, 0x1c, 0x35, 0x29, 0x80, 0x9d,
+       0x01, 0x74, 0xcf, 0xb5, 0x6d, 0x7b, 0xb9, 0xcd, 0x67, 0xa4, 0x26, 0xf1,
+       0x19, 0xbc, 0xdb, 0xbb, 0x0e, 0x7d, 0x03, 0xcf, 0xe0, 0xcc, 0xea, 0xc4,
+       0xc0, 0xd5, 0xcb, 0x89, 0x45, 0xad, 0x12, 0xdf, 0x51, 0x30, 0x57, 0x96,
+       0xa1, 0xe3, 0x99, 0x42, 0x8a, 0xcb, 0x32, 0xf4, 0x70, 0xcc, 0x10, 0xe6,
+       0x63, 0xff, 0xe5, 0x58, 0x2b, 0xf7, 0xd5, 0xee, 0x85, 0xec, 0xbc, 0x4a,
+       0xca, 0x07, 0xec, 0xdf, 0xd0, 0x7b, 0xbe, 0x90, 0xdf, 0xc7, 0xb4, 0x10,
+       0xf3, 0x8d, 0x7d, 0x8c, 0x43, 0x0d, 0x78, 0xc3, 0x98, 0x84, 0xfb, 0x90,
+       0x57, 0xf6, 0x21, 0x37, 0x97, 0x8a, 0xaa, 0x6d, 0x26, 0xc7, 0xb2, 0xf1,
+       0xba, 0x1a, 0xc7, 0x39, 0x21, 0x4e, 0xd4, 0x59, 0x41, 0x8b, 0x3a, 0xe4,
+       0x34, 0x7c, 0x9c, 0x81, 0x50, 0x5b, 0xac, 0x24, 0x9c, 0xcf, 0xf7, 0xd9,
+       0xba, 0xe2, 0xb9, 0x4d, 0xc8, 0xe0, 0x79, 0x83, 0xf4, 0x86, 0xcf, 0xf7,
+       0x07, 0xd9, 0xdd, 0x46, 0x89, 0x86, 0x21, 0x0f, 0xbb, 0xc6, 0xd8, 0xae,
+       0xa0, 0xa1, 0x6a, 0x11, 0xd6, 0xbd, 0x5f, 0x4f, 0xef, 0x5c, 0x7e, 0x93,
+       0xcd, 0x65, 0x83, 0x5f, 0x08, 0xe7, 0x1d, 0x9f, 0xf3, 0xda, 0xd7, 0x0c,
+       0xba, 0x4e, 0x8a, 0x23, 0xc5, 0x37, 0x90, 0xef, 0x0e, 0x42, 0x26, 0x50,
+       0xfc, 0x92, 0x9e, 0x19, 0x72, 0x99, 0x8a, 0xb1, 0x5d, 0xc7, 0x77, 0xcc,
+       0xed, 0xef, 0x01, 0x62, 0xab, 0x9a, 0xcd, 0xd7, 0x8f, 0xd3, 0x4d, 0xe0,
+       0x74, 0xb3, 0xb0, 0x75, 0xee, 0x28, 0x15, 0x30, 0x8e, 0x6d, 0x64, 0x2e,
+       0x61, 0x99, 0x4f, 0xac, 0xed, 0x7a, 0x2a, 0x3b, 0xe8, 0xf8, 0x53, 0x9f,
+       0x8e, 0x12, 0xaf, 0x4d, 0x34, 0xd2, 0xf3, 0xb3, 0xfa, 0x6b, 0xc0, 0xcf,
+       0x38, 0x6f, 0x3c, 0xa0, 0x63, 0x1d, 0x5c, 0x7f, 0xd5, 0x55, 0x3f, 0x0e,
+       0x56, 0xdb, 0xf4, 0xfe, 0x30, 0x9b, 0x67, 0x5f, 0x1a, 0x0f, 0x1e, 0xda,
+       0x64, 0xb3, 0xcf, 0x76, 0x6b, 0x87, 0x79, 0x91, 0xd8, 0xbd, 0x19, 0x8d,
+       0xf1, 0x66, 0xd4, 0x38, 0x07, 0xe3, 0x79, 0x0b, 0x1f, 0x8c, 0xd5, 0xcf,
+       0xc7, 0xa8, 0xf5, 0x05, 0x31, 0xfa, 0x46, 0x9b, 0xb9, 0x22, 0xc5, 0x68,
+       0xe3, 0x0e, 0x8c, 0xa2, 0x06, 0x2a, 0xe5, 0xf8, 0xe4, 0x78, 0xc9, 0xf1,
+       0x99, 0x3f, 0xf3, 0xfd, 0x08, 0x38, 0x38, 0xe3, 0xb6, 0x18, 0xdc, 0x16,
+       0xa9, 0x1c, 0xe7, 0x96, 0x23, 0x4a, 0xe3, 0x78, 0x19, 0x71, 0x1c, 0x19,
+       0x9c, 0xf3, 0x38, 0x86, 0x59, 0x8e, 0xe3, 0x98, 0xe5, 0x46, 0x32, 0x39,
+       0xb4, 0x88, 0xe7, 0x28, 0x8b, 0xe7, 0x16, 0x78, 0x37, 0xca, 0xe2, 0xb9,
+       0x85, 0x18, 0x5e, 0xc9, 0xe2, 0xb9, 0x95, 0xc5, 0x33, 0xdf, 0xdb, 0x19,
+       0x55, 0x95, 0x8b, 0x9d, 0x3a, 0x78, 0x6d, 0x45, 0xe9, 0x6c, 0x62, 0x9d,
+       0xb0, 0xb1, 0x93, 0xc7, 0xc5, 0x1d, 0xf7, 0x5b, 0x58, 0xcf, 0xad, 0xbc,
+       0x32, 0x8b, 0xbc, 0x72, 0x0e, 0x79, 0xa5, 0xdb, 0x77, 0xbf, 0x75, 0x56,
+       0xe5, 0x95, 0x27, 0x8b, 0x79, 0x5e, 0xe9, 0x66, 0x79, 0xa5, 0xab, 0xf2,
+       0xca, 0x13, 0x45, 0xce, 0x2b, 0x31, 0x05, 0xc5, 0xfe, 0xbc, 0x12, 0x6f,
+       0xcb, 0x2b, 0xb9, 0x2c, 0xf7, 0xef, 0x94, 0x57, 0x72, 0x9f, 0x71, 0x6e,
+       0xb1, 0x72, 0x5e, 0xbd, 0x2d, 0x9f, 0xe4, 0x63, 0xd8, 0x56, 0xe6, 0x25,
+       0xe6, 0xe0, 0xb4, 0xae, 0xbf, 0x92, 0xe4, 0xb1, 0x74, 0x0c, 0xf3, 0xe0,
+       0xbd, 0xb3, 0x53, 0x2c, 0xd9, 0x59, 0x2c, 0x0d, 0xa7, 0x32, 0x9d, 0xfe,
+       0x78, 0x3a, 0x56, 0xdc, 0x1e, 0x4f, 0xb9, 0x9e, 0x3c, 0x9e, 0x52, 0x9d,
+       0x1f, 0x1a, 0x65, 0xae, 0x07, 0x70, 0x96, 0x76, 0xfd, 0x39, 0xf4, 0x5e,
+       0xe8, 0x4d, 0xa3, 0xae, 0x36, 0xe9, 0x6a, 0xce, 0x37, 0xea, 0xbe, 0x07,
+       0x6d, 0x2f, 0xb7, 0xb5, 0xb8, 0xf5, 0xad, 0x8b, 0xda, 0xfa, 0x7d, 0xf0,
+       0xc8, 0x79, 0xf5, 0xfd, 0x33, 0x79, 0xb5, 0x84, 0x33, 0xb0, 0x97, 0x8f,
+       0x7b, 0x1d, 0xf3, 0xb9, 0xe2, 0x2c, 0x9e, 0x5e, 0xee, 0xdd, 0x82, 0xf9,
+       0x8a, 0xc7, 0x7d, 0xff, 0x44, 0x0e, 0x41, 0x5d, 0xbe, 0x35, 0x96, 0xcf,
+       0x38, 0x1e, 0xd6, 0xec, 0xd0, 0xa5, 0x6d, 0xe7, 0x9c, 0xf4, 0x7c, 0x83,
+       0x75, 0xa3, 0x3e, 0xe1, 0x3a, 0x25, 0xfc, 0x8a, 0x4e, 0x2f, 0xd1, 0xb7,
+       0x7c, 0xee, 0xd3, 0x69, 0xf6, 0x31, 0x29, 0x5f, 0x40, 0xcd, 0xf2, 0xf4,
+       0xb6, 0x9a, 0xa5, 0x48, 0xe3, 0x07, 0xfa, 0xcf, 0x87, 0x37, 0xe5, 0xf8,
+       0xa4, 0x7b, 0x36, 0xa0, 0x40, 0x9b, 0x5d, 0xe7, 0x5a, 0x76, 0xab, 0x76,
+       0x25, 0x1a, 0xbd, 0x21, 0xf5, 0x49, 0xce, 0x85, 0x57, 0x33, 0x5f, 0xe1,
+       0xdb, 0x99, 0x1b, 0xe0, 0xd6, 0x48, 0xdd, 0xf1, 0x06, 0xeb, 0x3c, 0x0f,
+       0xbf, 0xa3, 0x4d, 0xb8, 0xbe, 0xb9, 0xdb, 0xbd, 0xab, 0x89, 0x7d, 0x71,
+       0x9d, 0xa3, 0x06, 0xa9, 0xbb, 0x8b, 0x25, 0xdf, 0xfd, 0x59, 0x8b, 0x52,
+       0x9e, 0x88, 0xfc, 0x05, 0xd8, 0x02, 0x9c, 0x8b, 0x45, 0xec, 0xcd, 0x24,
+       0x78, 0xc9, 0x75, 0x0e, 0xe8, 0x42, 0x61, 0x7f, 0x19, 0xba, 0x8d, 0x03,
+       0x5c, 0x3f, 0x7e, 0x2a, 0x97, 0x7b, 0x2a, 0x07, 0xfb, 0x8c, 0x91, 0x7a,
+       0xb2, 0x5b, 0xe7, 0x36, 0x48, 0xf8, 0xb9, 0x80, 0x79, 0x9c, 0xbb, 0xe0,
+       0xa7, 0x24, 0xa2, 0x33, 0x8e, 0x98, 0xed, 0x38, 0x62, 0xae, 0xa3, 0x03,
+       0xdd, 0xb6, 0x4d, 0xbb, 0xb0, 0x27, 0xc8, 0xc1, 0xf4, 0x00, 0x6c, 0xb9,
+       0xe0, 0x88, 0x3a, 0x6a, 0xc1, 0x1f, 0x18, 0xae, 0x78, 0x9a, 0x3e, 0xc1,
+       0x1a, 0x6f, 0xc8, 0xf4, 0xde, 0xc5, 0x11, 0xd1, 0xd6, 0xdc, 0x37, 0x30,
+       0x37, 0xdb, 0xc4, 0x31, 0xca, 0xf9, 0x72, 0x5e, 0x5b, 0x80, 0x8f, 0x8e,
+       0xac, 0x6b, 0xe0, 0x35, 0xce, 0x97, 0x23, 0xd9, 0xfd, 0x12, 0xf6, 0x07,
+       0xeb, 0xbf, 0x74, 0x47, 0xad, 0x99, 0xd7, 0x94, 0xe9, 0xdd, 0x69, 0x3c,
+       0xc3, 0xf3, 0x13, 0x6c, 0x99, 0x98, 0xba, 0xa0, 0xce, 0x3d, 0xd3, 0xa8,
+       0xf1, 0xb8, 0x95, 0xa8, 0x83, 0xf8, 0xae, 0x8b, 0x6b, 0x27, 0x89, 0xf8,
+       0x4f, 0x9f, 0x63, 0x3e, 0x13, 0xcd, 0xb0, 0x0e, 0x3e, 0x1b, 0x71, 0xfc,
+       0xfc, 0x1b, 0x2f, 0xf3, 0x0a, 0xbd, 0x68, 0x18, 0x00, 0x00, 0x00 };
+
+static const u32 bnx2_TPAT_b09FwData[(0x0/4) + 1] = { 0x0 };
+static const u32 bnx2_TPAT_b09FwRodata[(0x0/4) + 1] = { 0x0 };
+static const u32 bnx2_TPAT_b09FwBss[(0x850/4) + 1] = { 0x0 };
+static const u32 bnx2_TPAT_b09FwSbss[(0x2c/4) + 1] = { 0x0 };
 
 static struct fw_info bnx2_tpat_fw_09 = {
-       .ver_major                      = 0x1,
-       .ver_minor                      = 0x0,
-       .ver_fix                        = 0x0,
+       .ver_major                      = 0x3,
+       .ver_minor                      = 0x4,
+       .ver_fix                        = 0x3,
 
        .start_addr                     = 0x08000860,
 
        .text_addr                      = 0x08000800,
-       .text_len                       = 0x1480,
+       .text_len                       = 0x1864,
        .text_index                     = 0x0,
        .gz_text                        = bnx2_TPAT_b09FwText,
        .gz_text_len                    = sizeof(bnx2_TPAT_b09FwText),
 
-       .data_addr                      = 0x08001ca0,
+       .data_addr                      = 0x08002080,
        .data_len                       = 0x0,
        .data_index                     = 0x0,
        .data                           = bnx2_TPAT_b09FwData,
 
-       .sbss_addr                      = 0x08001ca0,
-       .sbss_len                       = 0x34,
+       .sbss_addr                      = 0x08002088,
+       .sbss_len                       = 0x2c,
        .sbss_index                     = 0x0,
        .sbss                           = bnx2_TPAT_b09FwSbss,
 
-       .bss_addr                       = 0x08001ce0,
-       .bss_len                        = 0x250,
+       .bss_addr                       = 0x080020c0,
+       .bss_len                        = 0x850,
        .bss_index                      = 0x0,
        .bss                            = bnx2_TPAT_b09FwBss,
 
@@ -3308,732 +3279,769 @@ static struct fw_info bnx2_tpat_fw_09 = {
 };
 
 static u8 bnx2_TXP_b09FwText[] = {
-       0x1f, 0x8b, 0x08, 0x08, 0x51, 0xfe, 0x2f, 0x45, 0x00, 0x03, 0x74, 0x65,
-       0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xcd, 0x7b, 0x7f, 0x70,
-       0x1b, 0xe7, 0x99, 0xde, 0xbb, 0x0b, 0x80, 0x04, 0x29, 0x8a, 0x5a, 0x31,
-       0x30, 0x83, 0x38, 0xb4, 0x8d, 0x15, 0x17, 0x34, 0x6d, 0xf2, 0x1c, 0x58,
-       0xe5, 0xf9, 0xd8, 0x06, 0xb5, 0xd7, 0xc0, 0x92, 0xa2, 0x63, 0x26, 0x47,
-       0xbb, 0xcc, 0x9d, 0x92, 0x51, 0x7d, 0x28, 0x48, 0x29, 0x6e, 0xe3, 0xb4,
-       0xaa, 0xe3, 0x3f, 0x34, 0x4d, 0x5b, 0xc3, 0x00, 0x25, 0xcb, 0x2e, 0x44,
-       0xd0, 0x16, 0x63, 0xa5, 0x33, 0x37, 0x53, 0x18, 0x80, 0x28, 0xe7, 0xba,
-       0x24, 0xdc, 0xe4, 0x2e, 0xe9, 0x1f, 0xc9, 0x99, 0xa5, 0x6c, 0xc5, 0x6d,
-       0xae, 0x33, 0xbe, 0x3f, 0xda, 0xa6, 0x37, 0xd7, 0x19, 0x8d, 0xfc, 0x23,
-       0xce, 0x8f, 0xb9, 0xb8, 0x69, 0x7a, 0x56, 0x5b, 0xd9, 0xe8, 0xf3, 0x7c,
-       0xbb, 0x4b, 0x82, 0x32, 0x15, 0x5b, 0xd7, 0x76, 0xa6, 0x9c, 0xc1, 0x10,
-       0xfb, 0xed, 0xb7, 0xdf, 0xf7, 0xfe, 0x7e, 0xdf, 0xe7, 0xfd, 0x16, 0x71,
-       0x91, 0x6e, 0xf1, 0xff, 0x76, 0xe3, 0x93, 0x38, 0x7a, 0xec, 0xb1, 0x3b,
-       0xc6, 0xef, 0xd8, 0x2f, 0x72, 0xe7, 0x9d, 0xb2, 0x2b, 0xaa, 0xf3, 0xe6,
-       0xdb, 0x21, 0x91, 0xdc, 0x4f, 0xe5, 0xaf, 0xfc, 0x87, 0xc7, 0x8d, 0x60,
-       0x7d, 0x7e, 0x24, 0xaa, 0xa7, 0x5f, 0xcc, 0x64, 0x2c, 0x89, 0x86, 0xd2,
-       0x33, 0x9f, 0x9d, 0xb3, 0x44, 0x6c, 0x77, 0x24, 0x91, 0x95, 0xf7, 0x5a,
-       0x85, 0x58, 0x58, 0x38, 0x7e, 0x53, 0xfa, 0xca, 0xe3, 0xdf, 0xff, 0x2d,
-       0xf3, 0x9d, 0x6a, 0x48, 0xa2, 0x46, 0x3a, 0x27, 0xc6, 0x90, 0x44, 0x07,
-       0xf0, 0xcc, 0xef, 0xdf, 0x3a, 0xa5, 0x4b, 0x6f, 0xb0, 0x56, 0x5c, 0x16,
-       0x2a, 0x6f, 0xb7, 0xbe, 0x7f, 0x6b, 0x4c, 0xfe, 0x55, 0xd3, 0x90, 0x17,
-       0x9b, 0x61, 0x6d, 0xb2, 0xd2, 0x23, 0xa5, 0x8a, 0x2b, 0xc7, 0xcb, 0x05,
-       0xc9, 0x36, 0x5f, 0x90, 0xe2, 0xb2, 0xd1, 0x9b, 0x39, 0xf7, 0x07, 0x52,
-       0x5a, 0xee, 0xeb, 0xcd, 0x9e, 0x73, 0xa5, 0x58, 0x8e, 0xf7, 0x66, 0x9a,
-       0x46, 0x6f, 0xf6, 0x4c, 0x0c, 0xd7, 0x7d, 0xbd, 0x99, 0x33, 0x66, 0x41,
-       0xa4, 0x1f, 0x73, 0xe2, 0xbd, 0xd9, 0x8a, 0x99, 0x13, 0x19, 0x4c, 0xbd,
-       0x22, 0x03, 0xbd, 0xd9, 0x66, 0x4d, 0x5b, 0x37, 0x34, 0x29, 0xfe, 0x86,
-       0x18, 0xbd, 0xe9, 0xcb, 0xad, 0x4f, 0x58, 0x86, 0xec, 0xb5, 0x64, 0xcf,
-       0x1e, 0x4b, 0x9e, 0x88, 0xa7, 0xa3, 0x92, 0x3f, 0xdd, 0x25, 0xb6, 0xe2,
-       0xc9, 0x90, 0xfc, 0x99, 0x11, 0x63, 0x43, 0x22, 0x62, 0xc7, 0x82, 0xeb,
-       0x56, 0x2b, 0x93, 0xfa, 0x02, 0xe5, 0x8a, 0xbd, 0xa4, 0x77, 0xb2, 0x29,
-       0x92, 0xa9, 0x44, 0x25, 0x93, 0x7a, 0xaf, 0xe5, 0x3d, 0x13, 0xc5, 0xbe,
-       0xe1, 0xde, 0x89, 0x4a, 0xab, 0xe5, 0xa4, 0xb0, 0x47, 0x2a, 0x78, 0x36,
-       0x22, 0xd5, 0x98, 0x5d, 0x2d, 0xa5, 0x4c, 0xdd, 0xd3, 0x09, 0x79, 0xe4,
-       0xb5, 0x2d, 0xba, 0xf5, 0xdb, 0x92, 0x8f, 0x49, 0xb5, 0x98, 0xba, 0x4b,
-       0x9e, 0x4e, 0x19, 0x72, 0x12, 0xeb, 0x3d, 0x95, 0x82, 0x1c, 0xad, 0x63,
-       0x5a, 0xa6, 0x69, 0xc6, 0x45, 0x7b, 0x5a, 0x32, 0x67, 0x06, 0x8d, 0xac,
-       0x60, 0x6f, 0xab, 0x75, 0x4b, 0x26, 0x85, 0xfd, 0x46, 0xff, 0x67, 0xcb,
-       0x8e, 0x99, 0xb9, 0xaa, 0x0c, 0x48, 0xb1, 0x32, 0x98, 0xfa, 0x13, 0xd1,
-       0xa4, 0xd3, 0xa2, 0x7c, 0x5a, 0x72, 0x3f, 0xf6, 0xcd, 0x58, 0x18, 0x6f,
-       0x8a, 0xad, 0x27, 0x23, 0xf2, 0x0f, 0x0c, 0x33, 0x91, 0x09, 0xf5, 0x4b,
-       0xf1, 0x74, 0x27, 0xe8, 0xb4, 0xfb, 0x74, 0xcc, 0x3d, 0x30, 0x26, 0xb1,
-       0x5d, 0x22, 0x5a, 0x28, 0x9d, 0xc4, 0xba, 0x22, 0x45, 0x77, 0x00, 0xcf,
-       0x26, 0xc7, 0x7f, 0x2a, 0x7b, 0x24, 0xb1, 0x37, 0x2c, 0x25, 0xb7, 0x1b,
-       0x72, 0x34, 0xa0, 0x83, 0xe4, 0xf8, 0x5f, 0x40, 0x29, 0xba, 0x95, 0x8c,
-       0x1f, 0x93, 0x9c, 0x96, 0x6d, 0x76, 0x48, 0x29, 0x19, 0x95, 0x05, 0xd0,
-       0xb1, 0x90, 0xfa, 0xa2, 0x96, 0x39, 0x77, 0x50, 0xcb, 0x9e, 0xc3, 0xbc,
-       0x66, 0xdd, 0xb7, 0x35, 0x03, 0xeb, 0xe8, 0x52, 0x4c, 0x1e, 0xc4, 0xbd,
-       0xa8, 0xcc, 0x61, 0xde, 0x1c, 0x78, 0x2a, 0x35, 0xf7, 0xc8, 0xfa, 0x6c,
-       0xac, 0x37, 0x03, 0x1d, 0x16, 0x71, 0xff, 0xb7, 0x67, 0x34, 0x31, 0x2c,
-       0x5b, 0x7e, 0x3c, 0x06, 0x1d, 0x9e, 0x81, 0xfe, 0xce, 0xc4, 0xe5, 0x78,
-       0x45, 0x62, 0xba, 0x24, 0xe3, 0x79, 0x79, 0x41, 0xea, 0x2e, 0xf5, 0x0f,
-       0x7d, 0x42, 0xdf, 0x45, 0x97, 0xcf, 0x41, 0x6f, 0x15, 0x07, 0xf2, 0x98,
-       0x02, 0x0d, 0x0f, 0x6a, 0xf7, 0xd7, 0x67, 0xb5, 0x03, 0xcd, 0x1f, 0x6b,
-       0xd2, 0x7d, 0x4c, 0xfb, 0x5c, 0xf3, 0x88, 0xe6, 0xcb, 0x1e, 0xba, 0x8b,
-       0x8a, 0x3d, 0x13, 0x95, 0x95, 0xa6, 0xa7, 0xbb, 0x1a, 0xec, 0xd3, 0x36,
-       0x6c, 0xe8, 0xe1, 0x6f, 0x6f, 0xce, 0x59, 0x69, 0xc6, 0x64, 0x01, 0xb4,
-       0x1d, 0x6f, 0x72, 0xfe, 0xef, 0x41, 0x3f, 0x51, 0x71, 0x6f, 0xed, 0x91,
-       0x1c, 0xc6, 0x8b, 0x67, 0xc4, 0xce, 0xa4, 0x74, 0x3c, 0xd3, 0x2b, 0x21,
-       0xab, 0x1f, 0x9f, 0x6e, 0x99, 0xab, 0x77, 0xda, 0x21, 0x2b, 0x26, 0x73,
-       0x4d, 0xca, 0x10, 0xff, 0x2b, 0x81, 0x1c, 0x49, 0x2b, 0xc7, 0xf9, 0x1c,
-       0xc7, 0x0d, 0x8c, 0xb7, 0x8f, 0xd1, 0x2e, 0x7a, 0x41, 0x8f, 0x39, 0x2c,
-       0x18, 0xcb, 0x57, 0x92, 0xc6, 0xe7, 0xf8, 0xbf, 0x49, 0xd9, 0x06, 0x32,
-       0x0d, 0x63, 0xae, 0x2e, 0xf9, 0x3a, 0xf6, 0x39, 0x7d, 0xa5, 0x15, 0x19,
-       0xc3, 0xb5, 0xf5, 0x4b, 0xc8, 0x92, 0xfb, 0x86, 0x41, 0x93, 0x2e, 0xb9,
-       0x3a, 0xd7, 0xe2, 0x7d, 0x81, 0xee, 0x8b, 0x7b, 0x75, 0x19, 0x86, 0x7e,
-       0x4d, 0xec, 0xd3, 0x85, 0x39, 0x3d, 0x90, 0x1f, 0x78, 0x3d, 0x87, 0xef,
-       0xe0, 0x5d, 0xb7, 0x74, 0x3c, 0xdf, 0x29, 0x73, 0x29, 0xda, 0x0b, 0xe9,
-       0xdc, 0x85, 0xb5, 0xbb, 0x64, 0xfe, 0x34, 0xe5, 0x01, 0xbb, 0xaa, 0xc4,
-       0xa4, 0x74, 0xc6, 0x34, 0x1c, 0x31, 0x21, 0x1b, 0x1b, 0xf3, 0x3a, 0x25,
-       0x67, 0xb4, 0x5a, 0x13, 0xa9, 0x11, 0xe3, 0x9b, 0xca, 0xce, 0x47, 0x8c,
-       0xa4, 0x26, 0x85, 0x8e, 0xf4, 0x10, 0x64, 0x6b, 0x1e, 0x14, 0xe1, 0xf5,
-       0x0f, 0xc4, 0x9e, 0xa5, 0xff, 0xc4, 0xb8, 0x17, 0xfc, 0xa9, 0x1f, 0xf4,
-       0xd3, 0xe7, 0x06, 0xa0, 0x97, 0xb8, 0xf2, 0x83, 0x89, 0x1d, 0xfd, 0xc0,
-       0x9c, 0xaa, 0x82, 0xdf, 0xe2, 0xb9, 0x30, 0xfd, 0x2f, 0x05, 0x73, 0x93,
-       0x5d, 0x56, 0x14, 0xb6, 0x40, 0x5a, 0xc6, 0xb1, 0x7e, 0xab, 0xf5, 0xd9,
-       0x94, 0x47, 0x53, 0xf1, 0x8c, 0x8d, 0x67, 0xc3, 0x90, 0xbb, 0xf9, 0x70,
-       0x42, 0xed, 0x3f, 0xee, 0xef, 0x6f, 0xc8, 0x1c, 0xe8, 0x2e, 0x56, 0x42,
-       0x92, 0x35, 0xb8, 0xc6, 0x9f, 0x71, 0x3c, 0xe7, 0xad, 0x05, 0xbb, 0x3d,
-       0x35, 0x68, 0xdc, 0x07, 0x5f, 0xa2, 0x8f, 0x15, 0x57, 0x29, 0x63, 0xac,
-       0x33, 0x46, 0x19, 0x1b, 0x8a, 0xc6, 0xcc, 0x19, 0xda, 0x91, 0x0c, 0x84,
-       0x84, 0x76, 0x8e, 0x98, 0x01, 0xbb, 0x2a, 0xf9, 0x76, 0x95, 0x77, 0xa9,
-       0xff, 0xbb, 0x7d, 0xff, 0xd4, 0x65, 0x28, 0x49, 0x7b, 0x7f, 0x5a, 0xb2,
-       0xf0, 0xf1, 0x39, 0xec, 0x54, 0x07, 0x4f, 0xb5, 0xca, 0x20, 0x64, 0x15,
-       0xf8, 0x1d, 0xf4, 0x3b, 0xfa, 0x6e, 0x2b, 0x88, 0x05, 0xc5, 0x0a, 0x7d,
-       0xa6, 0x68, 0xe8, 0x52, 0xc0, 0x07, 0x76, 0x63, 0x99, 0xc3, 0x99, 0x90,
-       0x39, 0x93, 0x03, 0x6d, 0xb0, 0x7b, 0xc9, 0xdc, 0x49, 0x7b, 0xc6, 0x9c,
-       0xa6, 0xec, 0x0f, 0xfc, 0xac, 0xe6, 0x52, 0x4f, 0xdd, 0xd8, 0x37, 0xa0,
-       0x29, 0x8c, 0x31, 0xae, 0x13, 0x85, 0xcd, 0x07, 0x36, 0x43, 0xfb, 0x33,
-       0xed, 0x75, 0xe9, 0x90, 0xe1, 0x24, 0x62, 0xd9, 0x19, 0x1d, 0xfa, 0x1b,
-       0x40, 0x4c, 0x09, 0xcb, 0x11, 0xc8, 0xea, 0x4b, 0x15, 0xd2, 0xe7, 0xc0,
-       0xef, 0x10, 0xdb, 0xce, 0x4c, 0xc2, 0xcf, 0xa6, 0xb4, 0x09, 0xf8, 0xc4,
-       0x67, 0xea, 0xa4, 0xa9, 0x25, 0xf4, 0x4b, 0xe7, 0x5c, 0x4e, 0x9b, 0x6c,
-       0x1e, 0xd4, 0xa6, 0xce, 0xd1, 0x4f, 0xe8, 0x23, 0xa6, 0xf1, 0x80, 0x78,
-       0x3c, 0x14, 0x9b, 0xaf, 0x68, 0xf4, 0xd5, 0xe2, 0xa9, 0x2e, 0xd0, 0xb1,
-       0x0b, 0xf4, 0x18, 0xf0, 0x3d, 0xd8, 0x97, 0x65, 0xce, 0xd0, 0x66, 0x9c,
-       0xa4, 0x95, 0xf8, 0xe7, 0xf2, 0x41, 0x39, 0x4c, 0x6c, 0xca, 0x61, 0x04,
-       0x32, 0xd9, 0x2e, 0x87, 0x85, 0x0f, 0xca, 0xc1, 0x2e, 0x40, 0x0e, 0x0b,
-       0x88, 0x43, 0x0b, 0x4d, 0xf2, 0xdc, 0x12, 0xfd, 0x4e, 0x81, 0x75, 0xca,
-       0xbd, 0x7a, 0x9a, 0x36, 0x4a, 0x3f, 0x49, 0x26, 0x4a, 0x58, 0xa1, 0xe1,
-       0xf6, 0x28, 0xdf, 0x98, 0x54, 0xb2, 0xf8, 0x30, 0x7e, 0xc9, 0xdf, 0x16,
-       0xcf, 0x53, 0x75, 0xc6, 0x1b, 0xd8, 0x79, 0xd2, 0x32, 0xbe, 0x20, 0x5b,
-       0x7c, 0xdf, 0xb7, 0xc5, 0x37, 0xf6, 0x09, 0x62, 0x10, 0x79, 0x0e, 0xe2,
-       0x31, 0x6d, 0xe5, 0xa5, 0x56, 0xc8, 0xb2, 0xa0, 0x03, 0xda, 0x0b, 0x69,
-       0x30, 0x8d, 0xcf, 0x0a, 0xfe, 0x23, 0x2e, 0xd0, 0x97, 0x72, 0x6a, 0x5e,
-       0x87, 0xe4, 0xf6, 0x7a, 0xf3, 0xe7, 0x2a, 0xad, 0x5f, 0xe8, 0xe9, 0xf7,
-       0x5b, 0x99, 0x31, 0xcb, 0xf7, 0xf1, 0xa8, 0x7c, 0xb9, 0x6e, 0xe6, 0x12,
-       0x5a, 0x8f, 0x14, 0x6e, 0x40, 0x5c, 0xa9, 0xd0, 0x3f, 0xfa, 0xaf, 0x11,
-       0xcb, 0x06, 0xfc, 0x58, 0xf6, 0x13, 0xc8, 0x9e, 0xb9, 0xe7, 0xf0, 0xfb,
-       0xeb, 0x31, 0xfe, 0x4f, 0x1a, 0x33, 0xf2, 0x05, 0xe6, 0x9b, 0x3d, 0xba,
-       0x8a, 0xdf, 0x16, 0x73, 0x41, 0x21, 0x9c, 0xee, 0x96, 0xc2, 0x5e, 0x29,
-       0x84, 0xd2, 0xf4, 0x23, 0xfa, 0x46, 0x87, 0x4f, 0x77, 0x90, 0x3b, 0xf8,
-       0x77, 0x4c, 0x17, 0x8b, 0x73, 0x90, 0x27, 0x2a, 0xe4, 0xe3, 0xbd, 0x40,
-       0x27, 0x78, 0x46, 0x22, 0x9e, 0xcd, 0x4d, 0x23, 0x66, 0x52, 0xa6, 0xed,
-       0xf6, 0xc2, 0x58, 0x2a, 0x09, 0xdd, 0x62, 0x2c, 0x15, 0x23, 0x94, 0x7e,
-       0x50, 0xb3, 0xeb, 0x5f, 0xd4, 0x6c, 0xc8, 0xce, 0x86, 0xec, 0x6c, 0xc8,
-       0x2e, 0x03, 0xd9, 0x65, 0x9b, 0xa4, 0x87, 0xb4, 0x78, 0xeb, 0x3b, 0xde,
-       0xfa, 0xa0, 0xb3, 0x5f, 0xf2, 0xca, 0xc7, 0xc9, 0x2f, 0x62, 0xb2, 0x8a,
-       0x07, 0x93, 0x9a, 0x17, 0x0f, 0xb8, 0xde, 0x14, 0x9e, 0xbf, 0x1b, 0x79,
-       0xce, 0xd6, 0x75, 0x6b, 0x4b, 0x26, 0x0b, 0x6d, 0x32, 0x29, 0xb9, 0x94,
-       0x11, 0xe7, 0xd3, 0x97, 0x5d, 0xe8, 0x3d, 0x90, 0xcb, 0x34, 0x68, 0xe8,
-       0x24, 0xef, 0x3e, 0x1f, 0x5c, 0xbf, 0xcf, 0x5f, 0xff, 0xd3, 0x58, 0x93,
-       0xbe, 0xbb, 0xd3, 0xbe, 0xdc, 0x93, 0xb9, 0xf4, 0xd7, 0xf1, 0x83, 0x5a,
-       0x02, 0x31, 0xfa, 0x45, 0xf8, 0xda, 0xc5, 0x50, 0x5c, 0xbe, 0x7f, 0xeb,
-       0x6b, 0xa8, 0x2f, 0xa4, 0x70, 0x63, 0xba, 0x95, 0x08, 0xa7, 0xdf, 0x6b,
-       0x2d, 0x8c, 0x21, 0x7e, 0xa6, 0xcd, 0x78, 0x26, 0x34, 0x2a, 0x2f, 0x35,
-       0x87, 0xe5, 0x3b, 0x4d, 0x4b, 0xfe, 0xa8, 0x99, 0x90, 0x3f, 0x6c, 0x0e,
-       0xc8, 0xb7, 0x9b, 0x71, 0xf9, 0x56, 0x33, 0xa8, 0x45, 0xe2, 0xb4, 0xa5,
-       0x5e, 0xa7, 0xb9, 0x53, 0x3d, 0x04, 0x3b, 0xc7, 0x5a, 0x99, 0xb1, 0x70,
-       0x2e, 0x94, 0x56, 0x35, 0xc2, 0xcc, 0xd1, 0xf2, 0xe3, 0x2d, 0xdd, 0xb2,
-       0x0a, 0xba, 0xde, 0x33, 0x6e, 0xdc, 0x25, 0x39, 0x3d, 0x8d, 0x31, 0x77,
-       0x3c, 0xec, 0x94, 0xbb, 0x90, 0x5f, 0xa2, 0xa8, 0x65, 0x06, 0xa4, 0x80,
-       0x75, 0x0b, 0xcd, 0x56, 0x6b, 0x29, 0xf5, 0x0f, 0x3f, 0x65, 0xfc, 0x8d,
-       0x7f, 0xd9, 0x29, 0xbd, 0xdf, 0x5e, 0x37, 0x86, 0xfe, 0xbb, 0x5f, 0x0f,
-       0xa1, 0xc6, 0xea, 0x57, 0x8b, 0xe7, 0xb4, 0xf4, 0xa8, 0x93, 0x70, 0x37,
-       0x70, 0x5f, 0xa2, 0xfd, 0xd6, 0xcf, 0x51, 0x85, 0xc8, 0xee, 0x98, 0xc5,
-       0x9a, 0x6b, 0x26, 0xfb, 0x79, 0xfc, 0xff, 0x58, 0x5a, 0xf6, 0xf4, 0xe1,
-       0xff, 0xde, 0x34, 0x4c, 0x2a, 0xcd, 0x98, 0xac, 0xb5, 0xc5, 0x64, 0xd1,
-       0x1c, 0xe4, 0xdf, 0x05, 0xf0, 0xe4, 0x40, 0x1e, 0xbf, 0xd3, 0x8c, 0x6a,
-       0xd9, 0xd3, 0xfd, 0x52, 0xaa, 0x33, 0xaf, 0x71, 0x5e, 0xd4, 0xaf, 0x7b,
-       0x78, 0xdd, 0x81, 0x6b, 0x41, 0xae, 0xf9, 0x94, 0x48, 0xaf, 0xf9, 0xa3,
-       0xcf, 0x4b, 0xdd, 0xaf, 0x5b, 0x22, 0xb2, 0xac, 0x6c, 0x8c, 0xe3, 0xaf,
-       0x65, 0xbf, 0x36, 0xb4, 0x35, 0xfe, 0xec, 0xe6, 0xf8, 0x3b, 0xd9, 0x4f,
-       0x6f, 0x8e, 0x77, 0x87, 0x3d, 0x1e, 0xc6, 0xb5, 0x99, 0x66, 0xc1, 0x1f,
-       0xbb, 0x0c, 0xb9, 0xb7, 0x5a, 0x0b, 0xc8, 0x3d, 0x45, 0xeb, 0x32, 0xea,
-       0x24, 0xc6, 0x9f, 0xeb, 0x89, 0x37, 0xdb, 0x62, 0x8d, 0x91, 0x09, 0x51,
-       0x9f, 0x51, 0xf1, 0xd6, 0xe4, 0xfd, 0x4e, 0xc4, 0x9d, 0xcb, 0xf8, 0xce,
-       0x3c, 0x17, 0xc4, 0x3c, 0xce, 0xe1, 0xf3, 0x6f, 0x5f, 0x43, 0xe7, 0x31,
-       0xe8, 0xfc, 0xff, 0x1b, 0xdd, 0xe2, 0x4f, 0xe9, 0x56, 0xc5, 0x9d, 0x97,
-       0xb6, 0xd9, 0x2c, 0xe9, 0xef, 0xf6, 0x69, 0x96, 0x68, 0x38, 0x6d, 0x38,
-       0x0b, 0xd6, 0x8d, 0x12, 0x41, 0x0d, 0x4b, 0x9b, 0x2d, 0x35, 0xbf, 0x8b,
-       0xe7, 0x99, 0x27, 0x25, 0x1a, 0x49, 0xd3, 0x2e, 0xd6, 0x07, 0x32, 0xd6,
-       0x31, 0xa7, 0xe6, 0x1e, 0x73, 0xce, 0x2a, 0x3b, 0x59, 0xbf, 0xc9, 0xab,
-       0xcd, 0x7f, 0x74, 0x13, 0x6a, 0x73, 0x3c, 0xcf, 0x98, 0xcb, 0xf1, 0x46,
-       0x4f, 0xc6, 0x62, 0x0e, 0x5a, 0x72, 0x8a, 0xf8, 0x2c, 0xa8, 0xb9, 0xaf,
-       0x0e, 0x70, 0x6e, 0x67, 0x3a, 0x76, 0xd3, 0x8f, 0xf1, 0xbf, 0x23, 0xfd,
-       0xce, 0x4d, 0x17, 0x2c, 0xae, 0x3b, 0x75, 0xd3, 0x59, 0xb5, 0x46, 0x18,
-       0xf1, 0x8c, 0xf3, 0x2e, 0xdf, 0xc4, 0x67, 0x9f, 0x44, 0x1c, 0x3f, 0xe1,
-       0x42, 0x97, 0xee, 0x8b, 0x4e, 0x1e, 0x9f, 0x39, 0xd2, 0x54, 0xe1, 0x7d,
-       0xe3, 0xe6, 0x8c, 0x15, 0x56, 0xf9, 0xf6, 0x4b, 0x98, 0x73, 0x04, 0x73,
-       0x0e, 0xbb, 0x01, 0x3f, 0xea, 0xbe, 0x93, 0xc5, 0xfd, 0xc3, 0x65, 0xc3,
-       0x71, 0xca, 0xe6, 0x38, 0x6a, 0x8e, 0xf8, 0x71, 0xe4, 0xe3, 0x1c, 0x72,
-       0xa0, 0x2d, 0xe6, 0x70, 0x41, 0xd2, 0x5d, 0x93, 0xa8, 0xe5, 0x56, 0x90,
-       0x4f, 0x50, 0x87, 0xa4, 0xaa, 0x32, 0xd8, 0x95, 0x39, 0xad, 0xc3, 0x3e,
-       0xef, 0x80, 0xbd, 0x1a, 0x8e, 0x9e, 0x44, 0x5c, 0x47, 0xdc, 0x5c, 0xa8,
-       0x58, 0x5a, 0xb6, 0x3c, 0x68, 0x94, 0xe4, 0x56, 0x59, 0x37, 0xcc, 0xf8,
-       0xa4, 0xec, 0x92, 0x6c, 0x18, 0xf3, 0x86, 0x3f, 0x2e, 0xb9, 0xb8, 0x86,
-       0xd8, 0x70, 0x03, 0xe2, 0x16, 0xeb, 0xe4, 0xf6, 0x18, 0xfa, 0x0b, 0x11,
-       0xeb, 0x8b, 0x21, 0xc6, 0x9e, 0x4e, 0x8b, 0x75, 0x3f, 0xe7, 0xed, 0x92,
-       0x8d, 0x0f, 0xcc, 0x7b, 0xb7, 0x6d, 0x5e, 0xfb, 0xf8, 0x7b, 0x18, 0xdf,
-       0x25, 0x17, 0x41, 0x47, 0x38, 0x39, 0x26, 0x25, 0xf0, 0x10, 0x39, 0xd5,
-       0x6a, 0x5d, 0x00, 0x3f, 0x3a, 0xf8, 0x2f, 0x56, 0x59, 0x0b, 0x84, 0xa4,
-       0x6a, 0xe0, 0x9e, 0xdb, 0x6a, 0xd5, 0x10, 0x46, 0xf5, 0x55, 0xd2, 0x1c,
-       0x95, 0x49, 0x77, 0x48, 0xec, 0x06, 0xe5, 0x60, 0xc2, 0xeb, 0xfe, 0xac,
-       0x2b, 0x7b, 0x86, 0x39, 0x13, 0x16, 0xb1, 0xfa, 0xe7, 0x5d, 0x19, 0xe4,
-       0x3e, 0x7d, 0xf5, 0x62, 0x57, 0x16, 0x7a, 0x0f, 0xad, 0xfe, 0xe7, 0x2e,
-       0xe7, 0x34, 0xe9, 0x0a, 0x21, 0xf7, 0xdd, 0x22, 0x45, 0xa3, 0x25, 0xdf,
-       0x44, 0x8d, 0x50, 0x1c, 0x46, 0x2e, 0x83, 0x17, 0xe8, 0xa0, 0xbb, 0x60,
-       0x48, 0xb4, 0x3b, 0xfd, 0x7d, 0xd0, 0x37, 0x06, 0xd9, 0xec, 0xc2, 0x9c,
-       0x10, 0xc6, 0x87, 0xf0, 0xbf, 0x7d, 0xfc, 0x8d, 0x2e, 0xe4, 0x05, 0xc4,
-       0x60, 0x89, 0x66, 0xc6, 0x7a, 0xb0, 0xfe, 0xf7, 0x30, 0x8e, 0x09, 0xc9,
-       0xcd, 0xf1, 0x27, 0xbc, 0xf1, 0xb7, 0x41, 0x0b, 0x9f, 0x63, 0x8d, 0x22,
-       0xd1, 0xb9, 0x31, 0x03, 0x34, 0x70, 0x6e, 0x4c, 0xcd, 0x75, 0xce, 0xd0,
-       0x06, 0x0c, 0xa7, 0x66, 0xdd, 0x2c, 0xd9, 0xe5, 0x7e, 0x99, 0x5c, 0xee,
-       0x93, 0x03, 0xcb, 0xe6, 0x4c, 0x95, 0xd8, 0x0f, 0x3c, 0x0b, 0xea, 0x30,
-       0x7d, 0x55, 0x20, 0x01, 0x33, 0x7e, 0x44, 0x06, 0xe3, 0x5f, 0x92, 0x5f,
-       0xb6, 0x90, 0xef, 0x91, 0xeb, 0x7b, 0x24, 0xac, 0xd6, 0x89, 0x07, 0x7b,
-       0xd2, 0x46, 0xb7, 0xed, 0xeb, 0x9c, 0xb9, 0xd6, 0xba, 0x70, 0xfe, 0xd5,
-       0xf8, 0x55, 0xeb, 0xfe, 0x85, 0xbf, 0xae, 0x81, 0x75, 0x07, 0xb0, 0x26,
-       0x79, 0x34, 0xbb, 0x26, 0x4e, 0x8b, 0xdd, 0x09, 0xfa, 0x9c, 0xe4, 0x8d,
-       0xc0, 0x86, 0xfd, 0x72, 0x62, 0x99, 0xf1, 0x42, 0xfa, 0xf1, 0x19, 0x8d,
-       0x48, 0x72, 0xf8, 0x1c, 0xea, 0xae, 0x09, 0xb5, 0x86, 0x57, 0x93, 0xe9,
-       0xab, 0x29, 0xd4, 0xc4, 0x3f, 0x05, 0x3d, 0xac, 0x15, 0xc8, 0x73, 0x18,
-       0xfc, 0xa6, 0x50, 0x8b, 0x11, 0x47, 0xb5, 0x1e, 0xcf, 0xa4, 0xf0, 0xfd,
-       0x5c, 0xa2, 0x2b, 0x8b, 0x98, 0x08, 0xff, 0xbe, 0x39, 0xa4, 0x72, 0x18,
-       0xf5, 0x32, 0xda, 0x45, 0x3c, 0x83, 0xe7, 0xa1, 0x27, 0xca, 0x68, 0xbc,
-       0xcb, 0xa9, 0x50, 0x46, 0x02, 0x7a, 0x2c, 0xd8, 0x64, 0x58, 0x61, 0x29,
-       0x7d, 0xd5, 0xc6, 0xbc, 0xb7, 0x42, 0xac, 0x77, 0x33, 0x16, 0xbf, 0x23,
-       0xe6, 0xac, 0x4e, 0x61, 0x2e, 0xbf, 0xdf, 0x85, 0x75, 0x07, 0x87, 0x8b,
-       0xd2, 0x31, 0x7c, 0x18, 0xf1, 0x4e, 0x1f, 0x1b, 0x01, 0x6d, 0xb4, 0xf3,
-       0x16, 0xb0, 0xc0, 0x6f, 0x81, 0x1f, 0xf8, 0x46, 0xd2, 0x92, 0xf9, 0x25,
-       0xca, 0x55, 0x3e, 0x0e, 0x1e, 0xc0, 0x7f, 0x12, 0x71, 0x8d, 0x3c, 0x70,
-       0x6f, 0x41, 0x8e, 0xbe, 0x5b, 0xf2, 0x4b, 0x51, 0x55, 0xeb, 0xdb, 0x06,
-       0xf7, 0xd7, 0x34, 0x3d, 0xdd, 0x0d, 0x1d, 0x93, 0xb7, 0x1c, 0x68, 0x7b,
-       0x0c, 0x79, 0x80, 0xbc, 0x91, 0x2f, 0xfa, 0xca, 0x28, 0xfc, 0x84, 0xf4,
-       0xfb, 0xb6, 0xa7, 0xad, 0x23, 0xa6, 0xa8, 0x38, 0x98, 0xca, 0x20, 0xb0,
-       0xbd, 0xd4, 0x1c, 0x97, 0x3f, 0x6e, 0x8e, 0xc9, 0x77, 0x9b, 0x29, 0xe4,
-       0xc0, 0x51, 0xe4, 0xc0, 0x61, 0xe4, 0x40, 0x0b, 0x39, 0x30, 0x81, 0x1c,
-       0x38, 0x80, 0x1c, 0x18, 0x47, 0x9c, 0x14, 0x39, 0xa1, 0xf2, 0x6d, 0x2c,
-       0x0a, 0xcc, 0x1d, 0xb5, 0x9b, 0x0e, 0x78, 0x99, 0xc1, 0x5e, 0xb3, 0xe0,
-       0xeb, 0x50, 0xd7, 0x44, 0x65, 0x1c, 0x31, 0xd7, 0x42, 0x3c, 0x4a, 0x20,
-       0xdf, 0x8c, 0x01, 0x6b, 0x89, 0x6c, 0x2c, 0x25, 0x10, 0x13, 0x5b, 0xe2,
-       0x00, 0x13, 0x97, 0x8c, 0x14, 0x9e, 0xdd, 0xab, 0xec, 0x33, 0x94, 0xbe,
-       0x3b, 0x2c, 0xdd, 0xa3, 0x92, 0x2f, 0x9f, 0xc4, 0x58, 0x1c, 0xeb, 0x75,
-       0x21, 0x2f, 0x31, 0x2e, 0x30, 0x06, 0x2c, 0x39, 0xbf, 0x6b, 0xd1, 0xd7,
-       0xba, 0xb5, 0xcc, 0xe9, 0x82, 0x30, 0x96, 0x23, 0x0f, 0xc0, 0x1e, 0x38,
-       0x36, 0x89, 0xe7, 0xf8, 0xfd, 0x2f, 0xfd, 0x98, 0xf9, 0xb1, 0x4e, 0x81,
-       0xd1, 0xbe, 0xc4, 0x9c, 0x67, 0x61, 0x3d, 0xb7, 0xdd, 0x4f, 0x9f, 0x47,
-       0xad, 0x14, 0xdc, 0x27, 0xae, 0x66, 0x3f, 0xe1, 0x24, 0x68, 0x1e, 0x04,
-       0xbe, 0x47, 0x6d, 0x75, 0xb0, 0x8a, 0xef, 0xed, 0xf3, 0x5d, 0xcc, 0x57,
-       0x63, 0x51, 0x23, 0x6d, 0xb1, 0x9e, 0x43, 0xac, 0x3c, 0x86, 0xb8, 0x68,
-       0x3b, 0xfa, 0x5a, 0x03, 0x7c, 0x42, 0x8e, 0x65, 0xdb, 0x09, 0x0f, 0xbd,
-       0xd6, 0x7a, 0xd6, 0x1a, 0x96, 0x89, 0xb5, 0x31, 0xc9, 0xae, 0x0d, 0xc6,
-       0xcf, 0x4b, 0xd7, 0x65, 0x5b, 0x5e, 0x6b, 0x95, 0x5c, 0xf3, 0xa4, 0x0d,
-       0xbb, 0xdc, 0xb7, 0xdf, 0x90, 0x1a, 0x30, 0xdc, 0xbe, 0xfd, 0x9d, 0xac,
-       0xe9, 0x5f, 0x14, 0x3d, 0x21, 0x99, 0x45, 0x5b, 0xc6, 0xf6, 0x07, 0xb5,
-       0xe7, 0x2f, 0x3b, 0xa4, 0x1b, 0x63, 0x6b, 0x09, 0xcc, 0x61, 0xdd, 0xaf,
-       0xfa, 0x27, 0xe0, 0x59, 0xf3, 0x9e, 0x51, 0x39, 0x8f, 0x98, 0x19, 0xbc,
-       0x37, 0x6d, 0xe7, 0xfc, 0x22, 0x70, 0x0d, 0xe4, 0x99, 0x59, 0x24, 0xee,
-       0xda, 0x05, 0x39, 0x45, 0x60, 0x23, 0xd4, 0xfd, 0x20, 0x9e, 0x6d, 0xc9,
-       0x57, 0x53, 0xb4, 0x87, 0xc7, 0x20, 0x4b, 0xac, 0x15, 0x0e, 0xf8, 0xf9,
-       0x9a, 0xcc, 0x2d, 0x51, 0x7e, 0x71, 0xd4, 0x96, 0xdc, 0x5b, 0xa2, 0x5d,
-       0xe9, 0xab, 0xeb, 0x46, 0xdb, 0xd9, 0x58, 0xc4, 0xfa, 0x43, 0xc4, 0xd8,
-       0x88, 0xd5, 0x65, 0xf6, 0x06, 0x58, 0x53, 0x1d, 0x80, 0x4e, 0xa6, 0x15,
-       0xe6, 0xce, 0xd4, 0x53, 0x62, 0x9d, 0x62, 0xac, 0x92, 0x44, 0xc8, 0x22,
-       0xbe, 0x17, 0x43, 0x4f, 0xcf, 0xe2, 0x1e, 0xe5, 0xc9, 0x5a, 0x1f, 0xf7,
-       0x57, 0xff, 0xa3, 0xd2, 0x49, 0x08, 0xba, 0xcb, 0xef, 0x67, 0x11, 0x22,
-       0x4b, 0xa1, 0x34, 0x62, 0xe0, 0x18, 0x79, 0x50, 0x7b, 0xa3, 0x9e, 0xa4,
-       0xdf, 0x81, 0x67, 0xd8, 0x46, 0x5b, 0x5d, 0xa9, 0xfe, 0x4a, 0x95, 0x08,
-       0x6c, 0x59, 0x0a, 0x91, 0x34, 0x78, 0x1a, 0xc3, 0x77, 0x38, 0xff, 0x09,
-       0xe8, 0xf3, 0x2c, 0x9e, 0x5f, 0x00, 0x5f, 0x1b, 0x65, 0xd2, 0x9d, 0x4c,
-       0x1c, 0x57, 0xbe, 0x8b, 0x6b, 0x97, 0xb5, 0xcc, 0xd7, 0xe4, 0xbc, 0xe2,
-       0xef, 0x13, 0xac, 0x9d, 0xa1, 0xa7, 0xeb, 0xe1, 0x6f, 0xf2, 0x3a, 0xf9,
-       0xf3, 0xd6, 0x67, 0xce, 0xca, 0x58, 0x09, 0xc9, 0x96, 0x5f, 0x6a, 0x85,
-       0x2d, 0x2b, 0x3e, 0xef, 0xeb, 0x31, 0xeb, 0x46, 0x41, 0x07, 0xfb, 0x00,
-       0xfb, 0x95, 0x2e, 0x41, 0x07, 0x6d, 0xa7, 0x10, 0x4d, 0x3f, 0x2e, 0x2b,
-       0x4b, 0xff, 0x54, 0x6a, 0x4b, 0x05, 0xa9, 0x2f, 0xfd, 0x23, 0x39, 0xb7,
-       0xd4, 0x92, 0x0b, 0x29, 0x15, 0x93, 0xac, 0x0e, 0xe5, 0xcf, 0x72, 0xa3,
-       0x87, 0x07, 0x93, 0xe3, 0x97, 0x20, 0xc0, 0x95, 0xaa, 0x47, 0xfb, 0x54,
-       0x1b, 0xed, 0x17, 0x60, 0x6b, 0xaf, 0x58, 0xa4, 0x7f, 0x4c, 0x6a, 0x65,
-       0xd2, 0xfe, 0xa0, 0xa2, 0xfd, 0xc0, 0x26, 0xed, 0x92, 0x0b, 0x59, 0xa4,
-       0x7f, 0x27, 0xda, 0x81, 0xf3, 0xfb, 0x49, 0x7f, 0x02, 0xcf, 0x7e, 0xd0,
-       0xfe, 0x6a, 0xee, 0x6b, 0xad, 0x8d, 0x72, 0x44, 0xd1, 0x1c, 0x4a, 0x8f,
-       0x41, 0x3e, 0xaf, 0xb5, 0xd6, 0x5d, 0xfa, 0x11, 0xbe, 0xbb, 0xf7, 0x20,
-       0x46, 0xf5, 0x61, 0xaf, 0x5e, 0xc9, 0xcf, 0x46, 0x11, 0x27, 0xc7, 0xa1,
-       0xdb, 0x2e, 0xe5, 0x87, 0x08, 0x17, 0xd0, 0xd9, 0x34, 0xe6, 0x1f, 0xa2,
-       0xbf, 0x29, 0xb9, 0x38, 0x90, 0x4b, 0xb1, 0x9c, 0x8e, 0xa0, 0xfe, 0xc7,
-       0x3e, 0x86, 0x93, 0x73, 0xf9, 0xcc, 0x00, 0x62, 0x1a, 0xff, 0x7f, 0x64,
-       0x7b, 0x28, 0x20, 0xd6, 0x42, 0xe7, 0x3d, 0x90, 0x1f, 0xe8, 0x18, 0x9b,
-       0x41, 0x6e, 0x4d, 0x0e, 0xd7, 0x54, 0x7f, 0x91, 0x71, 0xe5, 0x28, 0xf2,
-       0xe9, 0x21, 0x7c, 0xbc, 0xfd, 0x26, 0x9a, 0xdc, 0x73, 0x3b, 0x4f, 0x45,
-       0x77, 0x7d, 0x2f, 0x01, 0x52, 0xa6, 0xc9, 0x7d, 0x0b, 0x12, 0x4a, 0x87,
-       0xb0, 0x2f, 0xc7, 0x7a, 0x10, 0x63, 0x06, 0xa2, 0xd9, 0xe6, 0xcf, 0x31,
-       0x4e, 0x5f, 0x66, 0x7c, 0x0f, 0x68, 0x1f, 0xc5, 0x9a, 0x8c, 0xbb, 0x63,
-       0xe0, 0x99, 0x35, 0x26, 0xe3, 0x26, 0xf2, 0x48, 0xe3, 0x47, 0xcc, 0x2d,
-       0xf8, 0x3e, 0xe0, 0x7f, 0xe7, 0x7d, 0x89, 0xde, 0x9c, 0x36, 0xab, 0x05,
-       0x31, 0xb1, 0x27, 0x74, 0x6e, 0xc5, 0xa5, 0xd8, 0x30, 0x5f, 0x20, 0x66,
-       0xd4, 0x29, 0x83, 0x35, 0xca, 0x89, 0xfd, 0x27, 0xd4, 0x7f, 0xb5, 0xe7,
-       0x21, 0x8f, 0xa8, 0xec, 0xb5, 0x0e, 0x22, 0xa6, 0x80, 0xfe, 0xca, 0x18,
-       0x78, 0x63, 0x8f, 0x66, 0x10, 0xf9, 0x2b, 0x04, 0x21, 0xa0, 0x96, 0x5a,
-       0x0b, 0xc9, 0xbd, 0xe1, 0x11, 0xa3, 0x28, 0x8f, 0x46, 0x58, 0x36, 0x17,
-       0xd6, 0x98, 0x07, 0xc2, 0xb2, 0xb0, 0x26, 0x72, 0x69, 0x91, 0x71, 0x45,
-       0xfd, 0x41, 0xe6, 0x86, 0x33, 0x8f, 0x3c, 0x5b, 0x5a, 0x62, 0x8c, 0x61,
-       0x9c, 0xb8, 0x01, 0xba, 0x48, 0x7e, 0xe3, 0xab, 0xc8, 0x49, 0xa5, 0xf2,
-       0x20, 0x62, 0xa6, 0xac, 0xeb, 0x90, 0x29, 0x72, 0x19, 0x6b, 0xd4, 0x1d,
-       0xfa, 0x32, 0x41, 0x4f, 0x26, 0x2a, 0xc5, 0x45, 0xf6, 0x63, 0xa2, 0xa0,
-       0x85, 0x35, 0x76, 0x48, 0xd5, 0x3f, 0x37, 0xa8, 0xd8, 0xca, 0xff, 0xe1,
-       0xb6, 0x7d, 0x93, 0x27, 0xf7, 0xe9, 0x8c, 0x63, 0x37, 0x8b, 0x3d, 0x63,
-       0x77, 0x1d, 0xa8, 0x74, 0x48, 0xb5, 0x8f, 0x76, 0x49, 0xfd, 0xbf, 0xa0,
-       0x62, 0xed, 0x02, 0x78, 0x2a, 0x2e, 0x12, 0xe3, 0x86, 0x31, 0x2f, 0xe6,
-       0xcf, 0xa3, 0x5c, 0xff, 0x89, 0xcc, 0xed, 0x7f, 0x17, 0x74, 0x79, 0x71,
-       0x2d, 0xbf, 0x1f, 0xf1, 0x76, 0x46, 0x97, 0x3b, 0xef, 0x1a, 0xc7, 0xb3,
-       0xcc, 0x81, 0xef, 0xf8, 0x78, 0x92, 0x63, 0xec, 0x61, 0x81, 0xbe, 0x15,
-       0x03, 0xff, 0xfb, 0xa4, 0xb0, 0x12, 0x85, 0x1c, 0x90, 0x4b, 0x6b, 0xde,
-       0x5a, 0xac, 0x77, 0x4f, 0x42, 0x47, 0xfa, 0xa9, 0xa8, 0x44, 0x4e, 0xf5,
-       0x49, 0xf8, 0xeb, 0xdd, 0xd2, 0xf1, 0xf5, 0x21, 0x09, 0x7d, 0xdd, 0x64,
-       0x4e, 0x4f, 0x9c, 0x80, 0xbe, 0xe6, 0x65, 0x5c, 0x9e, 0x44, 0xde, 0x62,
-       0x5e, 0x57, 0x76, 0x6a, 0xf4, 0x4b, 0x08, 0x05, 0xab, 0xfe, 0x8c, 0x2d,
-       0x8f, 0xee, 0xff, 0x85, 0xea, 0x33, 0x01, 0xc3, 0x8b, 0xfe, 0xfc, 0x94,
-       0xd8, 0xcd, 0x77, 0x21, 0x6b, 0xc3, 0x79, 0xed, 0xd6, 0xa0, 0xa6, 0x1c,
-       0x56, 0xfd, 0xc2, 0x47, 0xf7, 0x7b, 0x35, 0x25, 0xf0, 0xb8, 0xe6, 0xa8,
-       0x9a, 0x12, 0xf1, 0x35, 0xcc, 0x79, 0xfd, 0xa2, 0x63, 0xaf, 0xbc, 0x0c,
-       0x42, 0x4f, 0xb7, 0x88, 0x7d, 0x08, 0x7e, 0xf1, 0x9c, 0x2c, 0xe9, 0x69,
-       0x4d, 0xad, 0x19, 0x7a, 0x86, 0x71, 0x8a, 0xf1, 0x8b, 0x36, 0x9e, 0x4c,
-       0x14, 0x61, 0x7f, 0xa1, 0xe7, 0x19, 0xa3, 0x3c, 0xdb, 0x9e, 0x68, 0x8b,
-       0x75, 0x0b, 0x95, 0x7b, 0xa0, 0x43, 0xd4, 0xf2, 0x16, 0xe2, 0x9c, 0x81,
-       0x5c, 0x6e, 0xf1, 0xda, 0xeb, 0xe1, 0xe5, 0x63, 0x31, 0x75, 0x5d, 0xac,
-       0x7a, 0x18, 0xdc, 0x5b, 0x9f, 0x75, 0x07, 0x62, 0x4c, 0x93, 0x74, 0x70,
-       0xdf, 0x01, 0x09, 0x3d, 0x17, 0x93, 0xf0, 0x73, 0xb4, 0x3f, 0x33, 0xe1,
-       0x40, 0x7e, 0x0b, 0x16, 0x31, 0xd0, 0x0a, 0xb0, 0xc5, 0xcd, 0xa2, 0xaf,
-       0x0c, 0xc0, 0x77, 0xcc, 0x78, 0x55, 0x92, 0x12, 0xaa, 0x45, 0xe5, 0xad,
-       0x45, 0x33, 0x41, 0x7b, 0x39, 0x6b, 0x61, 0xbc, 0xd9, 0x75, 0x79, 0x5d,
-       0x51, 0xc1, 0xb1, 0x2f, 0x87, 0x80, 0x19, 0x86, 0x6d, 0xbd, 0x47, 0x5e,
-       0x87, 0xbe, 0x73, 0x6a, 0xec, 0x66, 0xac, 0x0b, 0x1a, 0x9e, 0x33, 0xc1,
-       0x03, 0xd7, 0xfd, 0x1e, 0xd6, 0x54, 0xf8, 0xca, 0xd9, 0x60, 0x4d, 0xba,
-       0x48, 0xdb, 0xed, 0x83, 0xdd, 0xe1, 0xba, 0xd9, 0x21, 0xb9, 0xd9, 0x84,
-       0xe8, 0x8b, 0x9f, 0x91, 0xc1, 0xfd, 0xba, 0xc7, 0x8f, 0xe2, 0x91, 0x63,
-       0xec, 0xc7, 0xdd, 0xae, 0xfc, 0x51, 0x5f, 0x83, 0xcd, 0x3c, 0x48, 0x1d,
-       0x23, 0xf7, 0x23, 0x8f, 0x31, 0x8e, 0x85, 0x90, 0xc7, 0xb2, 0x4d, 0x4f,
-       0xef, 0xd5, 0x07, 0xfb, 0xe5, 0xc9, 0xe7, 0x68, 0x4f, 0xb8, 0xb7, 0x69,
-       0x53, 0x41, 0x0f, 0x98, 0xf7, 0x2c, 0x39, 0xf9, 0x6c, 0x50, 0x73, 0xb0,
-       0xbe, 0x32, 0xe3, 0x07, 0xc0, 0x8f, 0x7e, 0x27, 0xe3, 0x81, 0xae, 0x6c,
-       0x37, 0x6f, 0x59, 0x5e, 0xdd, 0x51, 0x49, 0xb0, 0x2f, 0x6e, 0xb0, 0x4e,
-       0xb3, 0xe3, 0x9e, 0xbc, 0x8b, 0x18, 0x2b, 0x35, 0x67, 0x11, 0xa3, 0x23,
-       0x72, 0x71, 0xd6, 0x86, 0xee, 0x3f, 0x0b, 0xba, 0x0e, 0x75, 0x11, 0x23,
-       0x5f, 0x9c, 0x75, 0x70, 0x7d, 0x48, 0xd5, 0x66, 0xa1, 0x3b, 0x61, 0xc7,
-       0xcd, 0x7e, 0xfa, 0x91, 0xaf, 0xa7, 0x84, 0x56, 0x5c, 0x32, 0xb5, 0x12,
-       0x62, 0xf6, 0x64, 0x8a, 0x39, 0xbe, 0x53, 0xf5, 0x4d, 0xd9, 0xaf, 0xc9,
-       0x2b, 0xbc, 0xb0, 0x4f, 0x2b, 0x56, 0x19, 0xe7, 0x0b, 0xf1, 0x0e, 0x21,
-       0x0e, 0x11, 0xad, 0x66, 0x51, 0x27, 0x9a, 0x9c, 0x57, 0xbd, 0x58, 0x11,
-       0xc7, 0x3d, 0x42, 0x19, 0x68, 0xf5, 0xea, 0x3e, 0xad, 0x50, 0x0d, 0xc9,
-       0xc5, 0x18, 0xe9, 0x4e, 0xa8, 0xfa, 0x7d, 0xbf, 0xb2, 0xb5, 0x1e, 0xe4,
-       0x12, 0xd8, 0x4c, 0xea, 0x93, 0xd8, 0x57, 0x8d, 0xc1, 0xa6, 0xa8, 0x7b,
-       0xea, 0x5d, 0xc5, 0x48, 0x5f, 0xf7, 0x3b, 0xe5, 0x4c, 0xd0, 0x51, 0x26,
-       0x7e, 0xef, 0xf4, 0xf1, 0xfb, 0xa2, 0x5f, 0x0f, 0x3d, 0x26, 0xac, 0x53,
-       0x16, 0x2a, 0xa4, 0x05, 0xf1, 0xd6, 0xdd, 0xc9, 0x96, 0x28, 0x47, 0x2f,
-       0xa6, 0x1c, 0x45, 0x1d, 0xa3, 0xaf, 0x19, 0xbe, 0x0d, 0xf0, 0x6f, 0x14,
-       0xf7, 0xbc, 0x5a, 0xaa, 0xd8, 0x8c, 0xc0, 0xdf, 0xa7, 0x21, 0x23, 0xea,
-       0x06, 0xfa, 0x5b, 0xe3, 0x99, 0x0a, 0xf4, 0xb7, 0xf6, 0xf2, 0xfb, 0x76,
-       0x1f, 0x63, 0xde, 0xb0, 0x3c, 0x89, 0xf1, 0x13, 0x67, 0x48, 0xcf, 0xb8,
-       0x8f, 0xc7, 0x12, 0x90, 0x09, 0x63, 0xfc, 0xa8, 0xbc, 0xd5, 0x70, 0x14,
-       0xfe, 0xdb, 0xb7, 0x7f, 0x46, 0xe6, 0xdd, 0x59, 0xe0, 0x3f, 0xc8, 0xdf,
-       0x48, 0xc0, 0x3f, 0xe3, 0x2a, 0x3e, 0x1e, 0xfe, 0x68, 0x35, 0x49, 0xd8,
-       0xcb, 0xd9, 0xf7, 0x5e, 0x67, 0xce, 0xde, 0x0d, 0xfc, 0xf5, 0x91, 0xd6,
-       0x0f, 0x79, 0xeb, 0xff, 0x17, 0xe8, 0xea, 0x73, 0xd8, 0x23, 0x0a, 0xfa,
-       0xfa, 0x29, 0xd3, 0x0f, 0x7b, 0x4e, 0xf7, 0x9e, 0xbb, 0xff, 0x3a, 0xe9,
-       0x32, 0xa4, 0x01, 0x8c, 0x50, 0x50, 0x79, 0x94, 0xb5, 0x62, 0xc4, 0xd7,
-       0xdf, 0x31, 0x60, 0x67, 0xae, 0x1b, 0xc4, 0xde, 0x4e, 0x29, 0xf4, 0x05,
-       0xf5, 0x27, 0x62, 0xf6, 0xe6, 0x78, 0x50, 0xcf, 0xf2, 0xf9, 0x94, 0x93,
-       0x2f, 0xb3, 0x4f, 0xc8, 0x5c, 0xc0, 0x31, 0x65, 0x87, 0x1f, 0x42, 0xb7,
-       0x09, 0xcf, 0x20, 0xdd, 0xf7, 0x29, 0xba, 0x1d, 0x45, 0x37, 0xfd, 0x8b,
-       0x67, 0x3a, 0xec, 0xa3, 0x05, 0x7d, 0x33, 0xae, 0x07, 0x4c, 0x00, 0x7d,
-       0x7f, 0x17, 0x3a, 0xfe, 0x4e, 0x05, 0x98, 0xa0, 0x02, 0x4c, 0x80, 0x3d,
-       0xbe, 0x0d, 0x1d, 0x7f, 0xab, 0x02, 0x4c, 0x50, 0x89, 0xfb, 0x3d, 0x0a,
-       0x9b, 0x98, 0xfe, 0x23, 0xda, 0x6e, 0xd0, 0x93, 0xb9, 0xda, 0x2e, 0x39,
-       0xce, 0xf9, 0x01, 0x36, 0x8e, 0xc2, 0x8e, 0x78, 0x6e, 0x11, 0xf4, 0x3b,
-       0xfc, 0x1c, 0xd1, 0xe0, 0xb9, 0x00, 0x72, 0x44, 0x83, 0xe7, 0x18, 0x23,
-       0xf1, 0x10, 0x30, 0x61, 0x48, 0xe2, 0xc2, 0x5e, 0xef, 0xdc, 0x18, 0xd6,
-       0x1a, 0x1d, 0x84, 0x27, 0x75, 0xa8, 0xbe, 0xd6, 0x71, 0xd5, 0x6f, 0x40,
-       0x5c, 0xa8, 0x06, 0xb5, 0x5b, 0x52, 0x26, 0x96, 0x88, 0x33, 0x65, 0xaf,
-       0x9e, 0x86, 0x0e, 0x5c, 0x62, 0xc3, 0xcd, 0xbe, 0xf4, 0x70, 0x1d, 0x7b,
-       0x16, 0x2d, 0x8f, 0xbe, 0xe3, 0xee, 0xd6, 0x33, 0x07, 0x10, 0x9f, 0xa7,
-       0xca, 0x09, 0x99, 0x2c, 0x7b, 0x98, 0x00, 0xf5, 0xcf, 0x55, 0xfd, 0x51,
-       0x9b, 0x7a, 0x80, 0xfe, 0x36, 0x6d, 0x23, 0x71, 0x3e, 0x45, 0x19, 0x53,
-       0xff, 0xd3, 0xaa, 0x67, 0x7d, 0xa0, 0xee, 0xf5, 0xe5, 0x27, 0x95, 0x2d,
-       0x84, 0x19, 0x67, 0xa8, 0x3f, 0xcf, 0x87, 0x61, 0x17, 0x79, 0x37, 0x90,
-       0x4b, 0x3b, 0x1e, 0xf9, 0xbc, 0x26, 0xd6, 0x4e, 0xe3, 0xb9, 0xb6, 0xf1,
-       0xcd, 0xfb, 0x3e, 0xbd, 0x88, 0x7d, 0x9b, 0x3d, 0x06, 0xc6, 0xa9, 0xad,
-       0xf1, 0x10, 0xea, 0x87, 0xb0, 0xba, 0x8f, 0x18, 0xde, 0x88, 0x49, 0xb6,
-       0x61, 0x89, 0x53, 0xe5, 0x3c, 0xf6, 0x2d, 0x18, 0x8f, 0x9e, 0x90, 0xec,
-       0x52, 0xaf, 0xe4, 0x62, 0x66, 0xca, 0x96, 0xbf, 0x27, 0x1b, 0xcb, 0x85,
-       0x04, 0xcf, 0x0d, 0x0b, 0x33, 0x1a, 0x9e, 0x7b, 0x18, 0xd7, 0xa4, 0xd9,
-       0x92, 0xc3, 0x65, 0xe6, 0x9d, 0x91, 0x78, 0x03, 0xf7, 0x72, 0xb3, 0xec,
-       0xd5, 0x54, 0x61, 0x93, 0x66, 0xa2, 0x8a, 0x78, 0xf0, 0x72, 0x99, 0xfb,
-       0x01, 0x1b, 0x95, 0xd9, 0xcf, 0x09, 0xee, 0x3f, 0x01, 0x1c, 0x88, 0x58,
-       0x1d, 0xf3, 0xe7, 0x28, 0x5e, 0x6d, 0x23, 0x2c, 0x81, 0xae, 0x3b, 0x65,
-       0xdd, 0x8f, 0xbb, 0xb5, 0xb2, 0xd7, 0x47, 0x39, 0x4b, 0x7a, 0xdc, 0xff,
-       0xd5, 0x5a, 0x8f, 0xa1, 0x16, 0xda, 0xe4, 0xf5, 0x8f, 0xb9, 0x8f, 0x81,
-       0xb0, 0x2b, 0x27, 0xdc, 0x40, 0x26, 0xbc, 0xcf, 0x31, 0x9e, 0x8d, 0xb6,
-       0x5a, 0x67, 0xad, 0xf6, 0x9e, 0xdf, 0xf5, 0xf4, 0xcc, 0xde, 0xb8, 0x2d,
-       0x63, 0xbd, 0xe6, 0xa0, 0x26, 0xf6, 0x7b, 0x66, 0x87, 0x46, 0xbc, 0x9e,
-       0xd9, 0xfc, 0xc8, 0xf6, 0x9e, 0xd9, 0xcf, 0x6f, 0xf3, 0x7a, 0x66, 0x17,
-       0x9d, 0x22, 0x3e, 0x5e, 0xcf, 0x6c, 0xf8, 0x76, 0xaf, 0x67, 0xf6, 0xf0,
-       0xed, 0x5e, 0xcf, 0xec, 0x91, 0x11, 0xaf, 0x67, 0xf6, 0xfb, 0xb7, 0x6f,
-       0xef, 0x99, 0x3d, 0x36, 0xb2, 0xbd, 0x67, 0x26, 0x13, 0xc8, 0x77, 0x13,
-       0x5b, 0x3d, 0xb3, 0xf2, 0xc8, 0xb5, 0x7b, 0x66, 0xaf, 0x06, 0x78, 0x1d,
-       0xfc, 0x8c, 0x81, 0x87, 0x14, 0xf0, 0xfa, 0x28, 0xf0, 0xfa, 0xaf, 0xeb,
-       0x59, 0x87, 0xc1, 0xe7, 0xcd, 0x7e, 0x5e, 0xb8, 0x1e, 0xdc, 0x7e, 0xbb,
-       0xff, 0x8c, 0xa0, 0xde, 0x4d, 0xf8, 0xb5, 0x0a, 0xb1, 0xfb, 0x1e, 0xbf,
-       0x66, 0xfb, 0x6b, 0xd1, 0xad, 0xf3, 0xec, 0xf6, 0xff, 0x37, 0xa0, 0xf4,
-       0x0e, 0xf0, 0x3c, 0xf9, 0x79, 0x0d, 0xb5, 0x1f, 0xf9, 0x47, 0xa2, 0xef,
-       0xbe, 0xe8, 0x7c, 0xd5, 0x22, 0xc6, 0x7f, 0x1c, 0xbe, 0x6a, 0xef, 0x0d,
-       0xc9, 0x3a, 0xfc, 0x96, 0x39, 0xea, 0xa4, 0x64, 0x31, 0x3f, 0xab, 0xe6,
-       0x27, 0x26, 0xb6, 0xe6, 0xa7, 0x26, 0xbe, 0xaa, 0x6a, 0x52, 0xf3, 0x5f,
-       0xe3, 0xf3, 0x0d, 0x65, 0xdf, 0x96, 0x87, 0xe1, 0x9d, 0x4a, 0x80, 0xb7,
-       0xc2, 0x3e, 0x76, 0x36, 0x1c, 0xdb, 0x9d, 0xc0, 0x33, 0xe6, 0x8b, 0xb6,
-       0x34, 0x14, 0x7e, 0x0f, 0xa5, 0xcd, 0x17, 0x73, 0xaa, 0x5e, 0x33, 0x9c,
-       0xbc, 0x1b, 0xd4, 0xdf, 0xa8, 0xa1, 0x86, 0x06, 0xd5, 0xf9, 0x9b, 0xbe,
-       0x36, 0x8c, 0x3c, 0xd6, 0x5e, 0x63, 0xb3, 0xae, 0xd6, 0xfd, 0xba, 0xda,
-       0x90, 0xbb, 0xf7, 0xb7, 0x63, 0x73, 0x99, 0xf8, 0x5b, 0x0a, 0x9b, 0xef,
-       0x42, 0x6d, 0x4e, 0xec, 0x4d, 0x1c, 0x43, 0x0c, 0x41, 0x7c, 0xce, 0x7e,
-       0x01, 0xeb, 0x19, 0xe6, 0x46, 0xd6, 0x37, 0x31, 0x7c, 0xf8, 0xbe, 0x41,
-       0x80, 0xd1, 0x3b, 0xfc, 0xf8, 0xce, 0xba, 0x28, 0xc0, 0x2a, 0x77, 0x75,
-       0x7b, 0xb5, 0xd1, 0x2e, 0xcd, 0xab, 0x3f, 0x13, 0xfe, 0x9c, 0xf0, 0x26,
-       0x16, 0x0e, 0x6f, 0x62, 0xe1, 0x6d, 0xe7, 0x30, 0xa2, 0xde, 0x6d, 0x50,
-       0xe7, 0x39, 0x3c, 0xdf, 0x11, 0x4d, 0x4f, 0xf3, 0x8c, 0x07, 0x38, 0xc7,
-       0xe2, 0x99, 0x0f, 0x7d, 0xe9, 0x41, 0x2d, 0x5b, 0x37, 0x10, 0xef, 0x99,
-       0x7f, 0x90, 0x6b, 0xcb, 0xc1, 0xd9, 0x62, 0xa0, 0x27, 0xca, 0x8e, 0x63,
-       0x7f, 0xaa, 0xa1, 0xe6, 0x4d, 0x45, 0xac, 0x43, 0xa0, 0x65, 0x0a, 0xff,
-       0x03, 0x99, 0xde, 0xa3, 0x72, 0x5f, 0x27, 0x6c, 0xf6, 0x78, 0x85, 0xd8,
-       0xf5, 0x71, 0x69, 0xf8, 0xf8, 0x75, 0x65, 0xc9, 0xc3, 0xae, 0xe1, 0xed,
-       0xd8, 0x35, 0xb5, 0x21, 0x1e, 0x8d, 0x07, 0x76, 0xa4, 0xd1, 0x70, 0x5e,
-       0x19, 0x22, 0x66, 0x25, 0x9d, 0xcc, 0x3d, 0xd3, 0x88, 0x81, 0xcc, 0x39,
-       0xcc, 0x37, 0xc4, 0xa5, 0xd7, 0xa2, 0x4f, 0x8d, 0x1d, 0xed, 0xb0, 0xa2,
-       0xf8, 0xcc, 0x83, 0x8e, 0x19, 0x3c, 0x93, 0x96, 0x85, 0xd3, 0x5f, 0xd1,
-       0x9c, 0xfa, 0x3c, 0xe8, 0x99, 0x42, 0xae, 0xa3, 0x2d, 0x15, 0x0c, 0xcf,
-       0x8e, 0xd6, 0x11, 0xf7, 0x5d, 0xc6, 0x02, 0xd4, 0xae, 0xa8, 0x47, 0xca,
-       0x8c, 0xbd, 0x3c, 0xeb, 0x0a, 0x62, 0x2e, 0xfb, 0x26, 0xa8, 0x59, 0x59,
-       0xbb, 0x2e, 0x72, 0xdf, 0xed, 0xba, 0xa8, 0xb9, 0xc4, 0x5d, 0x86, 0xb3,
-       0xbe, 0x46, 0xdc, 0xf8, 0x51, 0x31, 0xa4, 0xe1, 0xbc, 0x3c, 0x44, 0x1c,
-       0x79, 0x3d, 0xf8, 0xd1, 0x84, 0x34, 0xcd, 0x17, 0xd6, 0xf5, 0x76, 0xfc,
-       0xe8, 0x61, 0xc7, 0xcc, 0xda, 0x41, 0xac, 0xc9, 0xda, 0x8c, 0x38, 0xd1,
-       0x44, 0x98, 0x1b, 0xc4, 0xb3, 0x83, 0xe0, 0xc7, 0xc3, 0x8a, 0x59, 0x60,
-       0xc5, 0xbf, 0x03, 0xac, 0x58, 0x92, 0xf7, 0xa2, 0xc4, 0x8a, 0xb6, 0x8f,
-       0x15, 0x1d, 0xd8, 0x71, 0x7e, 0x9b, 0x1d, 0x6b, 0xaa, 0x07, 0xc5, 0x7b,
-       0x79, 0x60, 0xbd, 0xec, 0xa2, 0x79, 0x1d, 0xf8, 0x50, 0x93, 0x98, 0x3a,
-       0xaf, 0x0f, 0xb7, 0xad, 0x19, 0xe0, 0xc0, 0x7d, 0x0a, 0xdf, 0xdd, 0x57,
-       0xd9, 0x85, 0xda, 0x44, 0xe1, 0x3d, 0xff, 0x9c, 0x2f, 0x7c, 0xd5, 0xd9,
-       0x67, 0xb8, 0xed, 0xec, 0x73, 0x0b, 0x17, 0xe2, 0x39, 0xbf, 0xc7, 0x17,
-       0x81, 0xde, 0xfe, 0x07, 0x69, 0x82, 0x5f, 0xd1, 0x07, 0x34, 0xcf, 0x4f,
-       0xb6, 0xe1, 0xc3, 0xff, 0x7a, 0x15, 0x3e, 0x44, 0xce, 0x5a, 0x89, 0x49,
-       0x06, 0xd8, 0xd0, 0x5e, 0xe3, 0x5a, 0xf4, 0xe5, 0x51, 0xe9, 0x00, 0x7f,
-       0x9d, 0x8b, 0x7d, 0xc0, 0x44, 0xdd, 0x12, 0x05, 0x36, 0x8a, 0x28, 0x6c,
-       0x34, 0x44, 0x0c, 0x33, 0x7c, 0x18, 0x98, 0xa6, 0xb1, 0x89, 0x8f, 0xcc,
-       0xd4, 0x0f, 0xa0, 0x97, 0x87, 0x95, 0xad, 0x8c, 0xcb, 0x53, 0x88, 0x9d,
-       0x1d, 0x6b, 0xc0, 0x75, 0x2b, 0x1e, 0x6e, 0x8a, 0x5c, 0x85, 0x9b, 0x8e,
-       0xec, 0x88, 0x9b, 0x54, 0xbf, 0x7e, 0x9c, 0x32, 0x79, 0xdd, 0xf5, 0xfa,
-       0xf5, 0x97, 0x5c, 0xaf, 0x5f, 0xff, 0xba, 0xdb, 0xde, 0xaf, 0xbf, 0x49,
-       0x8a, 0x86, 0x69, 0x5f, 0x94, 0xab, 0xfa, 0xf5, 0x33, 0xec, 0x7f, 0x57,
-       0xbb, 0xbc, 0xbe, 0x7c, 0xb7, 0xdf, 0xaf, 0x37, 0xa5, 0xb8, 0x6d, 0xdc,
-       0x90, 0xb7, 0xad, 0xa0, 0x5f, 0xff, 0x2f, 0x30, 0xd6, 0x83, 0x3d, 0xb6,
-       0xf7, 0xea, 0x2f, 0xb9, 0xec, 0xd5, 0xc7, 0x38, 0xcf, 0xef, 0xd5, 0x73,
-       0x1e, 0x6a, 0x78, 0x97, 0x7d, 0xfa, 0x9b, 0x21, 0x8b, 0x7e, 0xc8, 0xa1,
-       0x4f, 0x3a, 0x9e, 0x8b, 0x73, 0x8e, 0xea, 0xcf, 0x5f, 0x74, 0x63, 0x78,
-       0xce, 0xeb, 0xa3, 0x1f, 0x86, 0x5d, 0x1d, 0xd9, 0xec, 0xcf, 0x7b, 0x7b,
-       0xbc, 0xe1, 0x6e, 0x5f, 0x7f, 0xfb, 0x3a, 0x03, 0xfe, 0x3a, 0x31, 0xac,
-       0x13, 0xbf, 0x6a, 0x9d, 0xad, 0x7e, 0xfc, 0x1b, 0xae, 0xd7, 0x8b, 0x77,
-       0x4e, 0x8b, 0xdd, 0x81, 0x98, 0xfc, 0xe2, 0xd0, 0x8d, 0xfe, 0x1a, 0x9b,
-       0xbd, 0x78, 0xc6, 0x0e, 0xe0, 0x75, 0xc6, 0x0f, 0x3e, 0xff, 0xff, 0xbe,
-       0x17, 0xcf, 0x3e, 0xbc, 0x77, 0x9e, 0x42, 0xff, 0x04, 0x2e, 0x7f, 0xd6,
-       0xeb, 0xc1, 0x4f, 0x54, 0x82, 0xde, 0x3a, 0xeb, 0xc6, 0xe0, 0xbd, 0x8c,
-       0xc1, 0xc4, 0x71, 0xa1, 0xad, 0x90, 0x3e, 0xae, 0xdb, 0x23, 0x73, 0x0a,
-       0x17, 0xc1, 0xa6, 0x92, 0xd7, 0xc6, 0xc6, 0xb5, 0xc5, 0x00, 0x1b, 0xc7,
-       0x14, 0x36, 0xae, 0xad, 0x05, 0xd8, 0x38, 0x73, 0x0d, 0x6c, 0xfc, 0xdf,
-       0xba, 0xbc, 0xf8, 0x1f, 0x95, 0x82, 0xc2, 0xc6, 0xd7, 0x7a, 0xc7, 0x86,
-       0xf7, 0xba, 0x89, 0x03, 0xc4, 0x3b, 0x17, 0xef, 0xbb, 0x86, 0xaf, 0x05,
-       0x78, 0x99, 0xb9, 0xbe, 0x5f, 0x66, 0x9e, 0xdb, 0xc2, 0xcb, 0x1e, 0x26,
-       0x36, 0x13, 0x47, 0x55, 0x2e, 0x04, 0x3e, 0x68, 0xb2, 0xef, 0x7d, 0x48,
-       0xd9, 0x6e, 0xa9, 0x32, 0xab, 0x70, 0x59, 0x1e, 0xb5, 0x6d, 0x51, 0xe1,
-       0x60, 0x62, 0xe0, 0x2e, 0x91, 0xbe, 0x20, 0x17, 0x05, 0x18, 0x33, 0xec,
-       0xc7, 0x67, 0x9e, 0x29, 0xbc, 0x1d, 0xca, 0x10, 0x03, 0xbb, 0x41, 0x8d,
-       0x40, 0x39, 0x0f, 0x23, 0x76, 0x19, 0xbe, 0xac, 0x3c, 0x9f, 0xdd, 0xb7,
-       0xff, 0x87, 0xef, 0xdb, 0x06, 0xe3, 0x5a, 0x80, 0x11, 0x51, 0x03, 0x55,
-       0xc6, 0xd5, 0xbb, 0x0e, 0x1e, 0x46, 0xf4, 0xf0, 0x61, 0xd6, 0x9d, 0x01,
-       0x4e, 0x9e, 0x95, 0x09, 0xe0, 0xf3, 0xf5, 0xdf, 0x65, 0xef, 0x29, 0xc0,
-       0x44, 0x36, 0xfe, 0xb7, 0xf7, 0xa2, 0x78, 0xdd, 0xa1, 0xce, 0xfe, 0xce,
-       0x0f, 0x45, 0xdb, 0xc6, 0xff, 0x3e, 0xe2, 0x37, 0xea, 0xa1, 0x0a, 0x73,
-       0x1d, 0xb1, 0xd0, 0x6f, 0x40, 0x07, 0x63, 0xd7, 0xc0, 0x42, 0x57, 0xe7,
-       0x26, 0xe6, 0xcb, 0xad, 0xbc, 0xe4, 0x6c, 0xe6, 0x25, 0xee, 0xf1, 0xeb,
-       0x72, 0x27, 0xc7, 0x6c, 0x23, 0x62, 0x4d, 0xe1, 0x33, 0x8f, 0x7c, 0xbd,
-       0x3d, 0x37, 0xcd, 0x5d, 0x47, 0x6e, 0x9a, 0x50, 0xb9, 0x89, 0xf4, 0xa2,
-       0x9e, 0x83, 0x4c, 0xbe, 0x0b, 0x59, 0x7e, 0x07, 0xb4, 0xff, 0x11, 0xf8,
-       0xf9, 0x43, 0x60, 0xac, 0x6f, 0x03, 0x63, 0x7d, 0xab, 0xd2, 0xfe, 0x0e,
-       0xc3, 0xb8, 0xb0, 0x0e, 0xf4, 0xea, 0x66, 0x0f, 0xc3, 0x1f, 0x86, 0x57,
-       0x35, 0xca, 0x86, 0x33, 0x57, 0x1e, 0x31, 0xe6, 0xbd, 0xf3, 0xd2, 0x44,
-       0x4e, 0xd2, 0x88, 0x11, 0xcc, 0x15, 0xea, 0x3a, 0xce, 0x7e, 0x25, 0xb1,
-       0x42, 0x5d, 0xd5, 0x93, 0x43, 0x52, 0x6d, 0x78, 0xf8, 0x6a, 0xe1, 0x8c,
-       0xb7, 0xc6, 0x9c, 0x8f, 0xaf, 0xf2, 0x3e, 0xbe, 0xca, 0x35, 0x36, 0x12,
-       0xac, 0xcf, 0x17, 0x52, 0xdb, 0x31, 0xd5, 0x61, 0x1f, 0x53, 0xcd, 0xff,
-       0x15, 0x31, 0x15, 0xf7, 0xca, 0xe3, 0x99, 0xc9, 0xa5, 0x84, 0x1c, 0x80,
-       0x7c, 0x27, 0xca, 0xd4, 0x93, 0x69, 0xc3, 0x6e, 0x3e, 0x44, 0x57, 0x8e,
-       0xd2, 0x4b, 0x28, 0xe9, 0xe9, 0x69, 0x12, 0x7a, 0x9a, 0xf8, 0xb5, 0xf5,
-       0x8d, 0x1a, 0x33, 0xde, 0x1c, 0x8b, 0xe2, 0xf3, 0x7f, 0xaa, 0x23, 0xd2,
-       0x4f, 0x3d, 0x5d, 0x8d, 0xb9, 0xae, 0x07, 0x7b, 0x6d, 0xc7, 0x5d, 0xb6,
-       0xc2, 0x5d, 0x1d, 0xfe, 0x9c, 0x99, 0x89, 0x49, 0xe8, 0xf0, 0xdf, 0x63,
-       0xce, 0x9f, 0xc0, 0xb7, 0x7e, 0x88, 0x78, 0xfd, 0xef, 0xa0, 0x8b, 0x7f,
-       0x8b, 0xda, 0xe0, 0x55, 0xe4, 0x9f, 0x1f, 0x60, 0x6c, 0x0b, 0xc7, 0xa8,
-       0x33, 0xfa, 0xd1, 0x8c, 0x95, 0x98, 0x28, 0xba, 0x89, 0x09, 0x0f, 0x7f,
-       0xfc, 0xea, 0x6f, 0x66, 0xac, 0x29, 0xbe, 0xc3, 0x00, 0xf9, 0xfe, 0xf9,
-       0xdd, 0x73, 0x0a, 0x7b, 0x04, 0x98, 0x23, 0x67, 0x73, 0xff, 0x92, 0x9b,
-       0x9a, 0xa8, 0xe1, 0xe3, 0x61, 0x9b, 0xef, 0xd9, 0x1e, 0xb6, 0x59, 0xfa,
-       0xeb, 0xd4, 0xbb, 0x87, 0x6b, 0x1e, 0x4e, 0xd3, 0xaf, 0xeb, 0xc0, 0x1c,
-       0x35, 0xf8, 0x64, 0xa1, 0x69, 0xab, 0xcf, 0xf1, 0x8a, 0x6d, 0x46, 0x20,
-       0x1f, 0xf6, 0x58, 0x4f, 0xd1, 0x0b, 0x5d, 0xd3, 0x28, 0x13, 0x81, 0xba,
-       0x66, 0xfc, 0x9f, 0xf9, 0xd7, 0x4f, 0xfb, 0xd7, 0x4f, 0xf9, 0xd7, 0x27,
-       0x91, 0x77, 0x9f, 0x54, 0xb9, 0x93, 0xe3, 0x1c, 0x83, 0x72, 0x5d, 0xac,
-       0x85, 0xf5, 0xce, 0x8e, 0xfe, 0xb4, 0x55, 0x8d, 0x79, 0xfe, 0x5c, 0x68,
-       0x3a, 0xf8, 0xfc, 0x63, 0x7c, 0x0e, 0xe2, 0x33, 0x8d, 0xcf, 0x63, 0xf8,
-       0x6c, 0xca, 0x54, 0xcb, 0x56, 0xa8, 0xa3, 0x61, 0xc9, 0x62, 0xbc, 0x88,
-       0x3a, 0x34, 0x93, 0x7a, 0x44, 0x8a, 0xf5, 0x92, 0x94, 0x96, 0x34, 0xe9,
-       0xb6, 0xd2, 0x52, 0xaa, 0x1f, 0x93, 0xe3, 0x4b, 0xde, 0xb9, 0x61, 0x57,
-       0xda, 0xc6, 0xdc, 0x96, 0x3c, 0x9c, 0x7a, 0x5c, 0xf4, 0x3b, 0x8f, 0x61,
-       0x9e, 0xe8, 0xc5, 0xd1, 0xdb, 0xd4, 0xf9, 0x58, 0x3d, 0xe5, 0xc9, 0xf8,
-       0x80, 0x65, 0x9b, 0xc8, 0x5b, 0xc3, 0x4f, 0x62, 0xed, 0x8c, 0x7a, 0x3f,
-       0x30, 0x2d, 0x27, 0x4e, 0x6f, 0xec, 0xf5, 0x62, 0xa9, 0x69, 0xbc, 0x81,
-       0x4d, 0xeb, 0xe0, 0xc3, 0x46, 0xec, 0x9b, 0x82, 0x9d, 0x1f, 0x71, 0xc3,
-       0xda, 0x04, 0x62, 0xe0, 0x84, 0xab, 0x6a, 0x3d, 0xc4, 0x2a, 0xc3, 0x49,
-       0x9e, 0x8a, 0xe1, 0x9a, 0xef, 0xd0, 0x20, 0x0f, 0x2a, 0x5b, 0xd9, 0x00,
-       0x8e, 0xd1, 0x54, 0xbf, 0xaf, 0xb4, 0x79, 0x0e, 0xa4, 0xfa, 0xff, 0x4e,
-       0x32, 0xa9, 0x4b, 0x7e, 0x8c, 0x38, 0xd6, 0x56, 0xb9, 0xa8, 0x51, 0xb6,
-       0x3f, 0xc1, 0xda, 0xf0, 0x75, 0x61, 0x5e, 0xbb, 0x07, 0xf3, 0x06, 0x10,
-       0x7f, 0x71, 0xaf, 0x09, 0x5e, 0x4e, 0x93, 0x57, 0x3e, 0x83, 0xda, 0xb6,
-       0xfa, 0x49, 0xbd, 0xb8, 0xe4, 0xd7, 0x44, 0xaa, 0x76, 0x48, 0x48, 0x7d,
-       0xf3, 0xcc, 0xc9, 0xeb, 0x93, 0xd4, 0xdd, 0x00, 0x3b, 0xf4, 0x60, 0x0e,
-       0xeb, 0x08, 0xc8, 0xc8, 0x3b, 0x27, 0x53, 0x67, 0x64, 0x45, 0xf7, 0x93,
-       0x7a, 0x69, 0x29, 0x83, 0x71, 0xf6, 0xa4, 0xf1, 0xbd, 0xaa, 0x2b, 0xec,
-       0x7f, 0x31, 0x74, 0x58, 0x1a, 0xd5, 0x16, 0xe8, 0x45, 0x8e, 0xdd, 0x7b,
-       0x58, 0x6a, 0xd5, 0x79, 0x79, 0xa1, 0xba, 0xb1, 0x0b, 0xd8, 0x09, 0x32,
-       0x25, 0xfd, 0x3d, 0x3e, 0xfd, 0x54, 0x41, 0x30, 0x0e, 0x79, 0x9e, 0x2e,
-       0xc4, 0xbd, 0xba, 0x96, 0xb8, 0xed, 0x24, 0xdf, 0x1b, 0x8c, 0xf3, 0x3d,
-       0xbe, 0x23, 0xcb, 0xb4, 0xc9, 0x8b, 0xf7, 0x2e, 0x58, 0x9f, 0x92, 0x0b,
-       0xa9, 0x3d, 0xb2, 0x91, 0x52, 0xf5, 0x2f, 0xf1, 0x01, 0x7c, 0xdb, 0x34,
-       0xd6, 0xe5, 0x6e, 0x39, 0x01, 0x3f, 0xbd, 0x90, 0xca, 0xa9, 0xf3, 0x9b,
-       0xe3, 0x4d, 0x62, 0xfb, 0x79, 0xd6, 0x54, 0xb2, 0xae, 0x7a, 0x60, 0xad,
-       0xd6, 0x64, 0x8a, 0xb1, 0xa7, 0x43, 0x36, 0x14, 0xd6, 0xf2, 0x7a, 0xe3,
-       0x1b, 0xb3, 0x9e, 0x6f, 0x84, 0x94, 0xbd, 0xff, 0x1b, 0xd0, 0x71, 0x0c,
-       0x36, 0x1b, 0x51, 0x73, 0x42, 0xe9, 0x4e, 0x7f, 0x8e, 0xc2, 0x66, 0x6d,
-       0x73, 0xc6, 0xc7, 0x33, 0x96, 0xf1, 0xa9, 0x8c, 0x35, 0x36, 0xe1, 0xf5,
-       0x53, 0x4c, 0xc3, 0xd6, 0x2e, 0xb6, 0x82, 0xf7, 0x4d, 0xa6, 0xe0, 0x4f,
-       0x2f, 0x6d, 0x62, 0x63, 0x18, 0xe7, 0xf3, 0x0b, 0xd0, 0x6b, 0x58, 0x3a,
-       0x4e, 0xb5, 0xee, 0x99, 0x4b, 0x8d, 0x24, 0x8e, 0x08, 0xdf, 0x30, 0x62,
-       0xfd, 0x6c, 0x82, 0xda, 0x05, 0xe4, 0xc3, 0x2b, 0xc4, 0x08, 0xc3, 0xe7,
-       0xe5, 0xca, 0x3d, 0x99, 0xd4, 0x7e, 0xad, 0x36, 0x8b, 0xea, 0xe4, 0xf9,
-       0x29, 0xe6, 0xd3, 0xa3, 0xec, 0x7d, 0x86, 0x4e, 0xbd, 0xad, 0x39, 0x65,
-       0xf5, 0x8e, 0x39, 0xf4, 0xd2, 0xd2, 0xe6, 0x21, 0x37, 0x3c, 0x3f, 0xc3,
-       0x04, 0xa8, 0x5b, 0x83, 0x09, 0x47, 0x72, 0xec, 0x71, 0x49, 0x7e, 0x59,
-       0xf6, 0x65, 0x10, 0x47, 0xed, 0x99, 0x0e, 0x99, 0x6f, 0x18, 0xce, 0xe0,
-       0xe2, 0x51, 0xac, 0x31, 0x87, 0xb5, 0xa6, 0x51, 0x83, 0xcc, 0x22, 0x27,
-       0x53, 0xae, 0x8c, 0xd5, 0x0f, 0x43, 0x46, 0x37, 0xf1, 0xcc, 0x78, 0x3c,
-       0x27, 0xe6, 0x4c, 0x41, 0xad, 0xfb, 0x9e, 0x96, 0x1f, 0xfd, 0x18, 0x72,
-       0x5a, 0x58, 0x0e, 0x24, 0x45, 0x9f, 0x4e, 0x86, 0xdf, 0x9f, 0xb3, 0x38,
-       0x16, 0xe5, 0x98, 0x8e, 0xb1, 0xf0, 0xe7, 0x92, 0x51, 0x3d, 0x93, 0x34,
-       0xc7, 0xd9, 0xef, 0x0d, 0x59, 0x73, 0x12, 0x7a, 0xbe, 0xb7, 0x47, 0xba,
-       0xa7, 0xa5, 0x77, 0xd5, 0x1c, 0x7f, 0x1d, 0xb4, 0x84, 0x55, 0x6c, 0x9f,
-       0x13, 0xdd, 0x1f, 0xef, 0xd9, 0x1c, 0x0f, 0xfb, 0xe3, 0xd3, 0xd2, 0xbd,
-       0x3a, 0x62, 0xbc, 0x29, 0x87, 0xb1, 0x66, 0x48, 0x2e, 0xa1, 0xa6, 0xb1,
-       0x86, 0xe6, 0xe0, 0x73, 0x0f, 0x91, 0x96, 0x83, 0xc0, 0x14, 0xf0, 0x09,
-       0xd4, 0xd9, 0xd6, 0x27, 0xe5, 0x4b, 0x46, 0x97, 0xe4, 0x55, 0x4d, 0x1b,
-       0xf6, 0x7a, 0xa5, 0xb0, 0xf3, 0x5b, 0x87, 0xa6, 0x77, 0x7b, 0xfd, 0x00,
-       0x9e, 0x67, 0x8c, 0x62, 0xec, 0x4a, 0x6b, 0xc5, 0xe2, 0x18, 0xef, 0x5d,
-       0x69, 0xd5, 0xad, 0x11, 0x23, 0xab, 0x45, 0xfd, 0x73, 0xed, 0x79, 0xc5,
-       0x7b, 0xa1, 0x3a, 0x68, 0xd4, 0xe4, 0x16, 0x2d, 0x7b, 0x03, 0xf2, 0x83,
-       0xfb, 0x19, 0xcc, 0xbd, 0xd2, 0xca, 0x58, 0xf3, 0xaa, 0x7f, 0x5f, 0x93,
-       0xe0, 0x9a, 0xeb, 0x8c, 0x18, 0x93, 0xea, 0xd9, 0x11, 0xe3, 0x84, 0xd6,
-       0xfe, 0xac, 0xa1, 0x4d, 0x6e, 0x7b, 0xb6, 0x5b, 0xc9, 0x28, 0x64, 0x79,
-       0x73, 0x4a, 0xd5, 0x69, 0x79, 0xda, 0xe5, 0xbc, 0x2b, 0xad, 0xac, 0x15,
-       0xd1, 0x4e, 0xdc, 0xc0, 0x18, 0xc8, 0xb9, 0x97, 0xaf, 0xda, 0x87, 0xd7,
-       0xd7, 0xda, 0xe3, 0x5d, 0xd9, 0xbe, 0xc7, 0x2e, 0x35, 0xe7, 0x82, 0x9a,
-       0x13, 0x56, 0xb2, 0xde, 0xbe, 0xcf, 0xcf, 0x64, 0xfb, 0x3e, 0xdd, 0x9b,
-       0x3c, 0x97, 0xb0, 0xe6, 0x93, 0x98, 0x5b, 0x76, 0x07, 0xe3, 0x75, 0xb9,
-       0xdc, 0xca, 0x5b, 0x17, 0xe5, 0xc2, 0xe6, 0xda, 0xbf, 0xc2, 0x75, 0x3b,
-       0x4d, 0xbf, 0xf2, 0x69, 0xe4, 0x77, 0x8e, 0x3d, 0xaa, 0xe4, 0xbd, 0xdb,
-       0x1a, 0x3c, 0x58, 0xd3, 0xcc, 0xf1, 0x9f, 0x09, 0x75, 0x75, 0x44, 0xc5,
-       0x98, 0xdb, 0xa0, 0xa7, 0x7d, 0xcf, 0xc0, 0x67, 0x47, 0x6d, 0x35, 0xe7,
-       0x92, 0x35, 0x2d, 0xfb, 0x4e, 0x0d, 0x1a, 0x97, 0x10, 0xdb, 0x9c, 0x18,
-       0xaf, 0x51, 0x2b, 0x59, 0x7c, 0x27, 0xfe, 0x4e, 0xd6, 0x01, 0xd0, 0xe5,
-       0xe0, 0xf0, 0xcf, 0xe4, 0xa8, 0x9c, 0xa8, 0x1c, 0x43, 0x2e, 0x9c, 0x93,
-       0xe1, 0x67, 0x90, 0x37, 0x2a, 0x05, 0x3c, 0x49, 0x9f, 0xf5, 0x72, 0xe0,
-       0x9c, 0x7a, 0xcf, 0xfc, 0x24, 0xea, 0x64, 0xd8, 0x6e, 0x79, 0x70, 0x78,
-       0x05, 0xcf, 0xbc, 0xa0, 0x70, 0xa8, 0x2b, 0x0d, 0xf8, 0x40, 0xe2, 0xf9,
-       0x3d, 0xb2, 0xfb, 0x01, 0xda, 0x22, 0x32, 0xfd, 0x6d, 0x11, 0xf5, 0xee,
-       0xbd, 0x6e, 0x75, 0x8a, 0xec, 0xa5, 0xdd, 0x34, 0x61, 0x63, 0x73, 0xde,
-       0x99, 0xd6, 0xb6, 0x6b, 0x73, 0xe6, 0xa2, 0xac, 0x2a, 0xfb, 0xbb, 0x7d,
-       0xd5, 0xfb, 0x3f, 0xba, 0x8a, 0x72, 0x38, 0x39, 0x2d, 0x77, 0xac, 0x7a,
-       0xf6, 0x56, 0x5a, 0x3a, 0xaa, 0xe4, 0x3a, 0xa7, 0xe4, 0xda, 0x92, 0xc3,
-       0x29, 0xca, 0x9c, 0xbc, 0xf0, 0xbd, 0x40, 0x4f, 0x16, 0xf7, 0xfb, 0xf6,
-       0x33, 0xf8, 0x0c, 0x7f, 0x57, 0x42, 0xd9, 0xb0, 0xee, 0xbe, 0x7f, 0x37,
-       0xcf, 0x59, 0xf7, 0xad, 0x92, 0xcf, 0x1b, 0xb7, 0xf1, 0xf9, 0x14, 0x62,
-       0xea, 0xd0, 0x90, 0xc7, 0xeb, 0xab, 0x4b, 0x1f, 0xce, 0xeb, 0x37, 0x37,
-       0x79, 0x0d, 0x49, 0x43, 0xd5, 0xaf, 0x5d, 0xbd, 0xd2, 0x8d, 0xa8, 0x07,
-       0x7b, 0xf8, 0x09, 0xf6, 0x9a, 0x12, 0xd2, 0xe0, 0xed, 0xb7, 0xe1, 0x92,
-       0x96, 0x80, 0x76, 0xd2, 0x73, 0x9f, 0xaf, 0x2f, 0xee, 0x7f, 0x74, 0xc7,
-       0x7b, 0x97, 0xc4, 0x70, 0x86, 0x31, 0xa6, 0x2b, 0x9d, 0x65, 0x7d, 0xff,
-       0x9a, 0x16, 0x5d, 0xe9, 0xcc, 0xde, 0xd4, 0xd9, 0xeb, 0xd0, 0x59, 0x5d,
-       0x7e, 0x13, 0xbc, 0xc0, 0x9f, 0x9f, 0x19, 0x31, 0x0e, 0x13, 0x5b, 0x18,
-       0x5c, 0x0f, 0x31, 0xd4, 0xd7, 0x5d, 0xc7, 0x47, 0xd0, 0xdd, 0x9b, 0xa2,
-       0xf4, 0x07, 0x7e, 0x90, 0x7f, 0xd4, 0xf3, 0x8c, 0x61, 0xe4, 0xa9, 0x43,
-       0xf9, 0x3e, 0x69, 0x53, 0x67, 0xfc, 0x33, 0x9e, 0x3e, 0x95, 0x6f, 0xfb,
-       0xfa, 0xcc, 0xcd, 0x50, 0x67, 0xe6, 0x6e, 0x4f, 0x7f, 0x9d, 0x6a, 0xce,
-       0x62, 0x32, 0xa1, 0xfc, 0xda, 0x1a, 0xba, 0x65, 0x37, 0x75, 0xf8, 0xb4,
-       0xeb, 0xfd, 0x2f, 0xbb, 0xd3, 0xb2, 0xe8, 0x7e, 0x98, 0x1e, 0x3d, 0x1d,
-       0x4e, 0x88, 0xe7, 0x3f, 0x57, 0xeb, 0x4f, 0x5f, 0x0d, 0x2b, 0x5b, 0x9d,
-       0x80, 0xec, 0x4e, 0x56, 0x3e, 0xe6, 0xdb, 0xb7, 0xc7, 0xeb, 0xd0, 0x87,
-       0xf0, 0x7a, 0xb8, 0x3c, 0x68, 0xbc, 0x8d, 0xb5, 0x26, 0x15, 0x86, 0x8b,
-       0x88, 0xe3, 0xf3, 0x9a, 0xd8, 0xe4, 0x35, 0xa0, 0xcd, 0x9b, 0x97, 0x65,
-       0x5d, 0xea, 0x32, 0x3e, 0x3d, 0xaa, 0xde, 0xbf, 0x7f, 0xa3, 0xcc, 0xb8,
-       0x0c, 0xcc, 0x13, 0xeb, 0x93, 0x4b, 0x8d, 0x84, 0x5c, 0x22, 0x96, 0x18,
-       0xc3, 0x7f, 0xf7, 0x98, 0x9f, 0x9b, 0xa3, 0xf2, 0x66, 0xb9, 0xbd, 0x56,
-       0x1c, 0x95, 0xd7, 0xcb, 0x41, 0xbd, 0x48, 0x2c, 0xcb, 0xfc, 0x3f, 0x27,
-       0x6f, 0x2d, 0x0d, 0xca, 0xfa, 0x0c, 0xf2, 0xf8, 0x10, 0x65, 0x30, 0x62,
-       0x7c, 0x46, 0xfd, 0xbe, 0xe2, 0x4a, 0xeb, 0xbc, 0x85, 0x75, 0x97, 0x5b,
-       0x72, 0x84, 0xe7, 0xd0, 0xfc, 0xde, 0xf8, 0x04, 0x56, 0xe1, 0xbc, 0x3e,
-       0xa9, 0x2d, 0xa3, 0x2e, 0x2f, 0x73, 0x5d, 0xca, 0x69, 0x5a, 0x7d, 0x9f,
-       0xc4, 0x3e, 0xf7, 0xf3, 0xbd, 0xf4, 0x18, 0x75, 0x71, 0xa5, 0xb5, 0x61,
-       0xf1, 0x1c, 0x72, 0x4e, 0x1a, 0xd0, 0xd7, 0x97, 0x93, 0x3c, 0x27, 0xcf,
-       0x0b, 0x7f, 0x9f, 0x52, 0x6b, 0xcc, 0xa0, 0x16, 0xb8, 0xd2, 0x5a, 0xb0,
-       0x9e, 0x52, 0x7a, 0x6a, 0x54, 0x1f, 0xf0, 0xc7, 0x79, 0xcd, 0x7b, 0x86,
-       0xb3, 0x6f, 0x88, 0xf5, 0xe7, 0x03, 0xc8, 0xff, 0xac, 0x3d, 0x89, 0xb7,
-       0x28, 0x8b, 0x04, 0x6a, 0x5c, 0xae, 0xc5, 0xdf, 0x04, 0x25, 0x87, 0xf3,
-       0x32, 0x09, 0x7a, 0x80, 0xcb, 0x5c, 0xc6, 0xfd, 0x5b, 0x65, 0x23, 0xe6,
-       0xc5, 0x77, 0xbe, 0xaf, 0xb5, 0x81, 0x98, 0xbf, 0xb1, 0x19, 0xf3, 0xfb,
-       0x71, 0x6d, 0x38, 0xa9, 0xa1, 0xff, 0x84, 0xf5, 0xd9, 0x77, 0x61, 0xcc,
-       0x1f, 0xc7, 0x7c, 0x8e, 0xf5, 0x49, 0x69, 0x59, 0x6c, 0xf6, 0x99, 0x6a,
-       0xc2, 0x77, 0x31, 0x72, 0xb2, 0xd8, 0x18, 0x8c, 0x9f, 0xd7, 0x1c, 0xf5,
-       0xce, 0x46, 0x72, 0x88, 0x7d, 0xb7, 0x3e, 0x69, 0x2c, 0x4b, 0x22, 0x94,
-       0x7e, 0x48, 0xdc, 0x86, 0x87, 0xb9, 0x17, 0x34, 0xf6, 0xdf, 0x6c, 0x69,
-       0x6c, 0x9f, 0x63, 0x84, 0xd2, 0x87, 0xe4, 0x0f, 0xfc, 0x39, 0x8e, 0x9a,
-       0xf3, 0x1f, 0x76, 0xf3, 0xec, 0xab, 0xe1, 0xf6, 0x82, 0x06, 0xd2, 0x76,
-       0x63, 0xfb, 0xbe, 0x89, 0xad, 0x7d, 0xb9, 0x27, 0x6a, 0x98, 0xbd, 0x36,
-       0xf6, 0x7d, 0x15, 0xcf, 0x3c, 0x04, 0x3a, 0xae, 0x84, 0x74, 0xeb, 0x21,
-       0x29, 0x36, 0xae, 0xde, 0xa3, 0x9d, 0x06, 0x3e, 0xc3, 0xf5, 0xb9, 0xcf,
-       0x21, 0xd0, 0x77, 0x45, 0xd3, 0xad, 0x43, 0x90, 0xa5, 0xb7, 0x47, 0xe8,
-       0x39, 0xd3, 0xf8, 0xa1, 0x0c, 0x89, 0xbe, 0xa2, 0x29, 0xf9, 0xeb, 0xb5,
-       0x51, 0x38, 0xc4, 0x94, 0x74, 0xaf, 0xcd, 0x4a, 0x68, 0x8d, 0x3d, 0x00,
-       0xda, 0x22, 0xf5, 0xb8, 0x0b, 0x7e, 0x2c, 0x76, 0xd8, 0x22, 0xde, 0x67,
-       0x1f, 0x77, 0xb5, 0x57, 0x7a, 0x89, 0xf7, 0x59, 0x0f, 0x1c, 0xc4, 0x7f,
-       0xd6, 0x04, 0x2f, 0xb5, 0x32, 0xa9, 0x77, 0x54, 0xde, 0xcc, 0x37, 0x78,
-       0xdf, 0x4c, 0x88, 0xf0, 0x1e, 0xe3, 0x43, 0x9f, 0x44, 0xbe, 0x3e, 0x8c,
-       0x98, 0x90, 0x03, 0x76, 0xc6, 0xba, 0xa7, 0x86, 0x24, 0xec, 0xbd, 0xeb,
-       0xa0, 0xfa, 0x25, 0x6f, 0x2d, 0x9b, 0xfe, 0xef, 0x53, 0x64, 0xdf, 0xf9,
-       0x14, 0x7b, 0x9a, 0x03, 0xb0, 0x53, 0xd6, 0x23, 0xa2, 0x6f, 0xa0, 0xde,
-       0xbc, 0xd4, 0x88, 0xf6, 0xf2, 0x7d, 0xcb, 0xd7, 0x5d, 0x5c, 0x13, 0xbb,
-       0xc7, 0x14, 0x56, 0xf4, 0xef, 0xf1, 0x3b, 0xea, 0xa0, 0x6d, 0x98, 0x32,
-       0x01, 0x4c, 0xc9, 0x3a, 0x69, 0xca, 0x7f, 0xe7, 0xcd, 0x70, 0x4e, 0x6c,
-       0xab, 0x95, 0x86, 0x65, 0x03, 0x38, 0x6b, 0xdd, 0xb5, 0x10, 0x07, 0xdf,
-       0xd6, 0xea, 0x65, 0xf5, 0xbb, 0x34, 0xed, 0x01, 0x60, 0xac, 0x44, 0x9f,
-       0xaa, 0x75, 0x4e, 0x3e, 0x20, 0x9e, 0xbd, 0xc3, 0xca, 0x54, 0xcc, 0x5a,
-       0xaf, 0x7a, 0xb5, 0xc5, 0x46, 0x75, 0x4a, 0xfe, 0xd4, 0x5d, 0x50, 0xbd,
-       0xd2, 0x25, 0xd4, 0x1b, 0xe1, 0x45, 0x55, 0x6b, 0xb5, 0xe1, 0x54, 0xc4,
-       0xb7, 0x67, 0x8f, 0xc0, 0x07, 0x4d, 0xf5, 0x6e, 0x81, 0xbe, 0xd2, 0x6a,
-       0x65, 0x11, 0x2f, 0x74, 0xcb, 0x32, 0x8a, 0xc8, 0x73, 0x59, 0xf5, 0x7e,
-       0x0a, 0xfd, 0xf7, 0xf7, 0x54, 0x1c, 0x96, 0x1a, 0x64, 0xf3, 0x5c, 0x02,
-       0xeb, 0x68, 0xca, 0x3e, 0x43, 0x4a, 0x0f, 0x0f, 0x28, 0xec, 0x1a, 0x5a,
-       0x41, 0x80, 0x5a, 0x1b, 0x12, 0x59, 0x81, 0xbf, 0xc2, 0x77, 0xc3, 0x6b,
-       0xd4, 0x01, 0x65, 0x3b, 0x2b, 0x11, 0xc8, 0x9e, 0x58, 0x22, 0xb4, 0x48,
-       0x19, 0xc7, 0x61, 0x17, 0x5c, 0x07, 0x32, 0xe6, 0xbb, 0x2c, 0xcb, 0x1d,
-       0xf2, 0x4c, 0xc3, 0xf4, 0xdf, 0x3d, 0x7f, 0x89, 0xef, 0xa3, 0xeb, 0x73,
-       0x63, 0x03, 0xc4, 0x4f, 0x52, 0x6a, 0x00, 0x63, 0x9c, 0x66, 0x0d, 0xce,
-       0x18, 0x50, 0x88, 0x47, 0x94, 0xaf, 0xb3, 0x06, 0xf6, 0x7c, 0x9f, 0xf8,
-       0x3a, 0x62, 0x11, 0xdb, 0x8e, 0x62, 0x8f, 0x9d, 0xe4, 0xea, 0xd5, 0x9e,
-       0x93, 0xa0, 0xf3, 0xfc, 0x92, 0x39, 0x55, 0x90, 0x14, 0xdf, 0x71, 0x9e,
-       0xb1, 0xc1, 0xf7, 0x06, 0xe2, 0xe4, 0x42, 0x85, 0xef, 0x33, 0x17, 0xe1,
-       0x59, 0x53, 0x72, 0xbe, 0xcc, 0x1a, 0xf0, 0x76, 0xe8, 0x8b, 0xd7, 0xc5,
-       0xf1, 0x10, 0xfc, 0xff, 0xa2, 0xc1, 0xdf, 0x91, 0xf1, 0x77, 0x41, 0x66,
-       0x2a, 0xa1, 0x1d, 0x84, 0x8e, 0x0b, 0x46, 0xc4, 0xb7, 0x03, 0xa7, 0x4c,
-       0x8c, 0x35, 0x62, 0x9c, 0xc3, 0xf7, 0x97, 0xdd, 0xcb, 0x2d, 0xd6, 0x3f,
-       0x17, 0x10, 0xe7, 0xa6, 0x92, 0x53, 0xb0, 0x9d, 0x42, 0xbc, 0x13, 0xb4,
-       0xfe, 0x5d, 0xdc, 0xcb, 0xbb, 0xdc, 0xc7, 0x4c, 0x5d, 0x94, 0x22, 0x30,
-       0xfd, 0x48, 0xe2, 0x65, 0xd9, 0x83, 0x3a, 0x55, 0x93, 0x37, 0x2d, 0x73,
-       0x5c, 0x34, 0xb5, 0xde, 0xf0, 0x7d, 0xb0, 0xbd, 0x37, 0x10, 0xdf, 0x3a,
-       0xfc, 0xda, 0x3d, 0x5b, 0x26, 0x16, 0x3a, 0xaa, 0xde, 0x05, 0xb8, 0x60,
-       0xb1, 0x7f, 0xc7, 0xdf, 0x44, 0xfe, 0xa5, 0xda, 0x63, 0xeb, 0x8c, 0x8d,
-       0xfd, 0x63, 0xd2, 0xe7, 0xf1, 0x78, 0xc0, 0xf2, 0x68, 0xe4, 0x3a, 0x91,
-       0xb6, 0x75, 0xce, 0xfb, 0xeb, 0x9c, 0xf5, 0xd7, 0xa9, 0xf9, 0xeb, 0x5c,
-       0xd8, 0x5c, 0xe7, 0x6e, 0xe8, 0xbf, 0xd5, 0x7a, 0x0a, 0xf8, 0x21, 0x93,
-       0x6a, 0xb5, 0x1c, 0xd4, 0x59, 0xa5, 0xd1, 0x79, 0x75, 0x46, 0xaa, 0xa7,
-       0xbf, 0x71, 0x6f, 0xc6, 0x2a, 0xc4, 0xc3, 0x0a, 0x7b, 0xa0, 0x92, 0x82,
-       0x1d, 0x16, 0xc4, 0xc3, 0xdc, 0x3c, 0xb7, 0xf3, 0xce, 0xf5, 0xba, 0xa1,
-       0xc3, 0x1c, 0x72, 0x86, 0x91, 0x39, 0x67, 0x49, 0x61, 0xdf, 0x6f, 0xea,
-       0xb0, 0xf3, 0x5e, 0xe4, 0x87, 0x9f, 0xc0, 0x66, 0x8c, 0x4c, 0xbd, 0x91,
-       0x43, 0xbd, 0xc3, 0xf9, 0x77, 0x40, 0x8f, 0x85, 0x4c, 0xad, 0x51, 0xc8,
-       0x9c, 0xe5, 0x79, 0x0e, 0xe6, 0xd5, 0x1a, 0x3d, 0x90, 0x7b, 0x8f, 0xea,
-       0x8b, 0xbc, 0x5c, 0x8e, 0x31, 0x06, 0xc1, 0xd6, 0x63, 0x18, 0x8b, 0xab,
-       0xdf, 0x68, 0xd5, 0xdd, 0x65, 0xf8, 0x74, 0x02, 0xe3, 0xd5, 0xae, 0x49,
-       0x85, 0x47, 0x2d, 0x59, 0x71, 0x7f, 0xa5, 0x15, 0xcb, 0x97, 0xb5, 0x52,
-       0x79, 0x18, 0x73, 0x46, 0xf9, 0x5b, 0x9f, 0x3d, 0xc0, 0x49, 0x53, 0xd5,
-       0x1d, 0x69, 0x4a, 0x80, 0x26, 0xbd, 0x8d, 0xa6, 0x04, 0xe8, 0x41, 0xcc,
-       0x3c, 0xc5, 0xde, 0xf1, 0xa8, 0x9c, 0x28, 0xf3, 0x9d, 0x26, 0xfe, 0x46,
-       0xd5, 0x90, 0x30, 0xb0, 0x65, 0xe4, 0x94, 0x19, 0x5f, 0x57, 0xbd, 0x1a,
-       0x73, 0xb8, 0x2e, 0x23, 0xa9, 0xba, 0xa8, 0xfc, 0x92, 0x38, 0x81, 0x7c,
-       0xf5, 0x86, 0xdb, 0x23, 0x6f, 0xfa, 0x7b, 0x5d, 0x14, 0x9e, 0x33, 0x6e,
-       0xdf, 0xeb, 0xc9, 0x4a, 0x2a, 0xf3, 0x8a, 0x15, 0xf2, 0xf9, 0xea, 0xc3,
-       0x5e, 0x7b, 0x30, 0x37, 0x95, 0x39, 0xdf, 0xd8, 0x69, 0xae, 0x83, 0xb9,
-       0x91, 0xb6, 0xb9, 0x0e, 0xe6, 0xf5, 0x20, 0xef, 0xf5, 0x28, 0x9e, 0x4a,
-       0xa0, 0xeb, 0x52, 0x99, 0x3c, 0xf1, 0x0c, 0x82, 0x7b, 0x1a, 0xc4, 0xc6,
-       0x53, 0xe2, 0x9f, 0xd9, 0xf2, 0xf7, 0x7a, 0x57, 0xf5, 0x6b, 0x94, 0x0d,
-       0x4c, 0x58, 0x3c, 0x9b, 0x99, 0xd1, 0xb2, 0xf5, 0x3c, 0x72, 0xd5, 0x8d,
-       0xc4, 0x43, 0x29, 0x1b, 0xb9, 0x92, 0xe7, 0x3c, 0x8d, 0x72, 0x81, 0xef,
-       0x3d, 0xc3, 0x2e, 0xde, 0x21, 0x5e, 0xbe, 0x31, 0xa4, 0xde, 0x43, 0x70,
-       0xfc, 0x73, 0x20, 0x31, 0x32, 0x63, 0x7c, 0xf7, 0xe0, 0x6e, 0xa9, 0x2f,
-       0x7f, 0x11, 0x63, 0x19, 0xe4, 0xc5, 0x43, 0x5a, 0xe6, 0xdc, 0x24, 0xae,
-       0x1f, 0xc2, 0x35, 0xe2, 0xf0, 0x72, 0x0e, 0xf7, 0x1f, 0xc2, 0xf5, 0xbc,
-       0x96, 0x6d, 0xe6, 0x70, 0xfd, 0x30, 0xae, 0x27, 0x48, 0x9b, 0xf3, 0x8a,
-       0x35, 0xa5, 0xd9, 0x58, 0xcb, 0x3e, 0x37, 0x89, 0x4f, 0xfb, 0x7a, 0xbc,
-       0x07, 0x3d, 0x95, 0x79, 0x3e, 0x96, 0x04, 0x4d, 0x0f, 0x6a, 0x4e, 0xbd,
-       0x1b, 0x6b, 0x0c, 0xe1, 0x79, 0xda, 0x54, 0xfb, 0x39, 0xd4, 0x6d, 0xaa,
-       0x67, 0x14, 0x4a, 0xa7, 0x81, 0x77, 0x1f, 0x41, 0xde, 0xd7, 0xc4, 0xb1,
-       0x1e, 0x97, 0x62, 0x2a, 0x2d, 0x0b, 0xf5, 0x90, 0x64, 0x63, 0x05, 0x7c,
-       0x2f, 0x48, 0x66, 0x1c, 0xf7, 0xeb, 0xb4, 0x05, 0xce, 0x2b, 0x49, 0xb1,
-       0x4a, 0xfc, 0xce, 0x7e, 0xd1, 0x57, 0xc0, 0x37, 0xfb, 0x44, 0x79, 0xc8,
-       0x20, 0x46, 0xfb, 0xdd, 0xa1, 0xa7, 0xe5, 0xbd, 0xd3, 0x8c, 0x7c, 0xac,
-       0x65, 0xea, 0xfe, 0x59, 0x9d, 0xc5, 0xdf, 0x2b, 0xb1, 0x47, 0x25, 0xc5,
-       0x50, 0x9a, 0x7d, 0x0e, 0xd5, 0x17, 0x4f, 0x79, 0x67, 0x7a, 0xed, 0xef,
-       0x90, 0x04, 0xfe, 0xc2, 0x7d, 0xbf, 0x82, 0xe7, 0xbd, 0xbe, 0x54, 0xb6,
-       0xf9, 0x41, 0x5d, 0xf0, 0x5d, 0xfd, 0x15, 0xe8, 0xe2, 0xfc, 0x87, 0xf6,
-       0xb9, 0xd8, 0xe3, 0x9a, 0x47, 0x2c, 0x62, 0x7f, 0x2c, 0x90, 0xdf, 0xd5,
-       0x34, 0x92, 0xbe, 0xc3, 0x58, 0x4b, 0x52, 0x8c, 0xb3, 0xb9, 0x58, 0x42,
-       0xd5, 0xbe, 0x1b, 0x4b, 0xf2, 0xc4, 0x16, 0xbd, 0xa4, 0x95, 0x72, 0x78,
-       0x04, 0xf5, 0x1a, 0x7f, 0xff, 0xf0, 0xb8, 0xe4, 0x53, 0xec, 0xd1, 0x84,
-       0x90, 0x0b, 0x0b, 0xf8, 0xbe, 0x25, 0xb7, 0x92, 0x2f, 0xb7, 0x7c, 0xf5,
-       0x5b, 0x4a, 0x77, 0x35, 0x8b, 0xfb, 0x05, 0xbd, 0x8b, 0x69, 0xa5, 0xb3,
-       0x9a, 0x7a, 0xcf, 0x36, 0xe0, 0x3d, 0xe8, 0xbf, 0xed, 0x6c, 0x73, 0x93,
-       0x16, 0x69, 0xfb, 0x38, 0xdf, 0x5b, 0x18, 0xb6, 0x85, 0xf4, 0x93, 0x0f,
-       0xe6, 0xac, 0xe0, 0x5c, 0x34, 0xe0, 0x21, 0xe0, 0xf3, 0xa3, 0xca, 0x85,
-       0x74, 0xee, 0x31, 0xa4, 0x7b, 0xca, 0x08, 0x59, 0xcc, 0x01, 0x9f, 0xf6,
-       0xfb, 0xf8, 0xff, 0x37, 0xe5, 0xea, 0xf1, 0x1e, 0x86, 0xa8, 0xfc, 0xdf,
-       0x8b, 0xee, 0xa0, 0xf7, 0xab, 0xcf, 0x80, 0x0d, 0xe7, 0xac, 0xb5, 0xc5,
-       0x67, 0x6d, 0x07, 0x3e, 0x6b, 0x3e, 0x9f, 0x1f, 0x7e, 0x4e, 0xea, 0xd1,
-       0x59, 0x5b, 0xb2, 0xc1, 0x23, 0x6d, 0x6a, 0x27, 0x7b, 0xe3, 0x6f, 0x9c,
-       0xd4, 0xef, 0xad, 0xa2, 0xb6, 0x7b, 0xad, 0x5e, 0x27, 0xeb, 0x64, 0xcf,
-       0xee, 0xce, 0x22, 0xd7, 0x55, 0xab, 0x5e, 0xcd, 0x5c, 0x75, 0xd9, 0x6b,
-       0xde, 0x69, 0x6f, 0x0d, 0x34, 0xff, 0x8e, 0x7a, 0xef, 0xa4, 0xe4, 0x7a,
-       0x7d, 0xa9, 0x6a, 0xb5, 0x3d, 0x57, 0xde, 0xc0, 0x3c, 0x39, 0x5c, 0x90,
-       0x19, 0xe8, 0x31, 0x89, 0xeb, 0x9b, 0xe5, 0xe5, 0x65, 0x75, 0x86, 0xe4,
-       0x9f, 0xd5, 0xf0, 0x0c, 0x46, 0x9d, 0x43, 0x23, 0x5e, 0xcd, 0xaa, 0x78,
-       0xbd, 0xb1, 0xac, 0xee, 0xa9, 0xdf, 0x3c, 0xd4, 0xdd, 0x19, 0xc4, 0x73,
-       0xd4, 0x06, 0xd6, 0x6e, 0x29, 0xa2, 0x86, 0x3e, 0x6b, 0xcd, 0x18, 0xc4,
-       0x29, 0x5c, 0x6b, 0x03, 0x6b, 0x9d, 0x5f, 0x96, 0xbd, 0x7c, 0xa7, 0xa3,
-       0xaa, 0xce, 0xbd, 0xbc, 0x7e, 0xf5, 0xbc, 0x04, 0xbf, 0xd7, 0x8d, 0xfa,
-       0x39, 0x8e, 0xef, 0x95, 0xf0, 0xb7, 0xa7, 0x8c, 0x01, 0xa8, 0x6b, 0x66,
-       0x0a, 0x58, 0xaf, 0xd5, 0xf2, 0xfa, 0xd9, 0x2d, 0xd8, 0x7d, 0x84, 0xbf,
-       0x65, 0xc0, 0xdf, 0x23, 0xb0, 0x13, 0xf8, 0xc1, 0xe6, 0x38, 0xaf, 0x59,
-       0x4b, 0x04, 0xd7, 0x4c, 0x58, 0xff, 0x1b, 0xed, 0xcc, 0xfa, 0xa1, 0x98,
-       0x41, 0x00, 0x00, 0x00 };
-static u32 bnx2_TXP_b09FwData[(0xd0/4) + 1] = {
+       0x1f, 0x8b, 0x08, 0x00, 0x0e, 0x34, 0xe7, 0x45, 0x00, 0x03, 0xcd, 0x7c,
+       0x6f, 0x70, 0x5b, 0xd7, 0x95, 0xdf, 0x79, 0xef, 0x81, 0x24, 0x48, 0xd1,
+       0xd4, 0x13, 0x17, 0x56, 0x60, 0x87, 0x71, 0x00, 0xf1, 0x81, 0x66, 0x42,
+       0xae, 0x04, 0x2b, 0x4c, 0xc2, 0x6d, 0xd1, 0xf8, 0x05, 0x00, 0x29, 0x48,
+       0xd1, 0x6c, 0x68, 0x95, 0x49, 0x94, 0x54, 0xe3, 0x62, 0x41, 0x52, 0xf1,
+       0xb6, 0xce, 0x54, 0x9b, 0x78, 0x5a, 0x4d, 0xeb, 0xad, 0x11, 0x90, 0xfa,
+       0xe7, 0x85, 0x04, 0xda, 0x62, 0x44, 0x7f, 0xc8, 0x07, 0x18, 0x80, 0x24,
+       0x6f, 0xf2, 0x44, 0x28, 0x9b, 0x7f, 0xfd, 0xd0, 0xac, 0x50, 0x4a, 0xd6,
+       0xba, 0x9b, 0xb4, 0xa3, 0xed, 0x66, 0x67, 0x3b, 0xd3, 0x2f, 0x1c, 0x49,
+       0xf6, 0x7a, 0x77, 0x67, 0x36, 0xda, 0x6e, 0xb6, 0xab, 0xb6, 0xb2, 0xd1,
+       0xdf, 0xef, 0xbe, 0xf7, 0x28, 0x90, 0xa6, 0x6c, 0xcb, 0xb3, 0xed, 0x94,
+       0x33, 0x18, 0xe0, 0xdd, 0x77, 0xdf, 0xb9, 0xe7, 0x9e, 0x73, 0xee, 0x39,
+       0xe7, 0x77, 0xee, 0x7d, 0x0c, 0x8b, 0x74, 0x89, 0xf7, 0xf7, 0x00, 0x3e,
+       0x91, 0x43, 0x87, 0x9f, 0xd9, 0x3e, 0xb2, 0xfd, 0x13, 0xf8, 0xf9, 0x09,
+       0x31, 0x02, 0x06, 0x6f, 0xbe, 0x69, 0x88, 0x64, 0xff, 0x42, 0x3e, 0xf0,
+       0x1f, 0x1e, 0x37, 0x7d, 0xfa, 0xfc, 0x48, 0x50, 0x4f, 0x4c, 0xec, 0x4a,
+       0x5a, 0x12, 0x34, 0x12, 0xb2, 0x6f, 0xca, 0x12, 0xb1, 0x9d, 0xa1, 0x48,
+       0x4a, 0xde, 0x6a, 0xe6, 0x43, 0x01, 0x61, 0xfb, 0x47, 0x12, 0x77, 0x9e,
+       0xfb, 0xc9, 0xa7, 0xa3, 0xb7, 0xca, 0x86, 0x04, 0xcd, 0x44, 0x56, 0xcc,
+       0x01, 0x09, 0xf6, 0xe1, 0x99, 0x6f, 0x3f, 0x6a, 0x18, 0xd2, 0xb3, 0xca,
+       0xab, 0xcc, 0x95, 0x56, 0x9a, 0x3f, 0x79, 0x34, 0x2c, 0xbf, 0x57, 0x0f,
+       0xc9, 0xf7, 0xea, 0xa6, 0x5c, 0xac, 0x07, 0xb4, 0xf1, 0x92, 0x29, 0xb3,
+       0xa5, 0x69, 0xfd, 0x48, 0x31, 0x2f, 0xa9, 0x7a, 0x56, 0x2f, 0x2c, 0x98,
+       0x3d, 0xc9, 0xf3, 0x39, 0x7d, 0x76, 0xa1, 0xb7, 0x27, 0x75, 0x7e, 0x5a,
+       0x2f, 0x14, 0xc3, 0x3d, 0xc9, 0xba, 0xd9, 0x93, 0x5a, 0x0c, 0xe1, 0xba,
+       0xb7, 0x27, 0xb9, 0x18, 0x9d, 0x17, 0xd9, 0x8a, 0x3e, 0xe1, 0x9e, 0x54,
+       0x29, 0x9a, 0x15, 0xe9, 0x8f, 0xbf, 0x2a, 0x7d, 0x3d, 0xa9, 0xfa, 0x3f,
+       0xd1, 0x1b, 0xa6, 0x26, 0x85, 0x5f, 0x15, 0x33, 0x9c, 0xb8, 0xd5, 0x7c,
+       0xc8, 0xd2, 0xc4, 0xb4, 0x6e, 0x37, 0xb7, 0x58, 0x41, 0xc9, 0x9d, 0xee,
+       0x14, 0x5b, 0xcd, 0xc9, 0x94, 0xdc, 0xe2, 0x90, 0xb9, 0x2c, 0x6d, 0x62,
+       0x87, 0xfc, 0xeb, 0x66, 0x33, 0x19, 0xff, 0x32, 0xe5, 0x8a, 0x71, 0xa4,
+       0x67, 0xbc, 0x2e, 0x92, 0x2c, 0x05, 0x25, 0x19, 0x7f, 0xab, 0xe9, 0x3e,
+       0x13, 0xc4, 0x98, 0x81, 0x9e, 0xb1, 0x52, 0xb3, 0x99, 0x8e, 0x83, 0x7e,
+       0xdc, 0x7f, 0xb6, 0x4d, 0xca, 0x21, 0xbb, 0x3c, 0x1b, 0xff, 0x6f, 0xba,
+       0xab, 0x13, 0xce, 0x91, 0xd7, 0xb6, 0xe8, 0x56, 0x5e, 0x72, 0x21, 0x29,
+       0x17, 0xe2, 0x9f, 0x92, 0x13, 0xf1, 0x30, 0xe6, 0x17, 0x94, 0x63, 0x71,
+       0xc8, 0xd1, 0x3a, 0xac, 0x25, 0xeb, 0xd1, 0x48, 0x56, 0x9e, 0x97, 0xe4,
+       0x62, 0xbf, 0x99, 0x16, 0x8c, 0x6d, 0x35, 0x3f, 0x9a, 0x8c, 0x63, 0xbc,
+       0xe1, 0xff, 0xd5, 0xb4, 0x43, 0xd1, 0x6c, 0x59, 0x06, 0xa5, 0x50, 0xea,
+       0x8f, 0xff, 0x4c, 0x34, 0x09, 0x5a, 0x62, 0x4f, 0x59, 0x26, 0xe4, 0x16,
+       0x1d, 0x4c, 0x19, 0x4d, 0xd9, 0x83, 0xf1, 0x93, 0x16, 0xee, 0xd7, 0x65,
+       0xb3, 0x6e, 0xb5, 0x4b, 0xc1, 0x94, 0x50, 0x97, 0x3c, 0x22, 0x85, 0xd3,
+       0x68, 0x8f, 0xdb, 0xbd, 0x3a, 0x9e, 0xc9, 0x8c, 0xb0, 0x4d, 0x34, 0x23,
+       0x11, 0x33, 0x53, 0xe0, 0xa8, 0xe2, 0x0c, 0x62, 0xfc, 0x98, 0xdd, 0xa9,
+       0x99, 0xb2, 0x62, 0x06, 0xa4, 0xea, 0xc4, 0xec, 0xb0, 0xd6, 0x2e, 0xc7,
+       0x62, 0x5d, 0x90, 0x69, 0x18, 0xb4, 0xe5, 0x9b, 0x7a, 0x22, 0x16, 0xce,
+       0x41, 0x51, 0x3a, 0x64, 0x35, 0x07, 0x7e, 0xe6, 0xe2, 0x59, 0x2d, 0x55,
+       0xff, 0x8a, 0x96, 0x3c, 0xbf, 0x5f, 0xdb, 0x75, 0x1e, 0x7d, 0xea, 0xe7,
+       0x3c, 0xbb, 0x0b, 0x83, 0x37, 0x1d, 0xcf, 0xb2, 0x1d, 0x3c, 0x2b, 0xde,
+       0xd1, 0x06, 0x5d, 0x36, 0x26, 0x43, 0x3d, 0x49, 0xa5, 0x4b, 0xf2, 0xa6,
+       0x4b, 0x6e, 0x42, 0x93, 0x5e, 0xcb, 0x96, 0xe0, 0x27, 0xa1, 0xcf, 0x45,
+       0xe8, 0x72, 0x31, 0x22, 0x47, 0x4a, 0x12, 0xd2, 0x85, 0x63, 0x65, 0xf5,
+       0xaa, 0x43, 0x7b, 0x80, 0x6e, 0xa1, 0xfb, 0x82, 0xc3, 0x67, 0xa1, 0xc3,
+       0x52, 0x1a, 0xf2, 0xc9, 0x60, 0xec, 0x7d, 0xda, 0x9e, 0xea, 0xa4, 0x96,
+       0x81, 0x9d, 0x14, 0x4e, 0x0f, 0x41, 0x77, 0xd1, 0xc8, 0x8a, 0x6c, 0x96,
+       0x82, 0x65, 0x45, 0xbe, 0x2c, 0xdd, 0x72, 0x6c, 0xd1, 0x92, 0x23, 0x8b,
+       0x21, 0xc9, 0x9b, 0x51, 0xb3, 0x26, 0x7d, 0xd9, 0x4d, 0x89, 0x1e, 0x79,
+       0xfe, 0x74, 0x34, 0x53, 0x96, 0x7e, 0xfb, 0x75, 0xdc, 0xcf, 0x9d, 0xa4,
+       0x4e, 0x25, 0x9f, 0x8a, 0x1b, 0x92, 0x85, 0x4d, 0x18, 0xd6, 0x1f, 0x81,
+       0xff, 0xe6, 0x73, 0xc9, 0x78, 0x34, 0x2c, 0xa2, 0x4b, 0xea, 0x0b, 0xfd,
+       0xe6, 0x6e, 0x89, 0x9a, 0x19, 0xca, 0x3f, 0x3e, 0x04, 0x3d, 0xfc, 0x77,
+       0xca, 0x1e, 0xb4, 0xa8, 0xe3, 0xa1, 0xf0, 0x31, 0xe8, 0x32, 0xab, 0x74,
+       0xdc, 0x83, 0xf1, 0x03, 0x9e, 0xed, 0xf4, 0x48, 0xbe, 0x7a, 0xc3, 0x93,
+       0x43, 0x8f, 0xcc, 0x57, 0xbb, 0xa5, 0x00, 0x1d, 0x16, 0xc4, 0x92, 0xc2,
+       0xf9, 0x3f, 0xf7, 0xda, 0x2d, 0x99, 0x3b, 0xff, 0x32, 0xec, 0xe1, 0xb0,
+       0xb6, 0xbf, 0xfe, 0x0b, 0xcd, 0xb3, 0x1f, 0xd8, 0x5f, 0x50, 0xec, 0x89,
+       0xa0, 0x9c, 0xab, 0xbb, 0xf6, 0x57, 0xc1, 0x1a, 0xb3, 0x4d, 0x1b, 0xb6,
+       0xf4, 0xc6, 0x6a, 0x9f, 0x73, 0xf5, 0x3e, 0x3c, 0x1b, 0x94, 0x23, 0x75,
+       0xf6, 0xcf, 0xc3, 0xc6, 0x82, 0xb2, 0xf4, 0x68, 0xb7, 0x64, 0xd1, 0x5e,
+       0x58, 0x14, 0x3b, 0x19, 0xd7, 0xf1, 0x4c, 0x0f, 0xe6, 0xb2, 0x15, 0x9f,
+       0x2e, 0x99, 0xaa, 0x76, 0xd8, 0x86, 0x15, 0x92, 0xa9, 0x3a, 0xf5, 0x8f,
+       0xef, 0x92, 0x6f, 0x03, 0x94, 0x2f, 0xdb, 0xf9, 0x1c, 0xdb, 0x4d, 0xb4,
+       0xb7, 0xb6, 0xd1, 0xb6, 0x37, 0x53, 0xa6, 0x83, 0x82, 0xb6, 0x5c, 0x29,
+       0x66, 0xee, 0xe7, 0x77, 0x9d, 0xf6, 0xd0, 0x6a, 0x0b, 0x01, 0xf4, 0x87,
+       0x1e, 0xab, 0x18, 0xeb, 0xf4, 0x9d, 0x66, 0xdb, 0x08, 0xae, 0x2d, 0x2c,
+       0xaa, 0x2e, 0x8e, 0x1d, 0x00, 0x5f, 0xba, 0x64, 0xab, 0x8a, 0xb7, 0x08,
+       0x6d, 0xc0, 0x9d, 0x47, 0x9f, 0xcc, 0x2e, 0x76, 0xf7, 0xa4, 0x17, 0xd9,
+       0x9e, 0x0c, 0x1b, 0x98, 0xe7, 0x54, 0x5c, 0x1a, 0x73, 0x71, 0xbd, 0x3f,
+       0x00, 0xbe, 0xa6, 0xb1, 0xe0, 0x30, 0x0f, 0x8f, 0xc7, 0x06, 0xee, 0xf7,
+       0xca, 0xd4, 0x79, 0xf6, 0xe5, 0x18, 0x85, 0x2d, 0xba, 0x24, 0xc0, 0x1b,
+       0x3e, 0x56, 0x14, 0xf7, 0x3b, 0x31, 0x4e, 0x37, 0x6c, 0x27, 0x83, 0x31,
+       0x9b, 0x8f, 0x27, 0xe3, 0xbd, 0x92, 0x5d, 0xed, 0x2b, 0xb0, 0x3b, 0xf6,
+       0x1f, 0x5c, 0xd7, 0x17, 0xf2, 0x3d, 0x0f, 0x9a, 0x8b, 0x9d, 0x90, 0x21,
+       0xdb, 0x75, 0xf0, 0xdc, 0x01, 0x1e, 0x82, 0x98, 0x4f, 0x3f, 0xd6, 0x43,
+       0x07, 0xe8, 0x6f, 0xc2, 0x9c, 0x3a, 0x65, 0xfa, 0x74, 0x2f, 0x74, 0x61,
+       0xa2, 0x6f, 0x50, 0x9e, 0x2f, 0x45, 0x61, 0x03, 0xec, 0x0f, 0x1d, 0x2c,
+       0x46, 0xc3, 0x55, 0xb1, 0x65, 0x2e, 0xde, 0x01, 0xfb, 0x6a, 0x36, 0x67,
+       0x60, 0x1f, 0xdf, 0x51, 0xfe, 0x62, 0xc8, 0x1c, 0xd3, 0x24, 0xdf, 0x91,
+       0x38, 0x0c, 0x7e, 0xa2, 0x4f, 0x89, 0xf0, 0x7a, 0x87, 0xc6, 0x35, 0x0b,
+       0x39, 0x72, 0x6c, 0xf8, 0xa4, 0xad, 0x90, 0x21, 0xfd, 0x56, 0x1f, 0xec,
+       0x39, 0xac, 0xfc, 0xc9, 0xd8, 0x86, 0xfe, 0x24, 0x3a, 0x51, 0xc6, 0x58,
+       0x85, 0xf3, 0x01, 0xfa, 0xb0, 0x51, 0x2c, 0x57, 0x79, 0x00, 0x6b, 0x6f,
+       0x56, 0xd9, 0xc7, 0x09, 0xce, 0xb7, 0xf9, 0xf9, 0x38, 0xf9, 0xe2, 0x7c,
+       0x6d, 0x3c, 0x4b, 0x1b, 0x8c, 0x1e, 0xb6, 0xd5, 0xf8, 0x27, 0xbc, 0xf1,
+       0x5d, 0xde, 0x0b, 0xa5, 0x1e, 0x2d, 0xa5, 0x78, 0xf0, 0xe9, 0x88, 0x2c,
+       0x9f, 0xec, 0x37, 0xf7, 0xc0, 0x86, 0xe9, 0xa7, 0x96, 0x2f, 0x50, 0xc7,
+       0xa0, 0x31, 0x42, 0x1d, 0x9b, 0x8a, 0xbf, 0xe4, 0x22, 0xd7, 0x9e, 0xf4,
+       0x19, 0x42, 0x1f, 0x01, 0x9f, 0x8b, 0xb5, 0x38, 0xeb, 0xad, 0xc5, 0x9c,
+       0x43, 0xfb, 0x7b, 0x06, 0xcf, 0xea, 0x32, 0x16, 0xa3, 0x7f, 0x78, 0x5e,
+       0x52, 0xf0, 0x91, 0xd0, 0xa3, 0x54, 0x31, 0x97, 0x4a, 0xa9, 0xd5, 0x6f,
+       0xc1, 0xb6, 0x86, 0xff, 0xae, 0xe9, 0xfa, 0x43, 0xfa, 0x06, 0xfa, 0x9a,
+       0x82, 0xa9, 0x43, 0x72, 0x3a, 0x9c, 0x21, 0x74, 0x13, 0x4f, 0x1a, 0xd1,
+       0x4c, 0x16, 0x7c, 0x4d, 0x59, 0x4d, 0xb1, 0x1e, 0x13, 0x44, 0x0c, 0xf4,
+       0xa9, 0xcb, 0x4e, 0xdf, 0x3f, 0x2d, 0x3b, 0xbe, 0x2e, 0xa8, 0x57, 0xea,
+       0xc1, 0xf7, 0x11, 0x01, 0xb9, 0x0c, 0xdf, 0x35, 0x57, 0xea, 0x96, 0x06,
+       0x78, 0xba, 0xe2, 0xf8, 0xb6, 0x66, 0x78, 0xb6, 0xc6, 0x67, 0xba, 0xf1,
+       0x7c, 0x00, 0x7e, 0x4d, 0xf2, 0x46, 0x02, 0xbf, 0x8b, 0xa4, 0xc9, 0x36,
+       0xdf, 0xce, 0xb9, 0x66, 0xa2, 0x76, 0x59, 0xda, 0x25, 0x13, 0x43, 0xfc,
+       0x58, 0xd4, 0x31, 0x56, 0x1f, 0x7c, 0x79, 0x40, 0x0e, 0x96, 0x42, 0xf2,
+       0xd5, 0x12, 0xe7, 0x95, 0xd6, 0x52, 0xd0, 0x5b, 0x72, 0xb1, 0x09, 0x9d,
+       0x8f, 0xc3, 0xe7, 0x65, 0xb4, 0x31, 0xf8, 0x9f, 0xdd, 0xd5, 0xaf, 0x68,
+       0xe9, 0xf3, 0x59, 0x6d, 0xbc, 0xbe, 0x5f, 0xcb, 0x9c, 0x9f, 0xd4, 0x76,
+       0xb5, 0xf8, 0x22, 0xd1, 0xde, 0xdd, 0x17, 0x9d, 0x38, 0xcd, 0x31, 0xfb,
+       0xe3, 0x1b, 0xfb, 0xa2, 0x5f, 0x6a, 0xad, 0xbe, 0xa8, 0x1f, 0xbe, 0x28,
+       0x03, 0x5f, 0x34, 0x7e, 0xdf, 0xbe, 0xa8, 0x5d, 0xdf, 0xd8, 0x17, 0x75,
+       0xeb, 0x77, 0x7d, 0x11, 0x63, 0xcf, 0xbf, 0xc6, 0xb5, 0x29, 0xdb, 0x76,
+       0xfa, 0x72, 0x0e, 0xc3, 0x0f, 0x6f, 0x82, 0xac, 0xbb, 0xb8, 0x76, 0x22,
+       0x05, 0xd8, 0xfd, 0x34, 0xc6, 0xfa, 0x4d, 0xd8, 0xfb, 0xb6, 0x98, 0x65,
+       0x3e, 0xa1, 0xc6, 0x7d, 0xa7, 0xce, 0xc7, 0x56, 0x75, 0x4e, 0x1e, 0xdf,
+       0x53, 0xe7, 0xb6, 0xab, 0x73, 0xea, 0xba, 0x53, 0x66, 0xd4, 0xb8, 0x4d,
+       0x09, 0x3c, 0x26, 0xf0, 0x2a, 0xf2, 0x59, 0x23, 0x11, 0x05, 0x3d, 0x1d,
+       0xe3, 0x53, 0x5f, 0x31, 0xf0, 0x20, 0xd0, 0x6f, 0xb7, 0xf2, 0x45, 0xbb,
+       0xa0, 0xf7, 0x65, 0xe7, 0xfe, 0x74, 0x95, 0x69, 0xd1, 0xd5, 0x9e, 0x35,
+       0xba, 0xea, 0x90, 0xe1, 0x98, 0xaf, 0xa3, 0xcd, 0x92, 0x8c, 0x51, 0x67,
+       0xf7, 0xa3, 0xab, 0x7f, 0xaa, 0xff, 0xfd, 0xe8, 0xea, 0xb7, 0xee, 0xa1,
+       0xab, 0x7f, 0xb5, 0x4e, 0x57, 0x96, 0xf9, 0x82, 0x46, 0xda, 0x8c, 0x1f,
+       0xf4, 0x47, 0xcd, 0x8f, 0x4e, 0x31, 0x7f, 0xa8, 0x73, 0x4d, 0xfb, 0x79,
+       0x07, 0xd7, 0xf3, 0xa5, 0xa6, 0x61, 0x59, 0x90, 0x1d, 0xd7, 0x34, 0xe5,
+       0x16, 0x35, 0x3f, 0x4f, 0xfe, 0x11, 0x3b, 0xa6, 0x10, 0x6b, 0x5c, 0x1e,
+       0xda, 0xa5, 0xbc, 0xc5, 0xed, 0x3f, 0x55, 0x6a, 0xfe, 0x42, 0x4f, 0xbc,
+       0xdd, 0x4c, 0x8e, 0x58, 0x5e, 0x1c, 0x08, 0xca, 0xd7, 0xaa, 0xd1, 0xac,
+       0xad, 0x75, 0x4b, 0xfe, 0x41, 0xc4, 0x9e, 0x12, 0xfd, 0xd7, 0xd6, 0x7b,
+       0xc4, 0xe8, 0x3e, 0x2f, 0x46, 0x57, 0xc1, 0x2b, 0xf3, 0xab, 0xef, 0xbe,
+       0xd5, 0x08, 0xf1, 0x3b, 0x66, 0xee, 0x93, 0x2f, 0x73, 0x8e, 0x88, 0xf7,
+       0x8c, 0xfb, 0x16, 0x73, 0x9e, 0x7c, 0x20, 0xd1, 0x25, 0xf9, 0x2d, 0x5c,
+       0x8f, 0xf4, 0x73, 0xf4, 0x5d, 0xed, 0x1e, 0xdf, 0x7e, 0x8e, 0xa4, 0x78,
+       0x33, 0x30, 0x65, 0xf4, 0x41, 0x3e, 0x54, 0xe2, 0x3c, 0xde, 0xf2, 0xec,
+       0x89, 0xb9, 0x82, 0xb4, 0xb9, 0xbe, 0x61, 0x2f, 0x72, 0x01, 0xda, 0x81,
+       0xaf, 0x73, 0xea, 0x9b, 0x39, 0x82, 0x44, 0x74, 0x8b, 0x39, 0x82, 0x98,
+       0x46, 0x62, 0x9f, 0x66, 0x43, 0xf7, 0x36, 0x74, 0x6f, 0x43, 0xf7, 0x36,
+       0x74, 0x9f, 0xac, 0x1f, 0xc6, 0x3d, 0x95, 0x87, 0x80, 0x17, 0x97, 0x7e,
+       0xda, 0xa5, 0x0f, 0x3e, 0xb7, 0x4a, 0x4e, 0xe9, 0x84, 0xf3, 0x45, 0xae,
+       0xa1, 0xfc, 0xf5, 0xb8, 0xe6, 0xfa, 0x6b, 0xd2, 0xcb, 0xe0, 0xf9, 0xdb,
+       0x98, 0xa7, 0xad, 0xeb, 0xd6, 0x5d, 0x99, 0xcc, 0xb5, 0xc8, 0x64, 0xd6,
+       0xa1, 0x8c, 0xd8, 0x9f, 0x3e, 0x77, 0x5a, 0xaf, 0xac, 0xca, 0x65, 0x2f,
+       0x78, 0xe8, 0xe0, 0xdc, 0xbd, 0x79, 0x90, 0x7e, 0xaf, 0x47, 0xff, 0x6f,
+       0xd1, 0x87, 0xfe, 0x75, 0xa3, 0x71, 0x39, 0x26, 0x73, 0xc6, 0x77, 0x9b,
+       0x0f, 0x72, 0x66, 0xac, 0x81, 0xef, 0x21, 0x96, 0x5f, 0x44, 0x2c, 0x59,
+       0x31, 0x22, 0xf2, 0x93, 0x47, 0xaf, 0x21, 0x97, 0x96, 0xfc, 0xc3, 0x89,
+       0x66, 0x24, 0x90, 0x78, 0xab, 0x39, 0x37, 0x82, 0x18, 0x97, 0x88, 0x86,
+       0x93, 0xc6, 0xb0, 0x5c, 0xaa, 0x0f, 0xca, 0x8f, 0xea, 0x96, 0xfc, 0xb0,
+       0x1e, 0x91, 0x1f, 0x20, 0xe6, 0x7f, 0xbf, 0xde, 0x9a, 0x73, 0x47, 0x68,
+       0x4f, 0x3d, 0xe9, 0xfa, 0x46, 0xb9, 0x7f, 0x13, 0x34, 0xde, 0x82, 0x9d,
+       0x04, 0xb2, 0xc8, 0xf5, 0x19, 0xbf, 0x26, 0x0e, 0x15, 0x9f, 0x6b, 0x82,
+       0xb7, 0x6c, 0x5b, 0xc2, 0xca, 0xeb, 0x7a, 0xf7, 0xa8, 0xf9, 0x29, 0xb4,
+       0x39, 0xa3, 0x81, 0x6a, 0xb1, 0x53, 0xe5, 0x8b, 0xd0, 0x91, 0xd8, 0xf5,
+       0x60, 0xb0, 0x56, 0xbc, 0x85, 0x7e, 0xcd, 0xe6, 0xa1, 0xf8, 0x6f, 0xed,
+       0x30, 0xff, 0x81, 0x85, 0x35, 0xdd, 0xf9, 0x25, 0x23, 0xb1, 0x49, 0x66,
+       0x43, 0xdf, 0x6f, 0x98, 0x03, 0x7d, 0x59, 0x3d, 0x11, 0x94, 0x74, 0x91,
+       0x6b, 0x2a, 0x24, 0xb3, 0x55, 0x28, 0xff, 0x3c, 0xd7, 0x85, 0x3c, 0x3b,
+       0x17, 0xef, 0x86, 0xed, 0xff, 0x9a, 0xe1, 0xae, 0x03, 0x18, 0x50, 0x75,
+       0x50, 0xf2, 0xe0, 0x37, 0x5f, 0x7f, 0xcb, 0xc3, 0x0e, 0xf0, 0x2a, 0x5b,
+       0x21, 0xf8, 0xc4, 0x70, 0xda, 0x76, 0xfe, 0x30, 0x88, 0xb6, 0xe0, 0x56,
+       0xeb, 0xce, 0x26, 0x7c, 0x3f, 0x10, 0xb2, 0x88, 0x4d, 0x24, 0xf3, 0x05,
+       0x7c, 0xff, 0x4a, 0x42, 0x36, 0xf7, 0xe2, 0x7b, 0x4b, 0x02, 0x26, 0x99,
+       0x60, 0xcc, 0xd5, 0x5a, 0x62, 0xae, 0x68, 0x69, 0xc8, 0x6e, 0x0e, 0x73,
+       0x4f, 0x43, 0x9e, 0x5f, 0xac, 0x07, 0xb5, 0xd4, 0xe9, 0x47, 0xc0, 0x87,
+       0x9f, 0x3b, 0x23, 0x3f, 0x33, 0x97, 0xb7, 0x04, 0xe4, 0x16, 0x7c, 0x5c,
+       0x12, 0x7e, 0xcc, 0x46, 0x6e, 0xb1, 0x03, 0xcb, 0x35, 0xfa, 0x5f, 0xbf,
+       0x20, 0x5f, 0xf3, 0x78, 0x6b, 0x93, 0x05, 0x65, 0xa3, 0x6c, 0xcf, 0x67,
+       0xfe, 0xcd, 0xc0, 0xdd, 0xf6, 0x17, 0x57, 0xdb, 0xcb, 0x99, 0x7f, 0xb8,
+       0xda, 0xde, 0xdb, 0xe6, 0xf2, 0x3f, 0xaa, 0x4d, 0xd4, 0xf7, 0x78, 0x6d,
+       0xb7, 0xa1, 0xb3, 0x66, 0x93, 0xb9, 0x45, 0x01, 0xd8, 0x24, 0x1d, 0xa7,
+       0x2f, 0xbe, 0x1f, 0x5f, 0xbb, 0xc6, 0xcf, 0x9a, 0x49, 0x83, 0xb6, 0x10,
+       0x14, 0x97, 0x26, 0xef, 0x77, 0x20, 0x7f, 0xbf, 0x8d, 0xdf, 0x8c, 0xa3,
+       0x7e, 0x6e, 0xce, 0x3e, 0x7c, 0xfe, 0xcd, 0x7b, 0xd8, 0x4b, 0x08, 0xf6,
+       0xf2, 0xff, 0xab, 0x5d, 0x5c, 0xba, 0x1f, 0xbb, 0xc0, 0x9f, 0xb2, 0x0b,
+       0xd5, 0xff, 0xd2, 0xea, 0x5a, 0x09, 0x43, 0x3e, 0x8c, 0x07, 0x83, 0xd0,
+       0xf1, 0x66, 0x99, 0xb5, 0xc8, 0x8f, 0x15, 0xc9, 0xc1, 0x5f, 0x9e, 0x58,
+       0x17, 0xbb, 0xbb, 0x10, 0x0f, 0x8e, 0x9f, 0x8e, 0x8e, 0x32, 0x1e, 0xc4,
+       0xe0, 0x1b, 0x93, 0xef, 0x88, 0x07, 0x37, 0x8c, 0xd6, 0x78, 0x60, 0x20,
+       0x1e, 0xec, 0x7a, 0x97, 0x78, 0x70, 0xe2, 0x1d, 0xf1, 0x40, 0x83, 0x6c,
+       0x38, 0xbf, 0xbf, 0x35, 0xfc, 0x78, 0x50, 0x58, 0x13, 0x0f, 0x7c, 0x5d,
+       0x59, 0x0a, 0x0b, 0xdc, 0xd5, 0x5b, 0x97, 0xa7, 0x2b, 0x09, 0x06, 0x12,
+       0x8d, 0xcc, 0x9c, 0xf5, 0xb0, 0xb4, 0xc1, 0xe7, 0x5e, 0xaa, 0x8f, 0x40,
+       0x67, 0x97, 0x30, 0xf7, 0x68, 0x9c, 0x89, 0x65, 0x5b, 0x82, 0xeb, 0xe1,
+       0xcd, 0x08, 0x30, 0xe2, 0x6e, 0xe0, 0xbe, 0xdd, 0x67, 0xd5, 0xfa, 0x78,
+       0x33, 0xea, 0x61, 0xf7, 0x6d, 0xc0, 0xee, 0x78, 0x3e, 0x00, 0x4c, 0xc8,
+       0xf6, 0x2b, 0x66, 0x12, 0x7a, 0xaa, 0x3a, 0xf6, 0xee, 0x02, 0x3e, 0x73,
+       0xaa, 0xef, 0xad, 0x08, 0xfb, 0x76, 0x24, 0x12, 0xd1, 0x3f, 0xc3, 0x77,
+       0x7b, 0x22, 0xbc, 0xed, 0xaa, 0x45, 0xba, 0x87, 0xa2, 0x67, 0x15, 0x8d,
+       0x80, 0x14, 0xd4, 0xb3, 0x91, 0x6d, 0x7c, 0xf6, 0x18, 0x62, 0xf6, 0x51,
+       0xc7, 0x94, 0x23, 0x4e, 0x76, 0x77, 0x0e, 0x1f, 0x62, 0xd5, 0x4b, 0x25,
+       0xde, 0x1f, 0xc5, 0xfd, 0x80, 0x30, 0x97, 0xfc, 0x2a, 0xfa, 0x1c, 0x44,
+       0x9f, 0x19, 0xc7, 0xd7, 0x05, 0xef, 0x37, 0x32, 0x29, 0xdc, 0x9f, 0x29,
+       0x36, 0x32, 0xe9, 0x22, 0xf3, 0xd6, 0xa1, 0xf0, 0x11, 0xc8, 0x33, 0x8b,
+       0x5c, 0xcd, 0x96, 0xe8, 0x60, 0x5e, 0x9e, 0xee, 0x1c, 0x07, 0x4e, 0x3a,
+       0x87, 0x1c, 0xc2, 0x9e, 0x8c, 0xc6, 0xcb, 0xf2, 0xe1, 0xce, 0xe4, 0x69,
+       0xe4, 0x0b, 0xf1, 0xed, 0x90, 0x61, 0x23, 0xa3, 0xc7, 0x04, 0xb6, 0x1e,
+       0x87, 0x5f, 0x1e, 0xd1, 0x53, 0xc5, 0x7e, 0x73, 0x56, 0x1e, 0x95, 0x86,
+       0x19, 0x0d, 0x8f, 0xcb, 0x26, 0x49, 0x05, 0xd0, 0x6f, 0xf0, 0x43, 0x92,
+       0x0d, 0x53, 0xd6, 0x0f, 0xc2, 0xdf, 0x6b, 0xd2, 0x61, 0xb5, 0xc6, 0x9e,
+       0x5b, 0x10, 0x6f, 0x2e, 0x40, 0x9f, 0xdd, 0x61, 0x75, 0x7a, 0x3a, 0xd9,
+       0x24, 0xcb, 0xef, 0xe8, 0x77, 0xbb, 0xa5, 0x5f, 0x6b, 0xfb, 0xdb, 0x68,
+       0xdf, 0x84, 0x9c, 0xb3, 0x91, 0x09, 0xc4, 0x20, 0x7f, 0xcc, 0xa1, 0x0d,
+       0x76, 0x72, 0x15, 0xf3, 0x61, 0x1c, 0x2c, 0x94, 0x99, 0xf7, 0x18, 0x52,
+       0x36, 0x71, 0xcf, 0x69, 0x36, 0x2b, 0x16, 0xf8, 0xbd, 0x40, 0x9e, 0x83,
+       0x32, 0xee, 0x0c, 0x88, 0x5d, 0xa3, 0x1c, 0xa2, 0xf0, 0x4a, 0x0f, 0x77,
+       0xa5, 0x16, 0xa3, 0x76, 0x1e, 0x14, 0x8d, 0x0b, 0x7d, 0x5d, 0x49, 0xe4,
+       0x39, 0xfa, 0x85, 0x48, 0x57, 0x0a, 0x36, 0x6b, 0x5c, 0x78, 0xa8, 0x2b,
+       0x7d, 0x9a, 0x7c, 0x19, 0xc8, 0x73, 0x3e, 0x0a, 0x9c, 0xdf, 0x94, 0xdf,
+       0x45, 0x2e, 0x5b, 0x18, 0x44, 0x0e, 0x80, 0xd5, 0xaf, 0x83, 0xef, 0xbc,
+       0x29, 0xc1, 0xae, 0xc4, 0xab, 0xe0, 0x6f, 0x18, 0xb2, 0xd9, 0x84, 0x3e,
+       0x06, 0xda, 0x07, 0x58, 0x13, 0x68, 0x69, 0xb7, 0xba, 0x10, 0x4f, 0x11,
+       0xbb, 0x24, 0x98, 0x1c, 0xe9, 0x06, 0xfd, 0x2b, 0x01, 0xe6, 0x82, 0xc1,
+       0xd8, 0x6a, 0xfb, 0x37, 0xdd, 0xf6, 0x41, 0xf0, 0xc2, 0xe7, 0x88, 0x09,
+       0x24, 0x38, 0x35, 0x62, 0x82, 0x07, 0xf6, 0x0d, 0xa9, 0xbe, 0xe9, 0x45,
+       0xda, 0x40, 0x23, 0x53, 0xb1, 0x1e, 0x91, 0xd4, 0xc2, 0x56, 0x19, 0x5f,
+       0xe8, 0x95, 0x5d, 0x0b, 0xc4, 0x30, 0xac, 0x69, 0x60, 0x2a, 0xc0, 0x18,
+       0xfa, 0x05, 0xe6, 0x76, 0xd1, 0xf0, 0x41, 0xe9, 0x0f, 0x7f, 0x15, 0xeb,
+       0x60, 0xca, 0x8a, 0x45, 0x66, 0xb1, 0xc6, 0x02, 0x8a, 0x4e, 0xd8, 0x1f,
+       0x93, 0x36, 0xba, 0x66, 0xdc, 0xf4, 0xe2, 0xbd, 0xe8, 0x62, 0xe1, 0x5c,
+       0x08, 0xaf, 0xa3, 0xfb, 0x57, 0x1e, 0x5d, 0x13, 0x74, 0xfb, 0x40, 0x93,
+       0x73, 0x7c, 0xa8, 0x73, 0xec, 0xb4, 0xd8, 0x1d, 0xe0, 0x2f, 0x1d, 0x7b,
+       0x58, 0x66, 0x41, 0xe7, 0xe8, 0x02, 0xfd, 0xa4, 0x6c, 0xc5, 0x67, 0xb8,
+       0x4d, 0x62, 0x83, 0xe7, 0x81, 0x73, 0xc6, 0x14, 0x0d, 0x17, 0x73, 0xe8,
+       0x17, 0x12, 0xc0, 0xa9, 0x1f, 0x07, 0x3f, 0xcc, 0xb1, 0x38, 0xe7, 0x00,
+       0xe6, 0x9b, 0xc0, 0x3a, 0x64, 0x7d, 0x85, 0xeb, 0x1b, 0xbf, 0xcf, 0x87,
+       0x3b, 0x53, 0xa7, 0xdb, 0xb1, 0xee, 0xe4, 0x11, 0x43, 0xc5, 0x7e, 0xea,
+       0xc5, 0xea, 0x4c, 0x96, 0x14, 0xdf, 0x9d, 0xa9, 0x12, 0x65, 0x14, 0xef,
+       0x4c, 0x97, 0x28, 0x23, 0x01, 0x3f, 0x71, 0xd8, 0x64, 0x40, 0x22, 0x5b,
+       0xa8, 0xc7, 0x43, 0xe8, 0xf7, 0x57, 0x01, 0xe2, 0xb8, 0xa4, 0xc5, 0xdf,
+       0xf0, 0xb5, 0x17, 0x0e, 0xa3, 0x2f, 0x7f, 0x6f, 0x07, 0xdd, 0xfe, 0xc1,
+       0x82, 0xb4, 0x0f, 0xce, 0xc0, 0x4f, 0xe8, 0x23, 0xc0, 0x91, 0xca, 0xce,
+       0x9b, 0xc0, 0xd8, 0x3b, 0x30, 0x1f, 0xac, 0x8d, 0x98, 0x25, 0xd3, 0xf3,
+       0x94, 0xab, 0x7c, 0x08, 0x73, 0xc0, 0xfc, 0x63, 0xf0, 0x2d, 0x9c, 0x03,
+       0xc7, 0x16, 0xe4, 0x36, 0x4b, 0x92, 0x9b, 0x0f, 0x2a, 0x2c, 0x6b, 0x9b,
+       0x1c, 0x5f, 0xd3, 0xf4, 0x44, 0x17, 0x74, 0xcc, 0xb9, 0xcd, 0x81, 0xb7,
+       0x67, 0x10, 0xff, 0xa2, 0x0a, 0x43, 0x19, 0x17, 0xb8, 0x56, 0x46, 0xb1,
+       0x4e, 0xc8, 0xbf, 0x67, 0x7b, 0x5a, 0x03, 0x3e, 0x45, 0xf9, 0x7f, 0xe4,
+       0xea, 0x09, 0xf8, 0x91, 0x51, 0xf9, 0x7d, 0xf8, 0x92, 0x1f, 0xd7, 0xe3,
+       0xc8, 0x1b, 0x86, 0x91, 0x37, 0x0c, 0x22, 0x6f, 0xb0, 0x90, 0x37, 0x44,
+       0x90, 0x37, 0xf4, 0x21, 0x6f, 0x08, 0x23, 0x3e, 0x88, 0x1c, 0xad, 0xe7,
+       0x61, 0x63, 0x0d, 0xf8, 0x41, 0x33, 0x68, 0xd7, 0x43, 0xc1, 0x64, 0x3d,
+       0x1c, 0x4c, 0xd5, 0x03, 0x98, 0xd3, 0x01, 0x8e, 0x89, 0xf9, 0xe5, 0x3b,
+       0xc7, 0x4a, 0xc3, 0x88, 0x39, 0x36, 0xfc, 0x52, 0x1a, 0xf1, 0x36, 0x2e,
+       0x47, 0xf0, 0xcc, 0xf2, 0x7c, 0x04, 0xcf, 0x34, 0x25, 0x1d, 0x6f, 0x93,
+       0x59, 0x33, 0x0e, 0x1a, 0x5b, 0x94, 0x9d, 0x22, 0xdf, 0x6a, 0x83, 0x9d,
+       0x4a, 0xae, 0xc8, 0x7c, 0xab, 0x0f, 0xf4, 0x3a, 0x11, 0x97, 0xe9, 0x1f,
+       0xe8, 0x0b, 0xec, 0xdd, 0x5f, 0xb2, 0xb8, 0xe6, 0xba, 0xb4, 0xe4, 0xe9,
+       0xbc, 0x10, 0x6b, 0x22, 0x0e, 0xc2, 0x2e, 0xd8, 0x36, 0x81, 0xe7, 0xf8,
+       0xfb, 0x6d, 0xcf, 0xef, 0x7f, 0x24, 0x28, 0x30, 0xde, 0x4b, 0x8c, 0xf9,
+       0x16, 0xe8, 0x39, 0xad, 0xeb, 0xb5, 0xa6, 0x8b, 0xe5, 0xdf, 0x67, 0xfd,
+       0x8d, 0x35, 0xc7, 0xd7, 0xc0, 0x73, 0xbf, 0xb9, 0x8c, 0x1c, 0xd9, 0xde,
+       0xbf, 0x82, 0xdf, 0xad, 0xfd, 0xeb, 0xe8, 0xaf, 0xda, 0x82, 0x66, 0x22,
+       0xce, 0x7c, 0x18, 0x3e, 0x73, 0x10, 0xfe, 0xf1, 0x56, 0x46, 0x5f, 0xba,
+       0x89, 0x79, 0x42, 0x9e, 0xc5, 0x5b, 0x99, 0xc0, 0xc0, 0xb5, 0xe6, 0x8b,
+       0xc0, 0x37, 0x63, 0x4b, 0x23, 0x92, 0x5a, 0xea, 0x0f, 0x5f, 0x96, 0xce,
+       0xdb, 0xb6, 0x5c, 0x6b, 0xce, 0x3a, 0xd1, 0xe3, 0xb6, 0x10, 0x6f, 0x99,
+       0x52, 0x01, 0xa9, 0x6d, 0x3b, 0x3b, 0x88, 0x19, 0x2f, 0x8a, 0x1e, 0x91,
+       0xe4, 0x29, 0x5b, 0x46, 0x76, 0xfa, 0xb9, 0xfb, 0x9d, 0x0e, 0xe9, 0x42,
+       0xdb, 0x52, 0x04, 0x7d, 0x88, 0x53, 0x39, 0xef, 0x2c, 0xe6, 0xac, 0xb9,
+       0xcf, 0x78, 0xf5, 0xc9, 0x42, 0x09, 0x73, 0xaf, 0xdf, 0xca, 0x5c, 0x3e,
+       0x05, 0xec, 0x0e, 0x1d, 0x25, 0x4f, 0xb1, 0xae, 0xb0, 0x09, 0x72, 0x1a,
+       0x83, 0xad, 0xd0, 0x06, 0xfa, 0xf1, 0x6c, 0x53, 0xbe, 0x11, 0xa7, 0x5d,
+       0xbc, 0x04, 0x59, 0x82, 0x56, 0xc0, 0x9f, 0x0f, 0x70, 0xde, 0x3c, 0xe5,
+       0x17, 0x46, 0x6e, 0xce, 0xb1, 0x25, 0xd8, 0x99, 0x58, 0x9f, 0x77, 0xdf,
+       0xca, 0x2c, 0x9f, 0x02, 0xfd, 0x01, 0xd6, 0xde, 0xe0, 0xb3, 0x8b, 0xac,
+       0x1d, 0x32, 0x27, 0xdd, 0x05, 0x3d, 0xed, 0x55, 0xb5, 0xb8, 0x64, 0x35,
+       0x2e, 0xd6, 0x49, 0xfa, 0x2c, 0x89, 0x18, 0xd6, 0x7e, 0xe4, 0xaf, 0x62,
+       0xea, 0x89, 0x49, 0xdc, 0xa3, 0x3c, 0x35, 0xe4, 0x1c, 0xb8, 0x7f, 0x61,
+       0x45, 0xe9, 0xc4, 0x80, 0xee, 0x72, 0x3b, 0x99, 0x84, 0xc9, 0xbc, 0x91,
+       0x80, 0x2f, 0x1c, 0xe1, 0x1c, 0xd4, 0xd8, 0xc8, 0xc7, 0xb9, 0xfe, 0x30,
+       0x67, 0xd8, 0x55, 0x4b, 0x5e, 0xae, 0xfe, 0x66, 0x4b, 0x47, 0x60, 0xd3,
+       0x92, 0x6f, 0x43, 0x3e, 0x90, 0x1c, 0xc1, 0x6f, 0x38, 0x81, 0xa3, 0xd0,
+       0xe7, 0xd9, 0x11, 0xd6, 0x3f, 0x5f, 0x02, 0xb6, 0x27, 0xdf, 0xb1, 0xc8,
+       0x11, 0xb5, 0x86, 0x71, 0xed, 0x30, 0x97, 0xdb, 0x24, 0x97, 0xd5, 0xfc,
+       0x1e, 0x22, 0xf6, 0x80, 0x9e, 0xee, 0x67, 0x7e, 0xe3, 0xf7, 0x39, 0x3f,
+       0x97, 0x3e, 0x63, 0x57, 0xd2, 0x8a, 0x48, 0xaa, 0x78, 0xa9, 0x19, 0xb0,
+       0x2c, 0x60, 0x67, 0x57, 0x8f, 0x29, 0x27, 0x08, 0x3e, 0x58, 0x6b, 0xdb,
+       0xa9, 0x74, 0x09, 0x3e, 0x68, 0x3b, 0xf9, 0x60, 0x62, 0xb3, 0x9c, 0x9b,
+       0xef, 0x91, 0xca, 0xfc, 0xcf, 0xa5, 0x3a, 0xdf, 0x25, 0xe7, 0xe7, 0x9b,
+       0x72, 0x35, 0xae, 0x7c, 0x93, 0xd5, 0xae, 0xd6, 0xb5, 0x3c, 0xec, 0xd6,
+       0x61, 0x62, 0xa3, 0xd7, 0xe5, 0x79, 0x39, 0x57, 0x76, 0x79, 0xcf, 0xb4,
+       0xf0, 0x7e, 0x15, 0xb6, 0xf6, 0xaa, 0x45, 0xfe, 0x47, 0xa4, 0x52, 0x24,
+       0xef, 0xfb, 0x14, 0xef, 0xbb, 0x56, 0x79, 0x97, 0xac, 0x61, 0x91, 0xff,
+       0x8d, 0x78, 0xef, 0x90, 0xec, 0x56, 0xf2, 0x1f, 0xc1, 0xb3, 0xef, 0xb4,
+       0xbf, 0x8a, 0x73, 0xad, 0xb9, 0x5c, 0x6c, 0x53, 0x3c, 0x1b, 0x89, 0x11,
+       0xc8, 0xe7, 0x5a, 0xb3, 0xe1, 0x70, 0x1d, 0xe1, 0xb7, 0xf3, 0x2f, 0xe0,
+       0xab, 0x7a, 0x55, 0xce, 0x92, 0x9b, 0xec, 0xee, 0x4c, 0x2e, 0x8e, 0x42,
+       0xb7, 0x9d, 0x6a, 0x1d, 0xc2, 0x6d, 0x40, 0x67, 0xff, 0x1e, 0xfd, 0xbf,
+       0xcd, 0xf5, 0xa6, 0xe4, 0x92, 0x86, 0x5c, 0x0a, 0xc5, 0xf1, 0x76, 0xe0,
+       0x27, 0x8c, 0xd3, 0xc8, 0x64, 0x1d, 0x3e, 0xd3, 0x07, 0xdf, 0xc6, 0xef,
+       0xf7, 0x6d, 0x0f, 0x79, 0xf8, 0x5c, 0xe8, 0x1c, 0x79, 0x05, 0xd7, 0xf3,
+       0x48, 0x03, 0x31, 0x36, 0x36, 0x58, 0x51, 0xfb, 0x10, 0x71, 0x85, 0x85,
+       0x67, 0x9d, 0x6f, 0xe3, 0xe3, 0x8e, 0x37, 0x56, 0xe7, 0x98, 0x6b, 0xe7,
+       0x54, 0x70, 0x1a, 0xc8, 0xdf, 0x2d, 0xd0, 0xe5, 0xb8, 0x79, 0x31, 0x12,
+       0x06, 0xc6, 0x65, 0x5b, 0x37, 0x7c, 0x4c, 0x04, 0x3e, 0x6b, 0x18, 0xbe,
+       0x9f, 0x6b, 0x99, 0x7e, 0xde, 0xe7, 0x7d, 0x18, 0x34, 0xe9, 0x7f, 0x87,
+       0x31, 0x67, 0xe6, 0xd8, 0xf4, 0x9f, 0x88, 0x27, 0xb5, 0x70, 0x57, 0xf2,
+       0xb4, 0x5b, 0x1b, 0x74, 0x7f, 0xf3, 0xbe, 0x04, 0x1f, 0x49, 0x44, 0xcb,
+       0x79, 0xe4, 0x7e, 0x29, 0xac, 0xd1, 0xa4, 0x85, 0x3c, 0xbb, 0x16, 0x7d,
+       0x85, 0x98, 0x5b, 0xa7, 0x0c, 0x96, 0x28, 0x27, 0xd6, 0xa9, 0x4c, 0xc9,
+       0x57, 0xbe, 0x0b, 0x79, 0x04, 0x65, 0x8b, 0x95, 0x85, 0x4f, 0x01, 0xff,
+       0x98, 0xfb, 0x5c, 0x89, 0xb5, 0xc8, 0x7e, 0xc4, 0x31, 0x03, 0x42, 0x40,
+       0x4e, 0xb5, 0x64, 0xc8, 0x67, 0x03, 0x43, 0xc8, 0x01, 0x9f, 0x45, 0xdf,
+       0x80, 0xe4, 0x97, 0x18, 0x0f, 0x02, 0x32, 0xb7, 0x24, 0x72, 0xfd, 0x14,
+       0xfd, 0x8a, 0xfa, 0x83, 0xcc, 0x1b, 0x99, 0x69, 0x62, 0xed, 0x79, 0xfa,
+       0x18, 0xfa, 0x89, 0x07, 0xa1, 0x8b, 0xd8, 0x4b, 0xdf, 0x40, 0x6c, 0x9a,
+       0x2d, 0xf6, 0xc3, 0x67, 0x4a, 0x43, 0x87, 0x4c, 0x11, 0xd3, 0x98, 0xa3,
+       0x6f, 0x50, 0x77, 0xf4, 0x6b, 0x8e, 0x41, 0x29, 0x9c, 0x62, 0xbd, 0x31,
+       0x08, 0x5e, 0x98, 0xb7, 0x1a, 0x2a, 0x0f, 0x7a, 0x50, 0xf9, 0x56, 0x7e,
+       0x07, 0x5a, 0xc6, 0x8d, 0x1d, 0xdf, 0xa6, 0xd3, 0x8f, 0x3d, 0x22, 0xf6,
+       0xc4, 0xa1, 0xce, 0x5d, 0xa5, 0x76, 0x29, 0xf7, 0xd2, 0x2e, 0xa9, 0xff,
+       0xac, 0x4e, 0x5f, 0x8b, 0x3c, 0x0c, 0xf4, 0x58, 0x23, 0x08, 0xa0, 0x5f,
+       0xc8, 0xeb, 0x47, 0xb9, 0xfe, 0xb6, 0x4c, 0xed, 0xfc, 0x3b, 0xf0, 0xe5,
+       0xfa, 0xb5, 0xdc, 0x4e, 0xf8, 0xdb, 0x09, 0x5d, 0x1e, 0xfb, 0x54, 0x1a,
+       0xcf, 0x32, 0x16, 0xde, 0xf2, 0xf0, 0x38, 0xdb, 0x58, 0xa3, 0x45, 0x9e,
+       0x7e, 0xce, 0xc4, 0x77, 0xaf, 0xe4, 0xcf, 0x05, 0x21, 0x07, 0xe4, 0xc4,
+       0x15, 0x97, 0x16, 0xf3, 0xde, 0xe3, 0xd0, 0x91, 0x7e, 0x32, 0x28, 0x6d,
+       0x27, 0x7b, 0x25, 0xf0, 0xad, 0x2e, 0x69, 0xff, 0xd6, 0x80, 0x18, 0xdf,
+       0x62, 0x2d, 0x29, 0x1a, 0x39, 0xaa, 0xea, 0x58, 0x69, 0x39, 0x86, 0xf8,
+       0xa5, 0x23, 0x16, 0x2b, 0x3b, 0x35, 0xb7, 0x8a, 0x81, 0xc4, 0x55, 0x7f,
+       0xc1, 0x96, 0xaf, 0xef, 0xfc, 0x85, 0xaa, 0xa3, 0x26, 0x47, 0x70, 0xfd,
+       0x72, 0x06, 0xd8, 0x44, 0x83, 0xad, 0x34, 0x32, 0xd7, 0x1e, 0xf5, 0x73,
+       0xcb, 0x41, 0x55, 0x93, 0xff, 0xfa, 0x4e, 0x37, 0xb7, 0x9c, 0x45, 0x6e,
+       0x99, 0x56, 0xb9, 0x25, 0xfc, 0x6b, 0x80, 0xfd, 0xb6, 0x8a, 0x8e, 0xb1,
+       0x72, 0xc2, 0x5c, 0xfd, 0xa3, 0x62, 0x1f, 0xc0, 0xba, 0x38, 0x23, 0xf3,
+       0x7a, 0x42, 0x53, 0x34, 0x8d, 0x17, 0xe8, 0xa7, 0xe8, 0xbf, 0x68, 0xe3,
+       0xac, 0x69, 0xa1, 0xed, 0x65, 0xfa, 0x28, 0xd7, 0xb6, 0xc7, 0x5a, 0x7c,
+       0xdd, 0x5c, 0xa9, 0x0e, 0x1d, 0x22, 0xa7, 0xb7, 0xda, 0x30, 0x7f, 0xc4,
+       0x74, 0x8b, 0xd7, 0x9c, 0x3f, 0x7c, 0x67, 0x28, 0xa4, 0xae, 0x0b, 0x65,
+       0xb7, 0x86, 0xe1, 0xd2, 0x67, 0xfe, 0x01, 0x1f, 0x53, 0x27, 0x1f, 0x1c,
+       0xb7, 0x4f, 0x8c, 0x33, 0x21, 0x09, 0x9c, 0xa1, 0xfd, 0x45, 0x23, 0x69,
+       0xc8, 0x6f, 0xce, 0x22, 0x06, 0x3c, 0x04, 0x6c, 0xf4, 0x88, 0xe8, 0xe7,
+       0x06, 0xb1, 0x76, 0xa2, 0xe1, 0xb2, 0xc4, 0xc4, 0xa8, 0x04, 0xe5, 0x8d,
+       0x53, 0xd1, 0x08, 0xed, 0xe5, 0x2c, 0xe2, 0xd5, 0x91, 0x7a, 0xe7, 0xed,
+       0x86, 0xe2, 0x82, 0x6d, 0xdf, 0x08, 0x00, 0x3b, 0x0c, 0xda, 0x7a, 0xb7,
+       0xdc, 0x80, 0xbe, 0xb3, 0xaa, 0xed, 0x11, 0xd0, 0x05, 0x0f, 0x67, 0x58,
+       0x1b, 0x24, 0xdd, 0xa3, 0xa0, 0x49, 0xda, 0x8d, 0xcc, 0x32, 0x73, 0xd3,
+       0x53, 0xb4, 0xdd, 0x5e, 0xd8, 0x1d, 0xae, 0xeb, 0xed, 0x92, 0x9d, 0x8c,
+       0x88, 0x7e, 0x6a, 0x8f, 0xf4, 0xef, 0xd4, 0xdd, 0xf9, 0xa8, 0x39, 0xb2,
+       0x8d, 0x35, 0xe7, 0x11, 0xb5, 0x1e, 0xf5, 0x25, 0xd8, 0xcc, 0x3e, 0xea,
+       0x18, 0xb1, 0x1f, 0x71, 0x8c, 0x7e, 0xcc, 0x40, 0x1c, 0x4b, 0xd5, 0x5d,
+       0xbd, 0x97, 0xf7, 0x6d, 0x95, 0x63, 0x67, 0x68, 0x4f, 0xb8, 0xb7, 0x6a,
+       0x53, 0xfe, 0xde, 0x10, 0xef, 0x59, 0x72, 0xfc, 0x45, 0xe6, 0x1e, 0xcc,
+       0x39, 0x98, 0x67, 0x45, 0xc3, 0xbb, 0x30, 0x1f, 0xfd, 0x31, 0xfa, 0x03,
+       0x5d, 0xd9, 0x6e, 0x0e, 0x3e, 0xba, 0x50, 0xa7, 0xde, 0x86, 0xb9, 0x7f,
+       0x66, 0x32, 0x5f, 0xb3, 0xc3, 0xae, 0xbc, 0x0b, 0x68, 0x9b, 0x85, 0xef,
+       0x4f, 0x39, 0x6d, 0xb2, 0x32, 0x69, 0x43, 0xf7, 0x5f, 0x02, 0x5f, 0x07,
+       0x3a, 0x59, 0x23, 0x58, 0x99, 0x4c, 0xe3, 0xfa, 0x80, 0xca, 0xd1, 0x8c,
+       0xc7, 0x6c, 0xd0, 0xd8, 0xca, 0x75, 0xe4, 0xe9, 0x29, 0xae, 0x17, 0xe6,
+       0x1f, 0xd3, 0x67, 0xe1, 0xb3, 0xc7, 0xe3, 0x8c, 0xf1, 0xdc, 0x4b, 0xe8,
+       0x00, 0x1f, 0xdd, 0x0a, 0x57, 0xe8, 0xd6, 0x4e, 0xbd, 0x50, 0xa6, 0x9f,
+       0xcf, 0x87, 0xdb, 0x85, 0x78, 0xc4, 0xd4, 0x2b, 0x16, 0x75, 0xa2, 0xc9,
+       0x65, 0xb5, 0xef, 0x20, 0x92, 0x76, 0x0e, 0x61, 0xac, 0xb8, 0x5e, 0x2d,
+       0xef, 0xd4, 0xf3, 0x65, 0x43, 0x56, 0x42, 0xe4, 0x3b, 0xa2, 0xf2, 0xf8,
+       0x9d, 0xca, 0xd6, 0x8a, 0x88, 0x25, 0xb0, 0x99, 0xf8, 0x87, 0x31, 0xae,
+       0x6a, 0x83, 0x4d, 0x51, 0xf7, 0xd4, 0xbb, 0xf2, 0x91, 0x9e, 0xee, 0x37,
+       0x8a, 0x99, 0x45, 0xf8, 0x5f, 0xd6, 0x2f, 0x3a, 0xbc, 0x5a, 0xe3, 0x4b,
+       0x5e, 0x3e, 0xf4, 0x8c, 0x30, 0x4f, 0x99, 0x2b, 0x91, 0x97, 0x22, 0xfc,
+       0xe1, 0x46, 0xb6, 0x44, 0x39, 0xba, 0x3e, 0xe5, 0x10, 0xec, 0x42, 0x5f,
+       0x32, 0x3d, 0x1b, 0xe0, 0xdf, 0x28, 0xee, 0x31, 0x06, 0xe0, 0xbb, 0xde,
+       0x86, 0xf5, 0xbe, 0x17, 0x32, 0xa2, 0x6e, 0xa0, 0xbf, 0x25, 0xee, 0xbb,
+       0x42, 0x7f, 0x4b, 0x57, 0xde, 0xb6, 0x7b, 0xe9, 0xf3, 0x46, 0xe4, 0x18,
+       0xfc, 0xe8, 0xd1, 0x45, 0xf2, 0x93, 0xf6, 0x70, 0xd9, 0x30, 0x64, 0x42,
+       0x1f, 0x3f, 0x2c, 0x6f, 0xd4, 0x7e, 0xa0, 0x70, 0xe0, 0xb6, 0x9d, 0x0d,
+       0x99, 0x86, 0x7f, 0x98, 0x71, 0x20, 0x7f, 0x33, 0x82, 0xf5, 0x19, 0x56,
+       0xfe, 0x71, 0xe6, 0xfd, 0xe5, 0x24, 0x01, 0x37, 0x66, 0x7f, 0xf6, 0x3e,
+       0x63, 0xf6, 0x03, 0xc0, 0x61, 0xef, 0x8b, 0xbe, 0xe1, 0xd2, 0xff, 0x33,
+       0xe8, 0xea, 0xd7, 0x55, 0xfd, 0x22, 0xb7, 0x73, 0x2b, 0x65, 0xfa, 0x5e,
+       0xcf, 0xe9, 0xee, 0x73, 0x9f, 0xbb, 0x4f, 0xbe, 0x4c, 0xa9, 0x01, 0x2b,
+       0xe4, 0x55, 0x1c, 0x65, 0xae, 0xd8, 0xe6, 0xe9, 0x6f, 0x10, 0x18, 0x9a,
+       0x74, 0x7d, 0xdf, 0xdb, 0x21, 0xf9, 0x5e, 0x3f, 0xff, 0x84, 0xcf, 0x5e,
+       0x6d, 0xf7, 0xf3, 0x59, 0x3e, 0xbf, 0x92, 0x41, 0xfe, 0x0c, 0x1b, 0x60,
+       0x2c, 0x60, 0x5b, 0x5c, 0xf9, 0xa1, 0x77, 0xe7, 0x9b, 0xf5, 0x0b, 0xf2,
+       0xbd, 0x5b, 0xf1, 0x9d, 0x56, 0x7c, 0xb3, 0x06, 0xb9, 0x5f, 0x4b, 0x9d,
+       0x67, 0x1d, 0xd2, 0xaf, 0x3b, 0x92, 0x1e, 0xb0, 0x01, 0xf4, 0xfd, 0x63,
+       0xd0, 0xfd, 0x11, 0xf4, 0xfa, 0xc3, 0x12, 0xb0, 0x41, 0x09, 0xd8, 0xa0,
+       0x04, 0x6c, 0x50, 0x02, 0x36, 0x28, 0x85, 0xbd, 0x3a, 0x8b, 0x4d, 0x6c,
+       0xff, 0x3e, 0x6d, 0xd7, 0xaf, 0x6d, 0xac, 0xb7, 0x4b, 0xb7, 0xb6, 0x99,
+       0xaa, 0xfb, 0x18, 0x39, 0xc8, 0x5a, 0x2b, 0xb0, 0x9a, 0x5f, 0xf7, 0xf0,
+       0x62, 0x44, 0x8d, 0xfb, 0x5e, 0x88, 0x11, 0x35, 0x1b, 0xeb, 0x66, 0x28,
+       0x6c, 0x00, 0x1b, 0x1a, 0x12, 0xc6, 0x6f, 0x13, 0xbe, 0x17, 0xb4, 0x86,
+       0xfb, 0xb1, 0x92, 0xda, 0x55, 0x5d, 0xef, 0x88, 0xaa, 0x3b, 0x58, 0x32,
+       0x5b, 0xf6, 0x73, 0xb7, 0x98, 0x8c, 0xcd, 0x13, 0x6f, 0xca, 0x16, 0x3d,
+       0x01, 0x1d, 0x38, 0xc4, 0x88, 0xdc, 0x27, 0xe4, 0xf8, 0xb1, 0xc1, 0x2a,
+       0xc6, 0x2c, 0x58, 0x2e, 0x7f, 0x47, 0x9c, 0xbb, 0xcf, 0xec, 0x82, 0x7f,
+       0xce, 0x14, 0x23, 0x32, 0x5e, 0x74, 0x31, 0x01, 0xf2, 0x9f, 0x75, 0xf5,
+       0xe5, 0x5b, 0xd0, 0xc3, 0xad, 0xcc, 0x94, 0xb5, 0x6a, 0x1b, 0x91, 0xcb,
+       0x71, 0xca, 0x98, 0xfa, 0xdf, 0xab, 0xf6, 0x29, 0x76, 0x55, 0xdd, 0xbd,
+       0xa4, 0x71, 0x65, 0x0b, 0x01, 0xfa, 0x19, 0xd0, 0x89, 0xbb, 0x6b, 0x18,
+       0x76, 0x91, 0x73, 0x7c, 0xb9, 0xb4, 0xe2, 0x91, 0x2f, 0x6a, 0x62, 0x6d,
+       0xd4, 0xfe, 0x1b, 0x2d, 0xed, 0xab, 0xf7, 0x3d, 0x7e, 0xe1, 0xfb, 0x56,
+       0x6b, 0x0d, 0xf4, 0x53, 0x77, 0xdb, 0x81, 0xdd, 0x24, 0xa0, 0xee, 0xc3,
+       0x87, 0xd7, 0x42, 0x92, 0xaa, 0x59, 0x92, 0x2e, 0xb3, 0x1f, 0xeb, 0x17,
+       0xf4, 0x47, 0x7f, 0x22, 0x29, 0xe4, 0xab, 0xd9, 0x50, 0x34, 0x6e, 0xcb,
+       0x7f, 0x96, 0xe5, 0x85, 0x7c, 0x84, 0xe7, 0x0a, 0xf2, 0x13, 0x1a, 0x9e,
+       0xfb, 0x19, 0xae, 0xc9, 0xb3, 0x25, 0x33, 0x45, 0xc6, 0x9d, 0xa1, 0x70,
+       0x0d, 0xf7, 0xb2, 0x93, 0xac, 0xd9, 0x7c, 0x07, 0x36, 0x19, 0x8d, 0x94,
+       0xa1, 0xef, 0x2b, 0x45, 0x8e, 0x07, 0x6c, 0x54, 0x64, 0x5d, 0xc7, 0xbf,
+       0xff, 0x27, 0xc0, 0x81, 0xf0, 0xd5, 0x21, 0xaf, 0x8f, 0x9a, 0xab, 0x6d,
+       0x06, 0x60, 0xe3, 0x0d, 0xcf, 0xdf, 0x56, 0x8a, 0x6e, 0x1d, 0xe5, 0x2c,
+       0xf9, 0x70, 0xfe, 0x77, 0xb3, 0x11, 0x42, 0x0e, 0xb4, 0x3a, 0xc7, 0xab,
+       0xa4, 0x6f, 0xc2, 0xdd, 0xca, 0x51, 0xc7, 0x97, 0x05, 0xef, 0xb3, 0x8d,
+       0x67, 0x27, 0x9a, 0xcd, 0xb3, 0xd6, 0x07, 0xad, 0x99, 0xf5, 0x6d, 0x4f,
+       0x5a, 0xf9, 0xdd, 0x15, 0x27, 0xef, 0xd5, 0xcc, 0xbe, 0xbd, 0xc3, 0xad,
+       0x99, 0xd5, 0x76, 0xac, 0xad, 0x99, 0x59, 0xdb, 0xdd, 0x9a, 0xd9, 0xfc,
+       0xee, 0x02, 0x3e, 0x6e, 0xcd, 0x2c, 0xbb, 0xdd, 0xad, 0x99, 0x95, 0xb7,
+       0xbb, 0x35, 0x33, 0x67, 0x87, 0x5b, 0x33, 0xfb, 0xf9, 0xf6, 0xb5, 0x35,
+       0xb3, 0x1f, 0xec, 0x58, 0x5b, 0x33, 0xbb, 0xb8, 0x3b, 0x87, 0xcf, 0xdd,
+       0x9a, 0xd9, 0xcf, 0x76, 0xdc, 0xbb, 0x66, 0xf6, 0x9a, 0x8f, 0xd7, 0x31,
+       0x9f, 0x11, 0xcc, 0x21, 0x0e, 0xbc, 0x3e, 0x0c, 0xbc, 0xfe, 0x6e, 0x75,
+       0xfe, 0x00, 0xe6, 0x39, 0xe8, 0xc5, 0x83, 0x0f, 0x82, 0xdb, 0x47, 0xbc,
+       0x67, 0x6d, 0xe4, 0xbb, 0x11, 0x2f, 0x57, 0x21, 0x76, 0xdf, 0xec, 0xe5,
+       0x6c, 0xff, 0xa8, 0xf3, 0xee, 0xb9, 0x97, 0xd6, 0xef, 0x0f, 0x21, 0xf5,
+       0xf6, 0xf1, 0x3c, 0xe7, 0x95, 0x47, 0xee, 0x47, 0x39, 0xd8, 0xe8, 0x3f,
+       0xbf, 0xfb, 0x1b, 0x16, 0x31, 0xfe, 0x73, 0x58, 0xab, 0xf6, 0x16, 0x43,
+       0x9d, 0x01, 0x60, 0x8c, 0x3a, 0x2e, 0x29, 0xf4, 0x4f, 0xa9, 0xfe, 0xd7,
+       0x5a, 0xfa, 0xaf, 0xa0, 0x3f, 0xe9, 0x46, 0xff, 0x1d, 0x3e, 0x2f, 0x29,
+       0xfb, 0xb6, 0x5c, 0x0c, 0x9f, 0x2e, 0xf9, 0x78, 0x2b, 0xe0, 0x61, 0xe7,
+       0x46, 0xc6, 0x76, 0x3e, 0x8f, 0x67, 0xa2, 0x17, 0x6d, 0xb9, 0xa9, 0xf0,
+       0xbb, 0x91, 0x88, 0x5e, 0xcc, 0xaa, 0x7c, 0xad, 0x91, 0xc9, 0x39, 0x7e,
+       0xfe, 0x8d, 0x1c, 0x6a, 0x80, 0x39, 0x0c, 0xec, 0x7d, 0x69, 0x10, 0x71,
+       0xac, 0x35, 0xc7, 0x66, 0x5e, 0xad, 0x7b, 0x79, 0xb5, 0x29, 0x9f, 0xd9,
+       0xd9, 0x8a, 0xcd, 0x2f, 0xee, 0xfe, 0xc7, 0x0a, 0x9b, 0x6f, 0x42, 0x6e,
+       0x4e, 0xec, 0x4d, 0x1c, 0x43, 0x0c, 0x41, 0x7c, 0xce, 0x7a, 0x01, 0xf3,
+       0x19, 0xc6, 0x46, 0xe6, 0x37, 0x21, 0x7c, 0x78, 0x26, 0xc9, 0xc7, 0xe8,
+       0xed, 0x9e, 0x7f, 0x67, 0x5e, 0xe4, 0x63, 0x95, 0xe4, 0x26, 0x37, 0x37,
+       0xda, 0xa4, 0xb9, 0xf9, 0x67, 0xc4, 0xeb, 0x13, 0x58, 0xc5, 0xc2, 0x81,
+       0x55, 0x2c, 0xbc, 0x66, 0x1f, 0x4b, 0xd4, 0xf9, 0x27, 0xb5, 0x1f, 0xc6,
+       0xfd, 0xb1, 0x46, 0xe6, 0xca, 0x80, 0x68, 0x7a, 0x82, 0xfb, 0x64, 0xc0,
+       0x3a, 0x16, 0xf7, 0xcd, 0xe8, 0x3b, 0xf7, 0x69, 0xa9, 0x2a, 0xe3, 0x0f,
+       0xf1, 0x91, 0xbf, 0x17, 0xee, 0xeb, 0x89, 0xb2, 0x63, 0xdb, 0x1f, 0x6b,
+       0xc8, 0x79, 0xe3, 0xed, 0xd6, 0x53, 0xe0, 0x25, 0x83, 0x6f, 0x5f, 0xa6,
+       0x9f, 0x55, 0xb1, 0xaf, 0x03, 0xb6, 0x7b, 0xa4, 0x44, 0xec, 0xba, 0x59,
+       0x6a, 0x1e, 0x7e, 0x3d, 0x37, 0xef, 0x62, 0xd7, 0xc0, 0x5a, 0xec, 0x1a,
+       0x5f, 0x16, 0x97, 0xc7, 0x5d, 0x1b, 0xf2, 0x48, 0xbc, 0x4a, 0xfe, 0x18,
+       0x77, 0xf6, 0xc2, 0xff, 0x35, 0x80, 0x69, 0x19, 0x73, 0x18, 0x6f, 0x22,
+       0xc0, 0xf6, 0xf7, 0xe2, 0x4f, 0xb5, 0x1d, 0xea, 0xb0, 0x82, 0xf8, 0x4c,
+       0xc3, 0x7f, 0x4c, 0xe0, 0x99, 0x8c, 0xcc, 0x9e, 0xfe, 0x1a, 0xe6, 0x36,
+       0x2d, 0x57, 0xe6, 0x27, 0xc1, 0xdf, 0x73, 0x32, 0x17, 0xcf, 0xc3, 0x8f,
+       0x70, 0xcf, 0x83, 0xb8, 0xad, 0xdf, 0xfb, 0x9e, 0xd6, 0xcf, 0x5a, 0x51,
+       0xe2, 0x46, 0xa9, 0x16, 0xe9, 0x83, 0xb9, 0x67, 0xc8, 0xbd, 0x61, 0xda,
+       0x0f, 0xeb, 0x27, 0xc8, 0x5d, 0x99, 0xc3, 0x9e, 0xe2, 0xf8, 0x6b, 0x75,
+       0xb2, 0xec, 0x10, 0x7f, 0x35, 0x32, 0x8d, 0x25, 0xe2, 0xc7, 0xf7, 0x8b,
+       0x25, 0xa9, 0x07, 0xe2, 0xc9, 0xfb, 0xc1, 0x91, 0xd1, 0x79, 0x60, 0xc8,
+       0x57, 0x1a, 0x7a, 0x2b, 0x8e, 0x74, 0x31, 0x64, 0x72, 0x29, 0x0b, 0x9a,
+       0x71, 0x85, 0x95, 0x91, 0xc7, 0xc1, 0xed, 0xf5, 0xe3, 0xd9, 0x7e, 0xe4,
+       0xe4, 0x2e, 0x66, 0x4c, 0x01, 0x33, 0xfe, 0x06, 0x30, 0xe3, 0xac, 0x74,
+       0x76, 0x11, 0x33, 0xda, 0x1e, 0x66, 0x4c, 0xc3, 0x9e, 0x73, 0x6b, 0xec,
+       0x59, 0x53, 0xb5, 0x28, 0xde, 0xcb, 0x01, 0xf3, 0xa5, 0x4e, 0x45, 0xef,
+       0x03, 0x27, 0x6a, 0x12, 0x52, 0xe7, 0x52, 0x02, 0x2d, 0x34, 0x7d, 0x3c,
+       0xb8, 0x4d, 0xe1, 0xbc, 0xdd, 0xa5, 0x4d, 0xc8, 0x51, 0x14, 0xee, 0xf3,
+       0xf6, 0x4b, 0x03, 0xeb, 0xf6, 0x90, 0x03, 0x2d, 0x7b, 0xc8, 0x77, 0xf1,
+       0x21, 0x9e, 0xf3, 0x6a, 0x7d, 0x6d, 0xf0, 0x05, 0xff, 0x13, 0x3c, 0x71,
+       0x7d, 0x71, 0x2d, 0x68, 0xee, 0x7a, 0x59, 0x83, 0x13, 0xff, 0x7a, 0x1d,
+       0x4e, 0x44, 0xec, 0x3a, 0x17, 0x92, 0x24, 0x30, 0xa2, 0xbd, 0x44, 0x5a,
+       0x5c, 0xd3, 0xc3, 0xd2, 0x8e, 0xf9, 0x75, 0x9c, 0xea, 0x05, 0x36, 0xea,
+       0x92, 0x20, 0x30, 0x52, 0x9b, 0xc2, 0x48, 0x03, 0xc4, 0x32, 0x83, 0x33,
+       0xc0, 0x36, 0xb5, 0x55, 0x9c, 0x14, 0x8d, 0xff, 0x01, 0xf4, 0xf2, 0x94,
+       0xf2, 0x3d, 0x69, 0x39, 0x01, 0x5f, 0xda, 0xbe, 0x04, 0x7c, 0x77, 0xce,
+       0xc5, 0x4f, 0x6d, 0xeb, 0xf0, 0xd3, 0xc1, 0x0d, 0xf1, 0x93, 0xaa, 0xdf,
+       0x8f, 0x52, 0x26, 0x37, 0x1c, 0xb7, 0x7e, 0x7f, 0xdd, 0x71, 0xeb, 0xf7,
+       0x37, 0x9c, 0xd6, 0xfa, 0xfd, 0x47, 0xa4, 0x60, 0x46, 0xed, 0x15, 0x59,
+       0x57, 0xbf, 0x9f, 0x60, 0x3d, 0xdc, 0xe9, 0x72, 0xeb, 0xf4, 0x5d, 0x5e,
+       0xfd, 0x3e, 0x2a, 0x85, 0x35, 0xed, 0xa6, 0xbc, 0x69, 0xf9, 0xf5, 0xfb,
+       0xef, 0xa2, 0xad, 0x1b, 0x63, 0xac, 0xad, 0xdd, 0x5f, 0x77, 0x58, 0xbb,
+       0x0f, 0xb1, 0x9f, 0x57, 0xbb, 0x67, 0x3f, 0xe4, 0xf2, 0x0e, 0xeb, 0xf6,
+       0x8f, 0x40, 0x16, 0x5b, 0x21, 0x87, 0x5e, 0x69, 0x3f, 0x13, 0x66, 0x1f,
+       0x55, 0xaf, 0x5f, 0x71, 0x42, 0x78, 0xce, 0xad, 0xab, 0xcf, 0xc0, 0xae,
+       0x0e, 0xae, 0xd6, 0xeb, 0xdd, 0x31, 0x6e, 0x3a, 0x6b, 0xe9, 0xaf, 0xa5,
+       0xd3, 0xe7, 0xd1, 0x09, 0x81, 0x4e, 0x78, 0x1d, 0x9d, 0xbb, 0xf5, 0xf9,
+       0x9b, 0x8e, 0x5b, 0x9b, 0x4f, 0x9f, 0x16, 0xbb, 0x1d, 0xbe, 0xf9, 0xe2,
+       0xc0, 0xc3, 0x1e, 0x8d, 0xd5, 0xda, 0x3c, 0x7d, 0x08, 0x70, 0x7b, 0x4c,
+       0x9d, 0xbd, 0x9a, 0xf9, 0x7f, 0x50, 0x9b, 0x67, 0x5d, 0xde, 0xdd, 0x5f,
+       0xe1, 0xfa, 0x04, 0x3e, 0x7f, 0xd1, 0xad, 0xc9, 0x8f, 0x95, 0xfc, 0x5a,
+       0x3b, 0xf3, 0x47, 0xff, 0x5c, 0x54, 0x7f, 0xe4, 0x88, 0xd0, 0x56, 0xc8,
+       0x1f, 0xe9, 0x76, 0xcb, 0x94, 0xc2, 0x47, 0xb0, 0xa9, 0xd8, 0xbd, 0x31,
+       0x72, 0xe5, 0x94, 0x8f, 0x91, 0x43, 0x0a, 0x23, 0x57, 0x96, 0x7c, 0x8c,
+       0x9c, 0xbc, 0x07, 0x46, 0x6e, 0x76, 0xb9, 0x71, 0x20, 0x28, 0x79, 0x85,
+       0x91, 0xef, 0x75, 0x96, 0x8c, 0xf7, 0xba, 0x88, 0x07, 0xc4, 0x3d, 0x5f,
+       0xd0, 0x7b, 0x8f, 0xb5, 0xe6, 0xe3, 0x66, 0xc6, 0xfe, 0xad, 0x32, 0x71,
+       0xe6, 0x2e, 0x6e, 0x76, 0xb1, 0x71, 0x34, 0x72, 0x48, 0xc5, 0x44, 0xe0,
+       0x84, 0x3a, 0xeb, 0xdf, 0xc4, 0xbe, 0x8c, 0x39, 0x01, 0x85, 0xcf, 0x72,
+       0x45, 0xe6, 0x01, 0x6c, 0x23, 0x16, 0xee, 0xe4, 0x31, 0x2b, 0x2f, 0x26,
+       0xf9, 0x58, 0xd3, 0x3f, 0xd7, 0xc2, 0x3d, 0x86, 0x37, 0x8d, 0xa4, 0x85,
+       0x76, 0xc7, 0xcf, 0x15, 0xe2, 0xea, 0x3c, 0x50, 0x12, 0x58, 0x72, 0x6a,
+       0x15, 0x4b, 0xd2, 0x57, 0xfc, 0xf4, 0x6d, 0xdb, 0xa4, 0x5f, 0xf3, 0xb1,
+       0x22, 0x72, 0xa2, 0x12, 0xd7, 0xb6, 0x8f, 0x15, 0x5d, 0x9c, 0x98, 0x72,
+       0x1a, 0xc0, 0xcb, 0x01, 0x19, 0x03, 0x4e, 0x6f, 0x7c, 0x89, 0x35, 0x28,
+       0x1f, 0x1b, 0xd9, 0xf8, 0x6e, 0xad, 0x49, 0xf1, 0xba, 0x5d, 0xed, 0x05,
+       0x5e, 0x1e, 0x08, 0xb6, 0xb4, 0x3f, 0x0b, 0xff, 0x8d, 0xfc, 0x08, 0xd8,
+       0xc4, 0xc5, 0x44, 0x3b, 0xa0, 0x83, 0x91, 0x7b, 0x60, 0xa2, 0xf5, 0x31,
+       0x8a, 0x31, 0xf3, 0x6e, 0x8c, 0x4a, 0xd7, 0xe9, 0xcf, 0xef, 0xc6, 0xa8,
+       0x7b, 0xc7, 0x50, 0xb6, 0x61, 0x76, 0x56, 0x06, 0x9f, 0x69, 0x29, 0xac,
+       0x8b, 0x51, 0x73, 0x1f, 0x20, 0x46, 0xb9, 0xf8, 0xc0, 0xe5, 0xfb, 0xf7,
+       0x21, 0x9b, 0x1f, 0x43, 0xa6, 0x3f, 0x02, 0xe6, 0xfa, 0x21, 0xe6, 0xf5,
+       0x03, 0xe0, 0xa1, 0xef, 0x97, 0xd6, 0x9f, 0x07, 0x19, 0x15, 0xe6, 0x87,
+       0x2e, 0x66, 0x72, 0x31, 0xfd, 0x0c, 0x56, 0x57, 0xad, 0xd8, 0xc8, 0x4c,
+       0x15, 0x87, 0xcc, 0x69, 0x77, 0x1f, 0x35, 0x92, 0x95, 0xa7, 0x3b, 0x53,
+       0x8b, 0x8c, 0x19, 0xea, 0x3a, 0xcc, 0xfa, 0x25, 0xb1, 0x43, 0x55, 0xe5,
+       0x99, 0x03, 0x52, 0xae, 0xb9, 0x78, 0x6b, 0x6e, 0xd1, 0xa5, 0x31, 0xe5,
+       0xe1, 0xad, 0x9c, 0x87, 0xb7, 0xb2, 0xb5, 0xe5, 0x48, 0x00, 0xfd, 0xe7,
+       0xe2, 0x6b, 0x31, 0xd6, 0x8c, 0x87, 0xb1, 0xa6, 0x3f, 0x20, 0xc6, 0xe2,
+       0x58, 0x39, 0x3c, 0x33, 0x3e, 0x1f, 0x91, 0x5d, 0x90, 0xf3, 0x58, 0x91,
+       0xfa, 0xe2, 0x19, 0xb2, 0xf7, 0xd2, 0x19, 0xf5, 0xe5, 0xea, 0x2a, 0x10,
+       0xdb, 0xa7, 0x8d, 0x43, 0x57, 0x63, 0xef, 0xa9, 0x2b, 0x31, 0xdf, 0x18,
+       0x09, 0xe2, 0xf3, 0xf7, 0xa5, 0x2b, 0xce, 0x83, 0xfa, 0x5a, 0x8f, 0xc5,
+       0xee, 0x07, 0x93, 0xad, 0xc5, 0x63, 0xb6, 0xc2, 0x63, 0xed, 0x5e, 0x1f,
+       0xd9, 0x33, 0x0e, 0x5d, 0xfe, 0x27, 0xf4, 0xf9, 0x99, 0xd5, 0x2d, 0x3f,
+       0x85, 0xff, 0xfe, 0x43, 0xe8, 0xe4, 0x3f, 0x22, 0x57, 0x78, 0xcd, 0xea,
+       0x93, 0x3f, 0x40, 0xdb, 0x5d, 0x9c, 0xc3, 0xfe, 0xc1, 0xc7, 0x92, 0xd6,
+       0x35, 0xe0, 0x93, 0x6b, 0x1e, 0x3e, 0x79, 0x3a, 0x99, 0xb4, 0x26, 0x59,
+       0x37, 0x87, 0x9c, 0x0f, 0xa4, 0xa6, 0x14, 0x36, 0xf1, 0x31, 0xc9, 0xed,
+       0x34, 0xc7, 0x9f, 0x75, 0x56, 0x80, 0x7d, 0x56, 0x3c, 0xec, 0x73, 0x60,
+       0xcc, 0xc5, 0x3e, 0xc1, 0xcf, 0x50, 0xff, 0x2e, 0xee, 0x59, 0xb1, 0x93,
+       0x18, 0xa7, 0x0a, 0x4c, 0x52, 0x71, 0x0e, 0x48, 0xbe, 0xbe, 0x57, 0x7d,
+       0x8e, 0x94, 0xec, 0x68, 0x1b, 0xe4, 0xc4, 0xda, 0xeb, 0x49, 0xae, 0x4a,
+       0x27, 0x6a, 0x16, 0xf1, 0x9d, 0x75, 0xa2, 0xe1, 0xdf, 0xf1, 0xae, 0x9f,
+       0xf7, 0xae, 0x4f, 0x78, 0xd7, 0xc7, 0x11, 0x87, 0x8f, 0xa9, 0x58, 0xca,
+       0x76, 0xb6, 0x41, 0xc9, 0x0e, 0x68, 0x01, 0x7b, 0x9c, 0x1d, 0xfe, 0x8b,
+       0x66, 0x59, 0xe9, 0x98, 0xf4, 0x27, 0xf0, 0x39, 0x8e, 0xcf, 0x34, 0x3e,
+       0xfb, 0xf1, 0xc9, 0xe3, 0xb3, 0x2a, 0x53, 0x2d, 0x55, 0x9a, 0x84, 0x8d,
+       0x0c, 0x4a, 0xaa, 0xfe, 0x12, 0xf4, 0xf8, 0x1c, 0x74, 0x7b, 0x58, 0x0a,
+       0xd5, 0x3f, 0x95, 0xd9, 0x79, 0x4d, 0xba, 0x2c, 0xe8, 0xb4, 0x0a, 0x5b,
+       0x9e, 0x77, 0xf7, 0x13, 0x3b, 0x13, 0x7b, 0xd1, 0xb7, 0x29, 0x4f, 0xc5,
+       0x9f, 0x13, 0xfd, 0xb1, 0x39, 0xf4, 0x13, 0xbd, 0x30, 0xfc, 0x31, 0xb5,
+       0x6f, 0x56, 0x8d, 0xbb, 0x32, 0xde, 0x65, 0xd9, 0x51, 0xe8, 0x7c, 0xf0,
+       0x18, 0x68, 0x27, 0xd5, 0xd9, 0xd8, 0x8c, 0x1c, 0x3d, 0xbd, 0xbc, 0xc5,
+       0xf5, 0xad, 0x51, 0xf3, 0x26, 0xf5, 0x8e, 0x79, 0xd8, 0xf0, 0x85, 0x19,
+       0xd8, 0xfb, 0x41, 0x27, 0xa0, 0x8d, 0x21, 0xde, 0x8c, 0x39, 0x37, 0x55,
+       0xbc, 0x81, 0xef, 0xca, 0xc4, 0x4e, 0x86, 0x70, 0xcd, 0xb3, 0x45, 0x88,
+       0x8b, 0xea, 0x6c, 0xe5, 0x32, 0xf0, 0x8d, 0xa6, 0xea, 0x80, 0xb3, 0xab,
+       0xfb, 0x43, 0x86, 0xf2, 0x5b, 0xb1, 0x98, 0x2e, 0xb9, 0x11, 0xe2, 0xdc,
+       0xbd, 0x2a, 0x36, 0xd5, 0x8a, 0xf6, 0x43, 0xcc, 0x15, 0x6f, 0x08, 0xe3,
+       0xdc, 0xe3, 0xe8, 0xd7, 0x07, 0x7f, 0x8c, 0x7b, 0x75, 0xda, 0x27, 0xe7,
+       0xca, 0x67, 0xa6, 0xa5, 0x5a, 0x1e, 0xc5, 0x7c, 0xbd, 0x1c, 0x49, 0xe5,
+       0x12, 0x11, 0xd8, 0xa3, 0xbf, 0x17, 0xe5, 0xd6, 0x4f, 0xaa, 0x8e, 0x8f,
+       0x29, 0xba, 0xd1, 0x87, 0x79, 0x05, 0x64, 0xe4, 0xee, 0x9f, 0xa9, 0xbd,
+       0xb3, 0x82, 0x33, 0x0a, 0x39, 0x25, 0xd1, 0xce, 0x5a, 0x35, 0x7e, 0x97,
+       0x75, 0x55, 0x13, 0x58, 0x31, 0x66, 0xa4, 0x56, 0x6e, 0x82, 0x5f, 0xc4,
+       0xdc, 0x2d, 0x33, 0x52, 0x29, 0x4f, 0xcb, 0x2b, 0xe5, 0x9f, 0x77, 0x03,
+       0x53, 0x41, 0xa6, 0xe4, 0xbf, 0x5b, 0xee, 0x9e, 0xbf, 0xf5, 0xdb, 0x21,
+       0xcf, 0xd3, 0xf9, 0xb0, 0x9b, 0xe7, 0xe6, 0x55, 0x2d, 0xc6, 0xfd, 0xb6,
+       0xf5, 0x29, 0x2b, 0x1a, 0x9e, 0x45, 0xcf, 0x83, 0x0b, 0xb4, 0xcd, 0xfc,
+       0xf8, 0x9c, 0xb5, 0x43, 0xae, 0xc6, 0x37, 0xcb, 0x72, 0x5c, 0xe5, 0xc5,
+       0xc4, 0x0f, 0x58, 0xeb, 0x51, 0xb3, 0x21, 0x7b, 0xe4, 0x28, 0xd6, 0xed,
+       0xd5, 0xf8, 0xd3, 0xb0, 0xd3, 0x67, 0x61, 0x0b, 0xac, 0x01, 0x1c, 0x62,
+       0xae, 0x25, 0x0d, 0x55, 0x23, 0x6b, 0x36, 0xc7, 0xd5, 0x19, 0xee, 0x76,
+       0x59, 0x56, 0x58, 0xcc, 0xad, 0x9d, 0x2f, 0x4f, 0xba, 0x6b, 0xc4, 0x50,
+       0x76, 0xff, 0xc7, 0xe0, 0xc7, 0x84, 0xed, 0xb6, 0xa9, 0x3e, 0x46, 0xa2,
+       0xc3, 0xeb, 0xa3, 0xf4, 0xdb, 0xd2, 0xe7, 0x95, 0x44, 0xd2, 0xda, 0xff,
+       0x89, 0xa4, 0x75, 0x73, 0xb7, 0x5b, 0x6f, 0x89, 0x9a, 0xb6, 0xc6, 0xf7,
+       0x52, 0xdc, 0xf5, 0x98, 0xc1, 0xba, 0xba, 0xb4, 0x8a, 0xa1, 0x61, 0xa4,
+       0x2f, 0x5f, 0x81, 0x7e, 0x03, 0xd2, 0x7e, 0xb2, 0xf9, 0xf8, 0x54, 0x7c,
+       0x28, 0x72, 0x50, 0x78, 0x02, 0x8b, 0x79, 0x75, 0x34, 0x9e, 0x95, 0x2b,
+       0x88, 0x93, 0x77, 0x88, 0x1d, 0x06, 0x2f, 0xcb, 0x9d, 0xc7, 0x93, 0xf1,
+       0x51, 0xad, 0x32, 0x89, 0xac, 0xe5, 0xe5, 0x49, 0xc6, 0xd9, 0x43, 0x22,
+       0xc0, 0x97, 0x27, 0x47, 0x24, 0x5d, 0x54, 0xef, 0xa9, 0xf0, 0x9c, 0xad,
+       0x36, 0x0d, 0xf9, 0xe1, 0xf9, 0x09, 0x06, 0x46, 0xdd, 0xea, 0x8f, 0xa4,
+       0xe5, 0x69, 0xd6, 0xc0, 0x24, 0xb7, 0x20, 0xdb, 0x92, 0xf0, 0xab, 0xf6,
+       0x44, 0xbb, 0x4c, 0xd7, 0x1a, 0x99, 0xfe, 0x53, 0xcf, 0x82, 0xc6, 0x14,
+       0x68, 0xed, 0x45, 0x6e, 0x92, 0x45, 0xac, 0xa6, 0x7c, 0xe9, 0xbb, 0x9f,
+       0x81, 0x8c, 0x3e, 0xc2, 0x3d, 0xe5, 0xd1, 0xac, 0x44, 0x27, 0xf2, 0x8a,
+       0xee, 0x5b, 0x5a, 0x6e, 0xf8, 0x57, 0x10, 0xeb, 0x02, 0xb2, 0x2b, 0x26,
+       0xfa, 0xde, 0x58, 0xe0, 0xed, 0x29, 0x8b, 0x6d, 0x41, 0xb6, 0xe9, 0x68,
+       0x0b, 0xfc, 0x7a, 0x2c, 0xa8, 0x27, 0x63, 0xd1, 0x51, 0x9e, 0x8f, 0x36,
+       0xac, 0x29, 0xee, 0x4d, 0x3c, 0x20, 0x5d, 0x7b, 0xa5, 0xe7, 0x42, 0x74,
+       0xf4, 0x06, 0x78, 0x09, 0x28, 0x5f, 0x3f, 0x25, 0xba, 0xd7, 0xde, 0xbd,
+       0xda, 0x1e, 0xf0, 0xda, 0xf7, 0x4a, 0xd7, 0x85, 0x21, 0xf3, 0x75, 0x99,
+       0x01, 0x4d, 0x43, 0xae, 0x23, 0xd7, 0xb1, 0x06, 0xa6, 0x60, 0x8b, 0x4f,
+       0x92, 0x97, 0xfd, 0xc0, 0x1a, 0x58, 0x1b, 0xc8, 0xbf, 0xad, 0x0f, 0xcb,
+       0x57, 0xcd, 0x4e, 0xc9, 0xa9, 0x5c, 0x37, 0xe0, 0xd6, 0x52, 0x61, 0xef,
+       0x8f, 0x0e, 0x1c, 0xec, 0x71, 0xeb, 0x05, 0xdc, 0xef, 0x18, 0x46, 0xdb,
+       0x9d, 0xe6, 0x39, 0x8b, 0x6d, 0xbc, 0x77, 0xa7, 0x59, 0xb5, 0x86, 0xcc,
+       0x94, 0x16, 0xf4, 0xf6, 0xbd, 0x0f, 0xa9, 0xb9, 0xe7, 0xcb, 0xfd, 0x66,
+       0x45, 0x1e, 0xd5, 0x52, 0x0f, 0x22, 0x5e, 0x38, 0xd3, 0xe8, 0x7b, 0x87,
+       0xe7, 0x29, 0x54, 0x7d, 0xbf, 0x22, 0xfe, 0x35, 0xe9, 0x0c, 0x99, 0xe3,
+       0xea, 0xd9, 0x21, 0xf3, 0xa8, 0xd6, 0xfa, 0x6c, 0x58, 0x1b, 0x5f, 0xf3,
+       0x6c, 0x97, 0x92, 0x91, 0x61, 0xb9, 0x7d, 0x66, 0xcb, 0x7b, 0xe5, 0x79,
+       0x87, 0xfd, 0xee, 0x34, 0x53, 0xd6, 0x03, 0xda, 0xd1, 0x07, 0xe9, 0x0b,
+       0xd9, 0xf7, 0xf6, 0xba, 0x71, 0x78, 0x7d, 0xaf, 0x31, 0x9a, 0xb2, 0x76,
+       0x8c, 0x4d, 0xaa, 0xcf, 0x55, 0xd5, 0x27, 0xa0, 0x64, 0xbd, 0x76, 0x9c,
+       0xbf, 0x91, 0xb5, 0xe3, 0x74, 0xad, 0xce, 0x79, 0x16, 0x34, 0x8f, 0xa1,
+       0x6f, 0xd1, 0xe9, 0x0f, 0x57, 0xe5, 0x76, 0x33, 0x67, 0xbd, 0x29, 0x57,
+       0x57, 0x69, 0xff, 0x12, 0xd7, 0xad, 0x3c, 0xfd, 0xd2, 0xe3, 0x91, 0xbf,
+       0xd9, 0xf6, 0x2f, 0x95, 0xbc, 0x1f, 0xb0, 0xfa, 0xf7, 0x57, 0xb4, 0xe8,
+       0xe8, 0x5f, 0x0a, 0x75, 0xf5, 0xcf, 0x94, 0xaf, 0xf9, 0x18, 0xf4, 0xb4,
+       0xed, 0x05, 0xac, 0xdd, 0xe1, 0xa4, 0xea, 0x73, 0xdd, 0xda, 0x2b, 0xdb,
+       0x4e, 0xf6, 0x9b, 0xd7, 0xe5, 0x33, 0x92, 0x0e, 0xf1, 0x1a, 0x39, 0x94,
+       0xc5, 0xf7, 0x52, 0x3e, 0xc1, 0xbc, 0x00, 0xba, 0xec, 0x1f, 0xfc, 0x4b,
+       0x79, 0x56, 0x8e, 0x96, 0xe6, 0xe0, 0x7b, 0xa6, 0x64, 0xf0, 0x05, 0xfa,
+       0x9f, 0xbc, 0xe9, 0xd6, 0x6a, 0xdc, 0x98, 0x98, 0xf2, 0x62, 0xe2, 0x9c,
+       0xf2, 0x73, 0xaf, 0x79, 0xe7, 0x22, 0xfa, 0x07, 0xcf, 0xe1, 0xd9, 0x57,
+       0x94, 0x0f, 0xf8, 0x3d, 0xa9, 0x62, 0x2d, 0x44, 0x5e, 0xde, 0x2c, 0x0f,
+       0x3c, 0x41, 0x9b, 0x44, 0x06, 0xf0, 0xb1, 0x36, 0xf5, 0x1e, 0x8c, 0x6e,
+       0x75, 0x88, 0x6c, 0xa1, 0xfd, 0x5c, 0x86, 0xad, 0x4d, 0xb9, 0x7b, 0x5f,
+       0x6b, 0xae, 0xa3, 0x13, 0x2b, 0xf2, 0x1f, 0x94, 0x1d, 0x7e, 0xfc, 0x82,
+       0xfb, 0x3d, 0x7c, 0x01, 0xe9, 0x72, 0x6c, 0xaf, 0x6c, 0xbf, 0xe0, 0xda,
+       0xdd, 0xec, 0xfc, 0xb3, 0x4a, 0xbe, 0x53, 0x4a, 0xbe, 0x4d, 0x99, 0x89,
+       0x53, 0xf6, 0x9c, 0x13, 0xcf, 0x4f, 0xba, 0x32, 0xf9, 0x9c, 0x67, 0x47,
+       0xfd, 0x2f, 0xf0, 0x3d, 0x35, 0xca, 0x88, 0x7c, 0xcf, 0xf4, 0x70, 0x3f,
+       0x76, 0xdb, 0x05, 0xce, 0xb7, 0x6f, 0xcd, 0x7c, 0x4f, 0xc0, 0xc7, 0x0e,
+       0x0c, 0xb8, 0x73, 0x7e, 0x6d, 0xfe, 0xfd, 0xcf, 0xf9, 0x77, 0x57, 0xe7,
+       0x6c, 0x48, 0x55, 0xe5, 0xb9, 0xb1, 0xcd, 0xd2, 0x95, 0x93, 0x06, 0xec,
+       0xe3, 0xcf, 0x85, 0x67, 0xc6, 0xc9, 0x8b, 0x3b, 0xee, 0xb2, 0x43, 0x9e,
+       0xfc, 0x39, 0x90, 0xaf, 0x29, 0x4f, 0x7f, 0xe4, 0xe3, 0xd9, 0x0d, 0xef,
+       0x5d, 0x97, 0x46, 0x66, 0x10, 0x6d, 0xba, 0xd2, 0xe1, 0x98, 0xb7, 0xde,
+       0xf6, 0x8a, 0xae, 0x74, 0x98, 0x5c, 0xd5, 0xe1, 0x0d, 0xe8, 0xb0, 0x2a,
+       0x9f, 0xc6, 0x9c, 0xb0, 0xbe, 0x5f, 0x18, 0x32, 0x67, 0x64, 0xab, 0xd2,
+       0xbf, 0x35, 0x00, 0x9f, 0xea, 0xe9, 0xb2, 0xfd, 0x3e, 0x74, 0xf9, 0xba,
+       0x28, 0x7d, 0xaa, 0x73, 0x44, 0x55, 0x45, 0x87, 0xbe, 0x8d, 0x73, 0x6b,
+       0x57, 0x3e, 0x81, 0x3c, 0xaa, 0xb3, 0x01, 0x13, 0xae, 0x7e, 0xd5, 0x9a,
+       0xf7, 0xf4, 0x9b, 0x9d, 0xa0, 0x0e, 0x7f, 0xad, 0xc7, 0xd5, 0x67, 0x87,
+       0xea, 0x73, 0x2a, 0x36, 0xaa, 0xd6, 0xbb, 0x35, 0xf0, 0xe9, 0x1e, 0xea,
+       0xf4, 0x79, 0xc7, 0xfd, 0x2e, 0x22, 0xce, 0x9d, 0x72, 0xde, 0x4b, 0xaf,
+       0xae, 0x4e, 0xc7, 0xc4, 0x5d, 0x57, 0xeb, 0xf5, 0xa9, 0x5f, 0x08, 0x28,
+       0x1b, 0x1e, 0x83, 0x0c, 0x8f, 0x97, 0x1e, 0xf4, 0xec, 0xde, 0x9d, 0xf3,
+       0xc0, 0xfb, 0x9c, 0xf3, 0x91, 0x62, 0xbf, 0xf9, 0x26, 0xee, 0x8d, 0x63,
+       0xce, 0x33, 0xd2, 0x26, 0x29, 0x6f, 0xce, 0x91, 0xd5, 0x39, 0xfb, 0x3c,
+       0xba, 0xfd, 0x52, 0xcc, 0x63, 0x1d, 0xfa, 0xaf, 0x7f, 0xab, 0xde, 0x37,
+       0xb9, 0x59, 0xa4, 0xdf, 0x06, 0x56, 0x0a, 0xf5, 0xca, 0xf5, 0x5a, 0x44,
+       0xae, 0x13, 0x83, 0x8c, 0xe0, 0xdb, 0x99, 0xf3, 0x62, 0x78, 0x50, 0x5e,
+       0x2f, 0x6e, 0xc4, 0xc7, 0xb0, 0xdc, 0x28, 0xfa, 0xbc, 0x10, 0x0b, 0x33,
+       0x5f, 0x98, 0x92, 0x37, 0xe6, 0xfb, 0xa5, 0x31, 0x81, 0xb8, 0x3f, 0x40,
+       0x99, 0x0c, 0x99, 0x7b, 0xd4, 0x7b, 0x48, 0x77, 0x9a, 0x97, 0x2d, 0xd0,
+       0x5f, 0x68, 0xca, 0x41, 0xee, 0x67, 0xf3, 0x77, 0xed, 0x21, 0x69, 0x30,
+       0xa7, 0x18, 0xe8, 0x95, 0xca, 0x02, 0xf2, 0xf9, 0x22, 0xe9, 0x53, 0x6e,
+       0x7b, 0xd5, 0xef, 0x71, 0x8c, 0xf7, 0x39, 0xbe, 0x1f, 0x10, 0xa2, 0x6e,
+       0xee, 0x34, 0x97, 0x2d, 0xee, 0x67, 0x4e, 0x49, 0x0d, 0xfa, 0xfb, 0xe7,
+       0x31, 0xee, 0xb7, 0xe7, 0xd4, 0xf9, 0xdb, 0x4a, 0x6d, 0x02, 0xb9, 0xc3,
+       0x9d, 0xe6, 0x9c, 0x75, 0x56, 0xe9, 0xad, 0x56, 0x7e, 0xc2, 0x6b, 0xe7,
+       0x35, 0xef, 0x35, 0x32, 0xdb, 0x06, 0x98, 0xaf, 0x3e, 0x81, 0x7c, 0x81,
+       0xb9, 0xea, 0x04, 0xf0, 0x1a, 0x65, 0x12, 0x91, 0xd9, 0x22, 0x69, 0x49,
+       0x68, 0x13, 0xf2, 0xfb, 0x9c, 0x8c, 0x83, 0x9f, 0x08, 0x72, 0x7b, 0xc6,
+       0x87, 0x47, 0x65, 0x39, 0xe4, 0xc6, 0x01, 0x9e, 0xfb, 0x5a, 0x46, 0x6c,
+       0x58, 0x5e, 0x8d, 0x0d, 0x5b, 0x71, 0xdd, 0xc8, 0xc4, 0x07, 0xfe, 0x06,
+       0xf4, 0x59, 0xb7, 0x61, 0x6c, 0x18, 0x45, 0x7f, 0xb6, 0xf5, 0xca, 0xec,
+       0x02, 0x92, 0x08, 0xe4, 0x2c, 0x15, 0xe1, 0x99, 0x8e, 0xac, 0x9c, 0xaa,
+       0xf5, 0x87, 0x2f, 0x6b, 0x69, 0x75, 0xf6, 0x23, 0x36, 0xc0, 0xf3, 0x2c,
+       0xbd, 0x52, 0x5b, 0x90, 0x88, 0x91, 0x78, 0x52, 0x9c, 0x9a, 0x8b, 0xd9,
+       0xe7, 0x34, 0x9e, 0x69, 0xb1, 0xa5, 0xb6, 0xb6, 0x8f, 0x89, 0xdc, 0x57,
+       0xbe, 0xe3, 0xf5, 0x49, 0xab, 0x3e, 0x7f, 0xdd, 0xc3, 0x3d, 0xb4, 0x9a,
+       0xd3, 0x03, 0x1e, 0xc8, 0xdb, 0xc3, 0xad, 0xe3, 0x46, 0xee, 0x8e, 0xcb,
+       0x31, 0x91, 0xcd, 0x6c, 0xb1, 0x31, 0xee, 0x4d, 0x3c, 0xf3, 0x24, 0xf8,
+       0xb8, 0x63, 0xe8, 0xd6, 0x93, 0x52, 0xa8, 0xad, 0x1f, 0xa3, 0x95, 0x07,
+       0x3e, 0x43, 0xfa, 0x1c, 0xe7, 0x00, 0xf8, 0xbb, 0xa3, 0xe9, 0xd6, 0x01,
+       0xc8, 0xd2, 0x1d, 0xc3, 0x38, 0x13, 0x35, 0x7f, 0x2a, 0x03, 0xa2, 0x9f,
+       0xd3, 0x94, 0xfc, 0xf5, 0xca, 0x30, 0x16, 0x48, 0x46, 0xba, 0x96, 0x26,
+       0xc5, 0x58, 0x62, 0x0d, 0xe1, 0xb5, 0xce, 0xb4, 0xda, 0xbf, 0xdd, 0x84,
+       0xf5, 0x2d, 0x76, 0xc0, 0x62, 0xbd, 0x80, 0xf5, 0xe0, 0x9f, 0x6e, 0x96,
+       0x1e, 0xd6, 0x0b, 0x98, 0x37, 0xec, 0xc7, 0x37, 0x73, 0x87, 0x4b, 0x4d,
+       0xe4, 0x7a, 0x9b, 0x19, 0x5f, 0x73, 0x35, 0xde, 0x8f, 0x46, 0x44, 0x78,
+       0x8f, 0x7e, 0xa3, 0x57, 0xda, 0xbe, 0x35, 0x08, 0x5f, 0xf1, 0x34, 0xb0,
+       0x37, 0xe8, 0x9e, 0x1c, 0x90, 0x80, 0x7b, 0x66, 0x42, 0xd5, 0x5b, 0xde,
+       0x58, 0x88, 0x7a, 0xef, 0x73, 0xc9, 0xb6, 0xcb, 0x71, 0xd6, 0x44, 0xfb,
+       0x58, 0xf3, 0x41, 0x3f, 0xd1, 0x97, 0x91, 0x9f, 0x5e, 0xaf, 0x59, 0x9b,
+       0x79, 0x7e, 0xf3, 0x86, 0x83, 0x6b, 0x62, 0xff, 0x90, 0xc2, 0x98, 0xde,
+       0x3d, 0xfe, 0x46, 0xbe, 0xf4, 0x8e, 0x77, 0x13, 0x98, 0x4f, 0x4d, 0x7a,
+       0x67, 0xe7, 0x1a, 0x99, 0xa3, 0x6b, 0x72, 0xaa, 0x41, 0x55, 0xef, 0x6d,
+       0x38, 0x16, 0xfc, 0xe3, 0x08, 0xec, 0x93, 0x6b, 0xa0, 0xa9, 0x3d, 0x01,
+       0x6c, 0x16, 0xe9, 0x55, 0x39, 0xd1, 0xf1, 0x27, 0xc4, 0xb5, 0x77, 0x58,
+       0x99, 0xf2, 0x65, 0x8d, 0xb2, 0x9b, 0x83, 0x2c, 0x97, 0x33, 0xf2, 0x47,
+       0xce, 0x15, 0x55, 0x6b, 0x9d, 0x47, 0x5e, 0x12, 0x38, 0xa5, 0x72, 0xb2,
+       0x16, 0x7c, 0x0b, 0xbf, 0xf7, 0xe2, 0xd7, 0xb1, 0x16, 0xa3, 0xea, 0x8c,
+       0x82, 0x7e, 0xae, 0xd9, 0x4c, 0xc1, 0x7f, 0xe8, 0x96, 0x65, 0x16, 0x10,
+       0x0f, 0x53, 0xea, 0x9c, 0x0b, 0xd7, 0xf1, 0x6f, 0x2b, 0xff, 0x2c, 0x15,
+       0xc8, 0xe6, 0x4c, 0x04, 0x74, 0x34, 0x65, 0x9f, 0x86, 0xd2, 0xc3, 0x13,
+       0x0a, 0xf3, 0x1a, 0xe7, 0xe0, 0xb0, 0x96, 0x06, 0x44, 0xce, 0x65, 0x64,
+       0x0e, 0x6b, 0x38, 0xb0, 0x44, 0x1d, 0x50, 0xb6, 0x93, 0xd2, 0x06, 0xd9,
+       0x1f, 0x01, 0xf6, 0x30, 0x4e, 0x51, 0xc6, 0x61, 0xac, 0x8b, 0x5e, 0x09,
+       0x9c, 0x81, 0x8c, 0x4f, 0x01, 0x23, 0x2c, 0xb4, 0xcb, 0xf7, 0x6a, 0xbe,
+       0x4c, 0x2f, 0xf1, 0x5c, 0xbf, 0x3e, 0x35, 0xd2, 0x47, 0x1c, 0x25, 0xd5,
+       0xda, 0x9c, 0xcc, 0x9d, 0x66, 0xce, 0x3e, 0xa9, 0xce, 0x0c, 0x04, 0xd4,
+       0x99, 0x15, 0x37, 0x67, 0x76, 0xbf, 0x5d, 0x8c, 0x59, 0x15, 0xee, 0xb5,
+       0x09, 0x6c, 0x67, 0x18, 0xe3, 0x6e, 0x24, 0x5f, 0x37, 0x57, 0x1d, 0x07,
+       0xbf, 0x97, 0xe7, 0xa3, 0x99, 0xbc, 0xc4, 0x79, 0x76, 0x7a, 0xc2, 0xc6,
+       0xfc, 0x97, 0xe1, 0x3f, 0xe7, 0x4a, 0x3c, 0x27, 0x5d, 0xc0, 0x0a, 0xcb,
+       0xc8, 0xe5, 0x22, 0x73, 0xc6, 0x8f, 0x43, 0x6f, 0xbc, 0x2e, 0x8c, 0x1a,
+       0xf0, 0x03, 0x2b, 0xea, 0xdd, 0xcf, 0xa8, 0xdd, 0x40, 0x0e, 0x1b, 0xd1,
+       0xf6, 0x43, 0xd7, 0x79, 0xb3, 0xcd, 0xb3, 0x07, 0x9e, 0xc5, 0x3f, 0x0b,
+       0x3f, 0x7a, 0x5e, 0xf8, 0x4e, 0xd6, 0xed, 0x26, 0xf3, 0xa5, 0xab, 0xf0,
+       0x7b, 0x99, 0x58, 0x06, 0x36, 0x94, 0x0f, 0x77, 0x80, 0xe7, 0xdf, 0xc4,
+       0xbd, 0x9c, 0xc3, 0x71, 0xa2, 0xf1, 0x15, 0x29, 0x44, 0x02, 0x32, 0x14,
+       0xb9, 0x22, 0x9b, 0xe1, 0xc9, 0x34, 0x79, 0xdd, 0x8a, 0x8e, 0x8a, 0xa6,
+       0xe8, 0x0d, 0xee, 0x86, 0x0d, 0xde, 0x84, 0xbf, 0x6b, 0xf7, 0x72, 0xfd,
+       0x54, 0x91, 0x18, 0xea, 0x59, 0x75, 0xb6, 0xe0, 0xaa, 0xc5, 0x3a, 0x20,
+       0xdf, 0xc5, 0xfe, 0x1f, 0x6a, 0x8c, 0xbb, 0x7b, 0x77, 0xac, 0x43, 0x93,
+       0x3f, 0x77, 0x8e, 0xbb, 0x2c, 0x97, 0x47, 0xd2, 0x69, 0x6b, 0xa1, 0x73,
+       0xd9, 0xa3, 0x73, 0xd6, 0xa3, 0x53, 0xf1, 0xe8, 0x5c, 0x5d, 0xa5, 0xb3,
+       0x07, 0x76, 0xd0, 0x6c, 0x9e, 0x00, 0xde, 0x48, 0xc6, 0x9b, 0xcd, 0x34,
+       0xf2, 0xb2, 0xd9, 0xe1, 0x69, 0xb5, 0xe7, 0xaa, 0x27, 0x46, 0xc7, 0x93,
+       0x96, 0x2b, 0x7f, 0x58, 0x81, 0x4c, 0xc3, 0x1e, 0xf3, 0xe2, 0x62, 0x75,
+       0xee, 0x07, 0xba, 0xfb, 0x85, 0x5d, 0xf0, 0x03, 0x4f, 0x23, 0x96, 0x5c,
+       0x1c, 0x3f, 0x6f, 0x49, 0x7e, 0xdb, 0x27, 0x75, 0xd8, 0x7b, 0x0f, 0xdf,
+       0x27, 0x35, 0xa5, 0xeb, 0xe2, 0x78, 0xb5, 0xf6, 0x34, 0xf2, 0x23, 0xf6,
+       0xdf, 0x4e, 0x0c, 0xb6, 0xab, 0x52, 0x8b, 0xec, 0x3a, 0xcb, 0xfd, 0x21,
+       0xf4, 0xab, 0xd4, 0xba, 0x21, 0xf7, 0x6e, 0x55, 0x57, 0xb9, 0x52, 0x0c,
+       0x41, 0x8f, 0x26, 0x6c, 0x3e, 0x84, 0xb6, 0x30, 0xec, 0xa0, 0x0f, 0xed,
+       0x3f, 0xc7, 0xda, 0x8e, 0xa0, 0x7d, 0xa5, 0x73, 0x5c, 0xe1, 0x58, 0x4b,
+       0xce, 0x39, 0x37, 0x11, 0x73, 0xdf, 0x84, 0x1f, 0x1d, 0x44, 0x9f, 0x61,
+       0xf4, 0xf9, 0x14, 0xc6, 0xe1, 0x3b, 0xcd, 0x1b, 0xf1, 0xd4, 0x00, 0x4f,
+       0x7a, 0x0b, 0x4f, 0x0d, 0xf0, 0x03, 0xdf, 0x79, 0x92, 0x35, 0xe8, 0x61,
+       0x39, 0x5a, 0xe4, 0x19, 0x29, 0xbe, 0x17, 0x6f, 0x4a, 0x00, 0x98, 0xb4,
+       0xed, 0x64, 0x34, 0xdc, 0x50, 0xb5, 0x1e, 0xda, 0xd6, 0x50, 0xbc, 0x2a,
+       0x2a, 0xce, 0x44, 0x8e, 0x22, 0x7e, 0xdd, 0x74, 0xba, 0xe5, 0x75, 0x6f,
+       0xac, 0x15, 0xe1, 0xfe, 0xe5, 0xda, 0xb1, 0x8e, 0x95, 0xae, 0x8d, 0xbf,
+       0x6a, 0x19, 0xde, 0xbc, 0x7a, 0x31, 0xd6, 0xaf, 0xa2, 0xef, 0xb5, 0xf1,
+       0xcb, 0xb5, 0x8d, 0xfa, 0xde, 0x44, 0xdf, 0xb6, 0x96, 0xbe, 0x37, 0xd1,
+       0xaf, 0x1b, 0x71, 0xb0, 0x5b, 0xcd, 0x69, 0x16, 0x7c, 0x5d, 0x2f, 0xaa,
+       0xf7, 0xb4, 0x21, 0x77, 0x8e, 0x69, 0x12, 0x53, 0x67, 0xdc, 0x5a, 0x49,
+       0xd4, 0x8c, 0x68, 0xef, 0xa8, 0xf7, 0x28, 0x1b, 0x18, 0xb3, 0x80, 0x7b,
+       0xe7, 0x27, 0xb4, 0x54, 0x35, 0x87, 0x98, 0xf5, 0x30, 0xf1, 0x53, 0xdc,
+       0x46, 0xcc, 0xac, 0x80, 0x5e, 0xad, 0xd8, 0xe0, 0x79, 0x6a, 0xd8, 0xc5,
+       0x2d, 0xe2, 0xec, 0x87, 0x0d, 0x75, 0xae, 0x21, 0xad, 0x6a, 0x76, 0x95,
+       0xa2, 0x98, 0xc9, 0x11, 0x9e, 0x65, 0xf8, 0x0c, 0xd6, 0xe5, 0x57, 0xd0,
+       0x96, 0x44, 0x7c, 0x3c, 0xa0, 0x25, 0xcf, 0x8f, 0xe3, 0xfa, 0x49, 0x5c,
+       0xc3, 0x1f, 0x2f, 0x64, 0x71, 0xff, 0x49, 0x5c, 0x4f, 0x6b, 0xa9, 0x7a,
+       0x16, 0xd7, 0x4f, 0xe1, 0x7a, 0xca, 0x64, 0x9e, 0xf2, 0xaa, 0x95, 0xd1,
+       0x6c, 0xd0, 0xb2, 0xcf, 0x8f, 0xe3, 0xd3, 0x4a, 0x8f, 0xf7, 0xa0, 0xa7,
+       0x22, 0xf7, 0xda, 0x62, 0xe0, 0x69, 0x9f, 0x96, 0xae, 0x76, 0x81, 0xc6,
+       0x00, 0x9e, 0xa7, 0x4d, 0xed, 0xf7, 0xc6, 0x67, 0xcd, 0xe9, 0x63, 0xaa,
+       0xe6, 0x64, 0x24, 0x32, 0xc0, 0xc9, 0x87, 0x91, 0x07, 0x68, 0x92, 0xb6,
+       0x9e, 0x93, 0x42, 0x1c, 0x7e, 0xa5, 0x6a, 0x48, 0x2a, 0x94, 0xc7, 0xef,
+       0xbc, 0x24, 0x47, 0x71, 0xbf, 0x4a, 0x5b, 0x60, 0xbf, 0x3f, 0x95, 0x42,
+       0x99, 0xb8, 0x9f, 0x75, 0x26, 0xd6, 0xa6, 0x58, 0x5f, 0xca, 0x41, 0x06,
+       0x21, 0xda, 0xef, 0x06, 0x35, 0x31, 0xf7, 0x8c, 0x34, 0xe2, 0xb2, 0x96,
+       0xac, 0x72, 0xdf, 0xaf, 0x91, 0xb9, 0x6c, 0xf1, 0xfd, 0xb1, 0x69, 0xee,
+       0x23, 0x16, 0x8c, 0x04, 0xeb, 0x23, 0xaa, 0xbe, 0x1e, 0x77, 0xf7, 0x07,
+       0x5b, 0xcf, 0xa4, 0xf8, 0xeb, 0x85, 0xe3, 0x7e, 0x0d, 0xcf, 0xbb, 0xf5,
+       0xac, 0x54, 0xfd, 0x9d, 0xba, 0xe0, 0x3b, 0x00, 0xe7, 0xa0, 0x8b, 0xcb,
+       0x2a, 0x37, 0xe6, 0x1e, 0xee, 0xbb, 0xe5, 0x54, 0xc8, 0x61, 0x8a, 0xac,
+       0x91, 0xf9, 0xfb, 0x76, 0xbe, 0x1c, 0xd7, 0xf3, 0x4a, 0x3e, 0x67, 0x40,
+       0x53, 0xe2, 0xf4, 0xbb, 0xd9, 0x10, 0xf7, 0xdf, 0xf8, 0x8c, 0x7c, 0xf3,
+       0x2e, 0xdf, 0xe4, 0x99, 0xf2, 0x38, 0x0c, 0xff, 0xc9, 0xf7, 0x2b, 0x9e,
+       0x93, 0x5c, 0x9c, 0x35, 0x1e, 0x03, 0xb1, 0x31, 0x8f, 0xdf, 0x77, 0xe5,
+       0x37, 0xeb, 0xc9, 0x2f, 0x57, 0xfe, 0x2f, 0x4a, 0x87, 0x15, 0x8b, 0xe3,
+       0xf9, 0xb5, 0x8f, 0xbd, 0x4a, 0x77, 0x15, 0x75, 0x7e, 0xd7, 0x97, 0x81,
+       0x5f, 0xbf, 0xdb, 0xd8, 0xf6, 0xc6, 0x2d, 0xf2, 0xf6, 0x10, 0xcf, 0x43,
+       0x0c, 0xda, 0x42, 0xfe, 0x39, 0x0f, 0xc6, 0x30, 0x7f, 0xaf, 0xd5, 0x9f,
+       0x83, 0x3f, 0xcf, 0xfb, 0x95, 0x0f, 0xf9, 0xfd, 0xe4, 0x16, 0xe9, 0xca,
+       0x98, 0x86, 0xc5, 0xd8, 0xf0, 0xb8, 0xb7, 0x3f, 0xf0, 0x7f, 0x43, 0xce,
+       0xae, 0x2c, 0x02, 0x09, 0x99, 0xf5, 0xde, 0xbf, 0xde, 0xc0, 0x1e, 0xd6,
+       0xef, 0x35, 0x37, 0x32, 0x67, 0xad, 0xbb, 0xf3, 0xae, 0x6c, 0x30, 0xef,
+       0x8a, 0x37, 0xef, 0xea, 0x7d, 0xf2, 0x5b, 0x99, 0xb7, 0x31, 0x67, 0xda,
+       0xdc, 0x46, 0xf6, 0x28, 0xea, 0xdd, 0xb0, 0x15, 0x23, 0x18, 0xb4, 0x9d,
+       0x7b, 0xd5, 0x50, 0x99, 0x57, 0xbb, 0x76, 0x79, 0x16, 0xb1, 0xb0, 0x5c,
+       0x76, 0x73, 0xec, 0xb2, 0xc3, 0x5a, 0xf6, 0xbb, 0xf1, 0xc0, 0x77, 0xb9,
+       0xbe, 0xa8, 0xce, 0xbb, 0xcc, 0x3a, 0x6e, 0xdd, 0xab, 0x5c, 0x6e, 0x8d,
+       0xa9, 0x0f, 0x32, 0x9e, 0x0e, 0xe6, 0x65, 0x82, 0xef, 0x94, 0xe3, 0xfa,
+       0x11, 0xb9, 0xb2, 0xa0, 0xf6, 0xac, 0xbc, 0xbd, 0x21, 0xee, 0xf9, 0xa8,
+       0xfd, 0x6f, 0xf8, 0xb5, 0x49, 0xe5, 0xd7, 0x97, 0x17, 0xd4, 0x3d, 0x17,
+       0x2b, 0x39, 0x13, 0xf0, 0xfb, 0xc8, 0x25, 0xac, 0x07, 0xa4, 0x80, 0x9c,
+       0xfb, 0xac, 0x75, 0x78, 0x0b, 0x71, 0x0e, 0x69, 0x2d, 0x83, 0xd6, 0xe5,
+       0x05, 0xd9, 0xc2, 0x33, 0x25, 0x65, 0xb5, 0xcf, 0xe6, 0xd6, 0xc5, 0xa7,
+       0xc5, 0xff, 0x7f, 0x1d, 0x41, 0x2f, 0x16, 0xf2, 0x5c, 0x0b, 0xdf, 0x73,
+       0xa6, 0xaf, 0x40, 0x1e, 0x34, 0xc1, 0x7d, 0x9c, 0x66, 0xd3, 0xad, 0x9b,
+       0x37, 0xb1, 0x2e, 0xda, 0xf8, 0x0e, 0x05, 0xfe, 0x0e, 0xc3, 0x7e, 0xb0,
+       0x4e, 0x56, 0xdb, 0x79, 0xcd, 0xdc, 0xc3, 0xbf, 0x66, 0x60, 0xfb, 0x3f,
+       0xe8, 0xf3, 0x49, 0x14, 0x38, 0x46, 0x00, 0x00, 0x00 };
+
+static const u32 bnx2_TXP_b09FwData[(0xd0/4) + 1] = {
        0x00000000, 0x00000014, 0x00000014, 0x00000014, 0x00000014, 0x00000010,
        0x00000030, 0x00000030, 0x00000000, 0x00000000, 0x00000000, 0x00000010,
        0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00008002, 0x00000000,
@@ -4043,42 +4051,42 @@ static u32 bnx2_TXP_b09FwData[(0xd0/4) + 1] = {
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000,
        0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 };
-static u32 bnx2_TXP_b09FwRodata[(0x30/4) + 1] = {
-       0x08003be8, 0x08003c14, 0x08003c5c, 0x08003c5c, 0x08003ae8, 0x08003b14,
-       0x08003b14, 0x08003c5c, 0x08003c5c, 0x08003c5c, 0x08003b7c, 0x00000000,
+static const u32 bnx2_TXP_b09FwRodata[(0x30/4) + 1] = {
+       0x08004060, 0x0800408c, 0x080040d4, 0x080040d4, 0x08003f60, 0x08003f8c,
+       0x08003f8c, 0x080040d4, 0x080040d4, 0x080040d4, 0x08003ff4, 0x00000000,
        0x00000000 };
-static u32 bnx2_TXP_b09FwBss[(0xa20/4) + 1] = { 0x0 };
-static u32 bnx2_TXP_b09FwSbss[(0x80/4) + 1] = { 0x0 };
+static const u32 bnx2_TXP_b09FwBss[(0xa20/4) + 1] = { 0x0 };
+static const u32 bnx2_TXP_b09FwSbss[(0x8c/4) + 1] = { 0x0 };
 
 static struct fw_info bnx2_txp_fw_09 = {
-       .ver_major                      = 0x1,
-       .ver_minor                      = 0x0,
-       .ver_fix                        = 0x0,
+       .ver_major                      = 0x3,
+       .ver_minor                      = 0x4,
+       .ver_fix                        = 0x3,
 
        .start_addr                     = 0x08000060,
 
        .text_addr                      = 0x08000000,
-       .text_len                       = 0x4194,
+       .text_len                       = 0x4634,
        .text_index                     = 0x0,
        .gz_text                        = bnx2_TXP_b09FwText,
        .gz_text_len                    = sizeof(bnx2_TXP_b09FwText),
 
-       .data_addr                      = 0x080041e0,
+       .data_addr                      = 0x08004680,
        .data_len                       = 0xd0,
        .data_index                     = 0x0,
        .data                           = bnx2_TXP_b09FwData,
 
-       .sbss_addr                      = 0x080042b0,
-       .sbss_len                       = 0x80,
+       .sbss_addr                      = 0x08004750,
+       .sbss_len                       = 0x8c,
        .sbss_index                     = 0x0,
        .sbss                           = bnx2_TXP_b09FwSbss,
 
-       .bss_addr                       = 0x08004330,
+       .bss_addr                       = 0x080047e0,
        .bss_len                        = 0xa20,
        .bss_index                      = 0x0,
        .bss                            = bnx2_TXP_b09FwBss,
 
-       .rodata_addr                    = 0x08004198,
+       .rodata_addr                    = 0x08004638,
        .rodata_len                     = 0x30,
        .rodata_index                   = 0x0,
        .rodata                         = bnx2_TXP_b09FwRodata,
index e824d5d..88efe97 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
index e79700a..b3fa0d6 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
index e2ddd61..a4a2a0e 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
index 8545e84..5603121 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
index cdcfb96..04b4f80 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
index 65925b5..d0f2898 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
index f914478..d384010 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
index 235b177..0a563a8 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
index 3d82d46..50035eb 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/pci.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
index 8434d75..9e04a6b 100644 (file)
@@ -34,7 +34,6 @@
 #define _IXGB_OSDEP_H_
 
 #include <linux/types.h>
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include <asm/io.h>
 #include <linux/interrupt.h>
index d34afb5..75f6f44 100644 (file)
@@ -88,6 +88,23 @@ static unsigned short known_revisions[] =
        0xffff                  /* end of list */
 };
 
+static int jazzsonic_open(struct net_device* dev)
+{
+       if (request_irq(dev->irq, &sonic_interrupt, IRQF_DISABLED, "sonic", dev)) {
+               printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq);
+               return -EAGAIN;
+       }
+       return sonic_open(dev);
+}
+
+static int jazzsonic_close(struct net_device* dev)
+{
+       int err;
+       err = sonic_close(dev);
+       free_irq(dev->irq, dev);
+       return err;
+}
+
 static int __init sonic_probe1(struct net_device *dev)
 {
        static unsigned version_printed;
@@ -169,8 +186,8 @@ static int __init sonic_probe1(struct net_device *dev)
        lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
                             * SONIC_BUS_SCALE(lp->dma_bitmode));
 
-       dev->open = sonic_open;
-       dev->stop = sonic_close;
+       dev->open = jazzsonic_open;
+       dev->stop = jazzsonic_close;
        dev->hard_start_xmit = sonic_send_packet;
        dev->get_stats = sonic_get_stats;
        dev->set_multicast_list = &sonic_multicast_list;
@@ -260,8 +277,6 @@ MODULE_DESCRIPTION("Jazz SONIC ethernet driver");
 module_param(sonic_debug, int, 0);
 MODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)");
 
-#define SONIC_IRQ_FLAG IRQF_DISABLED
-
 #include "sonic.c"
 
 static int __devexit jazz_sonic_device_remove (struct platform_device *pdev)
@@ -269,11 +284,11 @@ static int __devexit jazz_sonic_device_remove (struct platform_device *pdev)
        struct net_device *dev = platform_get_drvdata(pdev);
        struct sonic_local* lp = netdev_priv(dev);
 
-       unregister_netdev (dev);
+       unregister_netdev(dev);
        dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
                          lp->descriptors, lp->descriptors_laddr);
        release_region (dev->base_addr, SONIC_MEM_SIZE);
-       free_netdev (dev);
+       free_netdev(dev);
 
        return 0;
 }
index 0edcd12..6b49fc4 100644 (file)
@@ -81,7 +81,6 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <linux/types.h>
 #include <linux/bitops.h>
 
index a12bb64..90b0c3e 100644 (file)
@@ -14,6 +14,8 @@
 /* 2001-05-15: support for Cabletron ported from old daynaport driver
  * and fixed access to Sonic Sys card which masquerades as a Farallon
  * by rayk@knightsmanor.org */
+/* 2002-12-30: Try to support more cards, some clues from NetBSD driver */
+/* 2003-12-26: Make sure Asante cards always work. */
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -61,25 +63,21 @@ static char version[] =
 #define DAYNA_8390_BASE                0x80000
 #define DAYNA_8390_MEM         0x00000
 
-#define KINETICS_8390_BASE     0x80000
-#define KINETICS_8390_MEM      0x00000
-
 #define CABLETRON_8390_BASE    0x90000
 #define CABLETRON_8390_MEM     0x00000
 
+#define INTERLAN_8390_BASE     0xE0000
+#define INTERLAN_8390_MEM      0xD0000
+
 enum mac8390_type {
        MAC8390_NONE = -1,
        MAC8390_APPLE,
        MAC8390_ASANTE,
-       MAC8390_FARALLON,  /* Apple, Asante, and Farallon are all compatible */
+       MAC8390_FARALLON,
        MAC8390_CABLETRON,
        MAC8390_DAYNA,
        MAC8390_INTERLAN,
        MAC8390_KINETICS,
-       MAC8390_FOCUS,
-       MAC8390_SONICSYS,
-       MAC8390_DAYNA2,
-       MAC8390_DAYNA3,
 };
 
 static const char * cardname[] = {
@@ -90,10 +88,6 @@ static const char * cardname[] = {
        "dayna",
        "interlan",
        "kinetics",
-       "focus",
-       "sonic systems",
-       "dayna2",
-       "dayna_lc",
 };
 
 static int word16[] = {
@@ -104,10 +98,6 @@ static int word16[] = {
        0, /* dayna */
        1, /* interlan */
        0, /* kinetics */
-       1, /* focus (??) */
-       1, /* sonic systems  */
-       1, /* dayna2 */
-       1, /* dayna-lc */
 };
 
 /* on which cards do we use NuBus resources? */
@@ -119,10 +109,12 @@ static int useresources[] = {
        0, /* dayna */
        0, /* interlan */
        0, /* kinetics */
-       0, /* focus (??) */
-       1, /* sonic systems */
-       1, /* dayna2 */
-       1, /* dayna-lc */
+};
+
+enum mac8390_access {
+       ACCESS_UNKNOWN = 0,
+       ACCESS_32,
+       ACCESS_16,
 };
 
 extern enum mac8390_type mac8390_ident(struct nubus_dev * dev);
@@ -134,8 +126,9 @@ static int mac8390_initdev(struct net_device * dev, struct nubus_dev * ndev,
 static int mac8390_open(struct net_device * dev);
 static int mac8390_close(struct net_device * dev);
 static void mac8390_no_reset(struct net_device *dev);
+static void interlan_reset(struct net_device *dev);
 
-/* Sane (32-bit chunk memory read/write) - Apple/Asante/Farallon do this*/
+/* Sane (32-bit chunk memory read/write) - Some Farallon and Apple do this*/
 static void sane_get_8390_hdr(struct net_device *dev,
                              struct e8390_pkt_hdr *hdr, int ring_page);
 static void sane_block_input(struct net_device * dev, int count,
@@ -172,23 +165,93 @@ static void word_memcpy_fromcard(void *tp, const void *fp, int count);
 
 enum mac8390_type __init mac8390_ident(struct nubus_dev * dev)
 {
-       if (dev->dr_sw == NUBUS_DRSW_ASANTE)
-               return MAC8390_ASANTE;
-       if (dev->dr_sw == NUBUS_DRSW_FARALLON)
-               return MAC8390_FARALLON;
-       if (dev->dr_sw == NUBUS_DRSW_KINETICS)
-               return MAC8390_KINETICS;
-       if (dev->dr_sw == NUBUS_DRSW_DAYNA)
-               return MAC8390_DAYNA;
-       if (dev->dr_sw == NUBUS_DRSW_DAYNA2)
-               return MAC8390_DAYNA2;
-       if (dev->dr_sw == NUBUS_DRSW_DAYNA_LC)
-               return MAC8390_DAYNA3;
-       if (dev->dr_hw == NUBUS_DRHW_CABLETRON)
-               return MAC8390_CABLETRON;
+       switch (dev->dr_sw) {
+               case NUBUS_DRSW_3COM:
+                       switch (dev->dr_hw) {
+                               case NUBUS_DRHW_APPLE_SONIC_NB:
+                               case NUBUS_DRHW_APPLE_SONIC_LC:
+                               case NUBUS_DRHW_SONNET:
+                                       return MAC8390_NONE;
+                                       break;
+                               default:
+                                       return MAC8390_APPLE;
+                                       break;
+                       }
+                       break;
+
+               case NUBUS_DRSW_APPLE:
+                       switch (dev->dr_hw) {
+                               case NUBUS_DRHW_ASANTE_LC:
+                                       return MAC8390_NONE;
+                                       break;
+                               case NUBUS_DRHW_CABLETRON:
+                                       return MAC8390_CABLETRON;
+                                       break;
+                               default:
+                                       return MAC8390_APPLE;
+                                       break;
+                       }
+                       break;
+
+               case NUBUS_DRSW_ASANTE:
+                       return MAC8390_ASANTE;
+                       break;
+
+               case NUBUS_DRSW_TECHWORKS:
+               case NUBUS_DRSW_DAYNA2:
+               case NUBUS_DRSW_DAYNA_LC:
+                       if (dev->dr_hw == NUBUS_DRHW_CABLETRON)
+                               return MAC8390_CABLETRON;
+                       else
+                               return MAC8390_APPLE;
+                       break;
+
+               case NUBUS_DRSW_FARALLON:
+                       return MAC8390_FARALLON;
+                       break;
+
+               case NUBUS_DRSW_KINETICS:
+                       switch (dev->dr_hw) {
+                               case NUBUS_DRHW_INTERLAN:
+                                       return MAC8390_INTERLAN;
+                                       break;
+                               default:
+                                       return MAC8390_KINETICS;
+                                       break;
+                       }
+                       break;
+
+               case NUBUS_DRSW_DAYNA:
+                       // These correspond to Dayna Sonic cards
+                       // which use the macsonic driver
+                       if (dev->dr_hw == NUBUS_DRHW_SMC9194 ||
+                               dev->dr_hw == NUBUS_DRHW_INTERLAN )
+                               return MAC8390_NONE;
+                       else
+                               return MAC8390_DAYNA;
+                       break;
+       }
        return MAC8390_NONE;
 }
 
+enum mac8390_access __init mac8390_testio(volatile unsigned long membase)
+{
+       unsigned long outdata = 0xA5A0B5B0;
+       unsigned long indata =  0x00000000;
+       /* Try writing 32 bits */
+       memcpy((char *)membase, (char *)&outdata, 4);
+       /* Now compare them */
+       if (memcmp((char *)&outdata, (char *)membase, 4) == 0)
+               return ACCESS_32;
+       /* Write 16 bit output */
+       word_memcpy_tocard((char *)membase, (char *)&outdata, 4);
+       /* Now read it back */
+       word_memcpy_fromcard((char *)&indata, (char *)membase, 4);
+       if (outdata == indata)
+               return ACCESS_16;
+       return ACCESS_UNKNOWN;
+}
+
 int __init mac8390_memsize(unsigned long membase)
 {
        unsigned long flags;
@@ -287,14 +350,6 @@ struct net_device * __init mac8390_probe(int unit)
                        continue;
                } else {
                        nubus_get_rsrc_mem(dev->dev_addr, &ent, 6);
-                       /* Some Sonic Sys cards masquerade as Farallon */
-                       if (cardtype == MAC8390_FARALLON &&
-                                       dev->dev_addr[0] == 0x0 &&
-                                       dev->dev_addr[1] == 0x40 &&
-                                       dev->dev_addr[2] == 0x10) {
-                               /* This is really Sonic Sys card */
-                               cardtype = MAC8390_SONICSYS;
-                       }
                }
 
                if (useresources[cardtype] == 1) {
@@ -334,6 +389,17 @@ struct net_device * __init mac8390_probe(int unit)
                                                dev->mem_start +
                                                mac8390_memsize(dev->mem_start);
                                        break;
+                               case MAC8390_INTERLAN:
+                                       dev->base_addr =
+                                               (int)(ndev->board->slot_addr +
+                                               INTERLAN_8390_BASE);
+                                       dev->mem_start =
+                                               (int)(ndev->board->slot_addr +
+                                               INTERLAN_8390_MEM);
+                                       dev->mem_end =
+                                               dev->mem_start +
+                                               mac8390_memsize(dev->mem_start);
+                                       break;
                                case MAC8390_CABLETRON:
                                        dev->base_addr =
                                                (int)(ndev->board->slot_addr +
@@ -356,8 +422,8 @@ struct net_device * __init mac8390_probe(int unit)
 
                                default:
                                        printk(KERN_ERR "Card type %s is"
-                                                       " unsupported, sorry\n",
-                                              cardname[cardtype]);
+                                              " unsupported, sorry\n",
+                                              ndev->board->name);
                                        continue;
                        }
                }
@@ -438,7 +504,7 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd
                24,    26,     28,     30
        };
 
-       int access_bitmode;
+       int access_bitmode = 0;
 
        /* Now fill in our stuff */
        dev->open = &mac8390_open;
@@ -468,29 +534,47 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd
 
        /* Fill in model-specific information and functions */
        switch(type) {
-       case MAC8390_SONICSYS:
-               /* 16 bit card, register map is reversed */
-               ei_status.reset_8390 = &mac8390_no_reset;
-               ei_status.block_input = &slow_sane_block_input;
-               ei_status.block_output = &slow_sane_block_output;
-               ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
-               ei_status.reg_offset = back4_offsets;
-               access_bitmode = 0;
-               break;
        case MAC8390_FARALLON:
        case MAC8390_APPLE:
+               switch(mac8390_testio(dev->mem_start)) {
+                       case ACCESS_UNKNOWN:
+                               printk("Don't know how to access card memory!\n");
+                               return -ENODEV;
+                               break;
+
+                       case ACCESS_16:
+                               /* 16 bit card, register map is reversed */
+                               ei_status.reset_8390 = &mac8390_no_reset;
+                               ei_status.block_input = &slow_sane_block_input;
+                               ei_status.block_output = &slow_sane_block_output;
+                               ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
+                               ei_status.reg_offset = back4_offsets;
+                               break;
+
+                       case ACCESS_32:
+                               /* 32 bit card, register map is reversed */
+                               ei_status.reset_8390 = &mac8390_no_reset;
+                               ei_status.block_input = &sane_block_input;
+                               ei_status.block_output = &sane_block_output;
+                               ei_status.get_8390_hdr = &sane_get_8390_hdr;
+                               ei_status.reg_offset = back4_offsets;
+                               access_bitmode = 1;
+                               break;
+               }
+               break;
+
        case MAC8390_ASANTE:
-       case MAC8390_DAYNA2:
-       case MAC8390_DAYNA3:
-               /* 32 bit card, register map is reversed */
-               /* sane */
+               /* Some Asante cards pass the 32 bit test
+                * but overwrite system memory when run at 32 bit.
+                * so we run them all at 16 bit.
+                */
                ei_status.reset_8390 = &mac8390_no_reset;
-               ei_status.block_input = &sane_block_input;
-               ei_status.block_output = &sane_block_output;
-               ei_status.get_8390_hdr = &sane_get_8390_hdr;
+               ei_status.block_input = &slow_sane_block_input;
+               ei_status.block_output = &slow_sane_block_output;
+               ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
                ei_status.reg_offset = back4_offsets;
-               access_bitmode = 1;
                break;
+
        case MAC8390_CABLETRON:
                /* 16 bit card, register map is short forward */
                ei_status.reset_8390 = &mac8390_no_reset;
@@ -498,21 +582,30 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd
                ei_status.block_output = &slow_sane_block_output;
                ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
                ei_status.reg_offset = fwrd2_offsets;
-               access_bitmode = 0;
                break;
+
        case MAC8390_DAYNA:
        case MAC8390_KINETICS:
-               /* 16 bit memory */
+               /* 16 bit memory, register map is forward */
                /* dayna and similar */
                ei_status.reset_8390 = &mac8390_no_reset;
                ei_status.block_input = &dayna_block_input;
                ei_status.block_output = &dayna_block_output;
                ei_status.get_8390_hdr = &dayna_get_8390_hdr;
                ei_status.reg_offset = fwrd4_offsets;
-               access_bitmode = 0;
                break;
+
+       case MAC8390_INTERLAN:
+               /* 16 bit memory, register map is forward */
+               ei_status.reset_8390 = &interlan_reset;
+               ei_status.block_input = &slow_sane_block_input;
+               ei_status.block_output = &slow_sane_block_output;
+               ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
+               ei_status.reg_offset = fwrd4_offsets;
+               break;
+
        default:
-               printk(KERN_ERR "Card type %s is unsupported, sorry\n", cardname[type]);
+               printk(KERN_ERR "Card type %s is unsupported, sorry\n", ndev->board->name);
                return -ENODEV;
        }
 
@@ -530,9 +623,9 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd
                                printk(":");
                }
        }
-       printk(" IRQ %d, shared memory at %#lx-%#lx,  %d-bit access.\n",
-                  dev->irq, dev->mem_start, dev->mem_end-1,
-                  access_bitmode?32:16);
+       printk(" IRQ %d, %d KB shared memory at %#lx,  %d-bit access.\n",
+                  dev->irq, (int)((dev->mem_end - dev->mem_start)/0x1000) * 4,
+                  dev->mem_start, access_bitmode?32:16);
        return 0;
 }
 
@@ -561,6 +654,18 @@ static void mac8390_no_reset(struct net_device *dev)
        return;
 }
 
+static void interlan_reset(struct net_device *dev)
+{
+       unsigned char *target=nubus_slot_addr(IRQ2SLOT(dev->irq));
+       if (ei_debug > 1)
+               printk("Need to reset the NS8390 t=%lu...", jiffies);
+       ei_status.txing = 0;
+       target[0xC0000] = 0;
+       if (ei_debug > 1)
+               printk("reset complete\n");
+       return;
+}
+
 /* dayna_memcpy_fromio/dayna_memcpy_toio */
 /* directly from daynaport.c by Alan Cox */
 static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count)
index 90e695d..26a3b45 100644 (file)
@@ -128,7 +128,7 @@ struct net_local {
 extern void reset_chip(struct net_device *dev);
 #endif
 static int net_open(struct net_device *dev);
-static int     net_send_packet(struct sk_buff *skb, struct net_device *dev);
+static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t net_interrupt(int irq, void *dev_id);
 static void set_multicast_list(struct net_device *dev);
 static void net_rx(struct net_device *dev);
@@ -374,56 +374,39 @@ net_open(struct net_device *dev)
 static int
 net_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
-       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;
-               if (tickssofar < 5)
-                       return 1;
-               if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name,
-                          tx_done(dev) ? "IRQ conflict" : "network cable problem");
-               /* Try to restart the adaptor. */
-               dev->tbusy=0;
-               dev->trans_start = jiffies;
-       }
-
-       /* 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("%s: Transmitter access conflict.\n", dev->name);
-       else {
-               struct net_local *lp = netdev_priv(dev);
-               unsigned long flags;
-
-               if (net_debug > 3)
-                       printk("%s: sent %d byte packet of type %x\n",
-                              dev->name, skb->len,
-                              (skb->data[ETH_ALEN+ETH_ALEN] << 8)
-                              | skb->data[ETH_ALEN+ETH_ALEN+1]);
-
-               /* keep the upload from being interrupted, since we
-                   ask the chip to start transmitting before the
-                   whole packet has been completely uploaded. */
-               local_irq_save(flags);
+       struct net_local *lp = netdev_priv(dev);
+       unsigned long flags;
 
-               /* initiate a transmit sequence */
-               writereg(dev, PP_TxCMD, lp->send_cmd);
-               writereg(dev, PP_TxLength, skb->len);
+       if (net_debug > 3)
+               printk("%s: sent %d byte packet of type %x\n",
+                      dev->name, skb->len,
+                      (skb->data[ETH_ALEN+ETH_ALEN] << 8)
+                      | skb->data[ETH_ALEN+ETH_ALEN+1]);
 
-               /* Test to see if the chip has allocated memory for the packet */
-               if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
-                       /* Gasp!  It hasn't.  But that shouldn't happen since
-                          we're waiting for TxOk, so return 1 and requeue this packet. */
-                       local_irq_restore(flags);
-                       return 1;
-               }
+       /* keep the upload from being interrupted, since we
+          ask the chip to start transmitting before the
+          whole packet has been completely uploaded. */
+       local_irq_save(flags);
+       netif_stop_queue(dev);
 
-               /* Write the contents of the packet */
-               memcpy_toio(dev->mem_start + PP_TxFrame, skb->data, skb->len+1);
+       /* initiate a transmit sequence */
+       writereg(dev, PP_TxCMD, lp->send_cmd);
+       writereg(dev, PP_TxLength, skb->len);
 
+       /* Test to see if the chip has allocated memory for the packet */
+       if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
+               /* Gasp!  It hasn't.  But that shouldn't happen since
+                  we're waiting for TxOk, so return 1 and requeue this packet. */
                local_irq_restore(flags);
-               dev->trans_start = jiffies;
+               return 1;
        }
+
+       /* Write the contents of the packet */
+       skb_copy_from_linear_data(skb, (void *)(dev->mem_start + PP_TxFrame),
+                                 skb->len+1);
+
+       local_irq_restore(flags);
+       dev->trans_start = jiffies;
        dev_kfree_skb (skb);
 
        return 0;
@@ -441,9 +424,6 @@ static irqreturn_t net_interrupt(int irq, void *dev_id)
                printk ("net_interrupt(): irq %d for unknown device.\n", irq);
                return IRQ_NONE;
        }
-       if (dev->interrupt)
-               printk("%s: Re-entering the interrupt handler.\n", dev->name);
-       dev->interrupt = 1;
 
        ioaddr = dev->base_addr;
        lp = netdev_priv(dev);
@@ -464,8 +444,7 @@ static irqreturn_t net_interrupt(int irq, void *dev_id)
                        break;
                case ISQ_TRANSMITTER_EVENT:
                        lp->stats.tx_packets++;
-                       dev->tbusy = 0;
-                       mark_bh(NET_BH);        /* Inform upper layers. */
+                       netif_wake_queue(dev);
                        if ((status & TX_OK) == 0) lp->stats.tx_errors++;
                        if (status & TX_LOST_CRS) lp->stats.tx_carrier_errors++;
                        if (status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++;
@@ -479,8 +458,7 @@ static irqreturn_t net_interrupt(int irq, void *dev_id)
                                    That shouldn't happen since we only ever
                                    load one packet.  Shrug.  Do the right
                                    thing anyway. */
-                               dev->tbusy = 0;
-                               mark_bh(NET_BH);        /* Inform upper layers. */
+                               netif_wake_queue(dev);
                        }
                        if (status & TX_UNDERRUN) {
                                if (net_debug > 0) printk("%s: transmit underrun\n", dev->name);
@@ -497,7 +475,6 @@ static irqreturn_t net_interrupt(int irq, void *dev_id)
                        break;
                }
        }
-       dev->interrupt = 0;
        return IRQ_HANDLED;
 }
 
@@ -531,7 +508,8 @@ net_rx(struct net_device *dev)
        }
        skb_put(skb, length);
 
-       memcpy_fromio(skb->data, dev->mem_start + PP_RxFrame, length);
+       skb_copy_to_linear_data(skb, (void *)(dev->mem_start + PP_RxFrame),
+                               length);
 
        if (net_debug > 3)printk("%s: received %d byte packet of type %x\n",
                                  dev->name, length,
@@ -610,8 +588,6 @@ static void set_multicast_list(struct net_device *dev)
 static int set_mac_address(struct net_device *dev, void *addr)
 {
        int i;
-       if (dev->start)
-               return -EBUSY;
        printk("%s: Setting MAC address to ", dev->name);
        for (i = 0; i < 6; i++)
                printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]);
index 27911c0..fef3193 100644 (file)
  *     Copyright (C) 1998 Alan Cox <alan@redhat.com>
  *
  *     Modified heavily by Joshua M. Thompson based on Dave Huang's NetBSD driver
+ *
+ *     Copyright (C) 2007 Finn Thain
+ *
+ *     Converted to DMA API, converted to unified driver model,
+ *     sync'd some routines with mace.c and fixed various bugs.
  */
 
 
@@ -23,8 +28,9 @@
 #include <linux/string.h>
 #include <linux/crc32.h>
 #include <linux/bitrev.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
 #include <asm/io.h>
-#include <asm/pgtable.h>
 #include <asm/irq.h>
 #include <asm/macintosh.h>
 #include <asm/macints.h>
 #include <asm/page.h>
 #include "mace.h"
 
-#define N_TX_RING      1
-#define N_RX_RING      8
-#define N_RX_PAGES     ((N_RX_RING * 0x0800 + PAGE_SIZE - 1) / PAGE_SIZE)
+static char mac_mace_string[] = "macmace";
+static struct platform_device *mac_mace_device;
+
+#define N_TX_BUFF_ORDER        0
+#define N_TX_RING      (1 << N_TX_BUFF_ORDER)
+#define N_RX_BUFF_ORDER        3
+#define N_RX_RING      (1 << N_RX_BUFF_ORDER)
+
 #define TX_TIMEOUT     HZ
 
-/* Bits in transmit DMA status */
-#define TX_DMA_ERR     0x80
+#define MACE_BUFF_SIZE 0x800
+
+/* Chip rev needs workaround on HW & multicast addr change */
+#define BROKEN_ADDRCHG_REV     0x0941
 
 /* The MACE is simply wired down on a Mac68K box */
 
 
 struct mace_data {
        volatile struct mace *mace;
-       volatile unsigned char *tx_ring;
-       volatile unsigned char *tx_ring_phys;
-       volatile unsigned char *rx_ring;
-       volatile unsigned char *rx_ring_phys;
+       unsigned char *tx_ring;
+       dma_addr_t tx_ring_phys;
+       unsigned char *rx_ring;
+       dma_addr_t rx_ring_phys;
        int dma_intr;
        struct net_device_stats stats;
        int rx_slot, rx_tail;
        int tx_slot, tx_sloti, tx_count;
+       int chipid;
+       struct device *device;
 };
 
 struct mace_frame {
-       u16     len;
-       u16     status;
-       u16     rntpc;
-       u16     rcvcc;
-       u32     pad1;
-       u32     pad2;
+       u8      rcvcnt;
+       u8      pad1;
+       u8      rcvsts;
+       u8      pad2;
+       u8      rntpc;
+       u8      pad3;
+       u8      rcvcc;
+       u8      pad4;
+       u32     pad5;
+       u32     pad6;
        u8      data[1];
        /* And frame continues.. */
 };
 
 #define PRIV_BYTES     sizeof(struct mace_data)
 
-extern void psc_debug_dump(void);
-
 static int mace_open(struct net_device *dev);
 static int mace_close(struct net_device *dev);
 static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev);
 static struct net_device_stats *mace_stats(struct net_device *dev);
 static void mace_set_multicast(struct net_device *dev);
 static int mace_set_address(struct net_device *dev, void *addr);
+static void mace_reset(struct net_device *dev);
 static irqreturn_t mace_interrupt(int irq, void *dev_id);
 static irqreturn_t mace_dma_intr(int irq, void *dev_id);
 static void mace_tx_timeout(struct net_device *dev);
+static void __mace_set_address(struct net_device *dev, void *addr);
 
 /*
  * Load a receive DMA channel with a base address and ring length
@@ -88,7 +107,7 @@ static void mace_tx_timeout(struct net_device *dev);
 
 static void mace_load_rxdma_base(struct net_device *dev, int set)
 {
-       struct mace_data *mp = (struct mace_data *) dev->priv;
+       struct mace_data *mp = netdev_priv(dev);
 
        psc_write_word(PSC_ENETRD_CMD + set, 0x0100);
        psc_write_long(PSC_ENETRD_ADDR + set, (u32) mp->rx_ring_phys);
@@ -103,7 +122,7 @@ static void mace_load_rxdma_base(struct net_device *dev, int set)
 
 static void mace_rxdma_reset(struct net_device *dev)
 {
-       struct mace_data *mp = (struct mace_data *) dev->priv;
+       struct mace_data *mp = netdev_priv(dev);
        volatile struct mace *mace = mp->mace;
        u8 maccc = mace->maccc;
 
@@ -130,7 +149,7 @@ static void mace_rxdma_reset(struct net_device *dev)
 
 static void mace_txdma_reset(struct net_device *dev)
 {
-       struct mace_data *mp = (struct mace_data *) dev->priv;
+       struct mace_data *mp = netdev_priv(dev);
        volatile struct mace *mace = mp->mace;
        u8 maccc;
 
@@ -168,7 +187,7 @@ static void mace_dma_off(struct net_device *dev)
  * model of Macintrash has a MACE (AV macintoshes)
  */
 
-struct net_device *mace_probe(int unit)
+static int __devinit mace_probe(struct platform_device *pdev)
 {
        int j;
        struct mace_data *mp;
@@ -179,24 +198,28 @@ struct net_device *mace_probe(int unit)
        int err;
 
        if (found || macintosh_config->ether_type != MAC_ETHER_MACE)
-               return ERR_PTR(-ENODEV);
+               return -ENODEV;
 
        found = 1;      /* prevent 'finding' one on every device probe */
 
        dev = alloc_etherdev(PRIV_BYTES);
        if (!dev)
-               return ERR_PTR(-ENOMEM);
+               return -ENOMEM;
 
-       if (unit >= 0)
-               sprintf(dev->name, "eth%d", unit);
+       mp = netdev_priv(dev);
+
+       mp->device = &pdev->dev;
+       SET_NETDEV_DEV(dev, &pdev->dev);
+       SET_MODULE_OWNER(dev);
 
-       mp = (struct mace_data *) dev->priv;
        dev->base_addr = (u32)MACE_BASE;
        mp->mace = (volatile struct mace *) MACE_BASE;
 
        dev->irq = IRQ_MAC_MACE;
        mp->dma_intr = IRQ_MAC_MACE_DMA;
 
+       mp->chipid = mp->mace->chipid_hi << 8 | mp->mace->chipid_lo;
+
        /*
         * The PROM contains 8 bytes which total 0xFF when XOR'd
         * together. Due to the usual peculiar apple brain damage
@@ -217,7 +240,7 @@ struct net_device *mace_probe(int unit)
 
        if (checksum != 0xFF) {
                free_netdev(dev);
-               return ERR_PTR(-ENODEV);
+               return -ENODEV;
        }
 
        memset(&mp->stats, 0, sizeof(mp->stats));
@@ -237,22 +260,98 @@ struct net_device *mace_probe(int unit)
 
        err = register_netdev(dev);
        if (!err)
-               return dev;
+               return 0;
 
        free_netdev(dev);
-       return ERR_PTR(err);
+       return err;
+}
+
+/*
+ * Reset the chip.
+ */
+
+static void mace_reset(struct net_device *dev)
+{
+       struct mace_data *mp = netdev_priv(dev);
+       volatile struct mace *mb = mp->mace;
+       int i;
+
+       /* soft-reset the chip */
+       i = 200;
+       while (--i) {
+               mb->biucc = SWRST;
+               if (mb->biucc & SWRST) {
+                       udelay(10);
+                       continue;
+               }
+               break;
+       }
+       if (!i) {
+               printk(KERN_ERR "macmace: cannot reset chip!\n");
+               return;
+       }
+
+       mb->maccc = 0;  /* turn off tx, rx */
+       mb->imr = 0xFF; /* disable all intrs for now */
+       i = mb->ir;
+
+       mb->biucc = XMTSP_64;
+       mb->utr = RTRD;
+       mb->fifocc = XMTFW_8 | RCVFW_64 | XMTFWU | RCVFWU;
+
+       mb->xmtfc = AUTO_PAD_XMIT; /* auto-pad short frames */
+       mb->rcvfc = 0;
+
+       /* load up the hardware address */
+       __mace_set_address(dev, dev->dev_addr);
+
+       /* clear the multicast filter */
+       if (mp->chipid == BROKEN_ADDRCHG_REV)
+               mb->iac = LOGADDR;
+       else {
+               mb->iac = ADDRCHG | LOGADDR;
+               while ((mb->iac & ADDRCHG) != 0)
+                       ;
+       }
+       for (i = 0; i < 8; ++i)
+               mb->ladrf = 0;
+
+       /* done changing address */
+       if (mp->chipid != BROKEN_ADDRCHG_REV)
+               mb->iac = 0;
+
+       mb->plscc = PORTSEL_AUI;
 }
 
 /*
  * Load the address on a mace controller.
  */
 
-static int mace_set_address(struct net_device *dev, void *addr)
+static void __mace_set_address(struct net_device *dev, void *addr)
 {
-       unsigned char *p = addr;
-       struct mace_data *mp = (struct mace_data *) dev->priv;
+       struct mace_data *mp = netdev_priv(dev);
        volatile struct mace *mb = mp->mace;
+       unsigned char *p = addr;
        int i;
+
+       /* load up the hardware address */
+       if (mp->chipid == BROKEN_ADDRCHG_REV)
+               mb->iac = PHYADDR;
+       else {
+               mb->iac = ADDRCHG | PHYADDR;
+               while ((mb->iac & ADDRCHG) != 0)
+                       ;
+       }
+       for (i = 0; i < 6; ++i)
+               mb->padr = dev->dev_addr[i] = p[i];
+       if (mp->chipid != BROKEN_ADDRCHG_REV)
+               mb->iac = 0;
+}
+
+static int mace_set_address(struct net_device *dev, void *addr)
+{
+       struct mace_data *mp = netdev_priv(dev);
+       volatile struct mace *mb = mp->mace;
        unsigned long flags;
        u8 maccc;
 
@@ -260,15 +359,10 @@ static int mace_set_address(struct net_device *dev, void *addr)
 
        maccc = mb->maccc;
 
-       /* load up the hardware address */
-       mb->iac = ADDRCHG | PHYADDR;
-       while ((mb->iac & ADDRCHG) != 0);
-
-       for (i = 0; i < 6; ++i) {
-               mb->padr = dev->dev_addr[i] = p[i];
-       }
+       __mace_set_address(dev, addr);
 
        mb->maccc = maccc;
+
        local_irq_restore(flags);
 
        return 0;
@@ -281,31 +375,11 @@ static int mace_set_address(struct net_device *dev, void *addr)
 
 static int mace_open(struct net_device *dev)
 {
-       struct mace_data *mp = (struct mace_data *) dev->priv;
+       struct mace_data *mp = netdev_priv(dev);
        volatile struct mace *mb = mp->mace;
-#if 0
-       int i;
 
-       i = 200;
-       while (--i) {
-               mb->biucc = SWRST;
-               if (mb->biucc & SWRST) {
-                       udelay(10);
-                       continue;
-               }
-               break;
-       }
-       if (!i) {
-               printk(KERN_ERR "%s: software reset failed!!\n", dev->name);
-               return -EAGAIN;
-       }
-#endif
-
-       mb->biucc = XMTSP_64;
-       mb->fifocc = XMTFW_16 | RCVFW_64 | XMTFWU | RCVFWU | XMTBRST | RCVBRST;
-       mb->xmtfc = AUTO_PAD_XMIT;
-       mb->plscc = PORTSEL_AUI;
-       /* mb->utr = RTRD; */
+       /* reset the chip */
+       mace_reset(dev);
 
        if (request_irq(dev->irq, mace_interrupt, 0, dev->name, dev)) {
                printk(KERN_ERR "%s: can't get irq %d\n", dev->name, dev->irq);
@@ -319,25 +393,21 @@ static int mace_open(struct net_device *dev)
 
        /* Allocate the DMA ring buffers */
 
-       mp->rx_ring = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, N_RX_PAGES);
-       mp->tx_ring = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, 0);
-
-       if (mp->tx_ring==NULL || mp->rx_ring==NULL) {
-               if (mp->rx_ring) free_pages((u32) mp->rx_ring, N_RX_PAGES);
-               if (mp->tx_ring) free_pages((u32) mp->tx_ring, 0);
-               free_irq(dev->irq, dev);
-               free_irq(mp->dma_intr, dev);
-               printk(KERN_ERR "%s: unable to allocate DMA buffers\n", dev->name);
-               return -ENOMEM;
+       mp->tx_ring = dma_alloc_coherent(mp->device,
+                       N_TX_RING * MACE_BUFF_SIZE,
+                       &mp->tx_ring_phys, GFP_KERNEL);
+       if (mp->tx_ring == NULL) {
+               printk(KERN_ERR "%s: unable to allocate DMA tx buffers\n", dev->name);
+               goto out1;
        }
 
-       mp->rx_ring_phys = (unsigned char *) virt_to_bus((void *)mp->rx_ring);
-       mp->tx_ring_phys = (unsigned char *) virt_to_bus((void *)mp->tx_ring);
-
-       /* We want the Rx buffer to be uncached and the Tx buffer to be writethrough */
-
-       kernel_set_cachemode((void *)mp->rx_ring, N_RX_PAGES * PAGE_SIZE, IOMAP_NOCACHE_NONSER);
-       kernel_set_cachemode((void *)mp->tx_ring, PAGE_SIZE, IOMAP_WRITETHROUGH);
+       mp->rx_ring = dma_alloc_coherent(mp->device,
+                       N_RX_RING * MACE_BUFF_SIZE,
+                       &mp->rx_ring_phys, GFP_KERNEL);
+       if (mp->rx_ring == NULL) {
+               printk(KERN_ERR "%s: unable to allocate DMA rx buffers\n", dev->name);
+               goto out2;
+       }
 
        mace_dma_off(dev);
 
@@ -348,34 +418,22 @@ static int mace_open(struct net_device *dev)
        psc_write_word(PSC_ENETWR_CTL, 0x0400);
        psc_write_word(PSC_ENETRD_CTL, 0x0400);
 
-#if 0
-       /* load up the hardware address */
-
-       mb->iac = ADDRCHG | PHYADDR;
-
-       while ((mb->iac & ADDRCHG) != 0);
-
-       for (i = 0; i < 6; ++i)
-               mb->padr = dev->dev_addr[i];
-
-       /* clear the multicast filter */
-       mb->iac = ADDRCHG | LOGADDR;
-
-       while ((mb->iac & ADDRCHG) != 0);
-
-       for (i = 0; i < 8; ++i)
-               mb->ladrf = 0;
-
-       mb->plscc = PORTSEL_GPSI + ENPLSIO;
-
-       mb->maccc = ENXMT | ENRCV;
-       mb->imr = RCVINT;
-#endif
-
        mace_rxdma_reset(dev);
        mace_txdma_reset(dev);
 
+       /* turn it on! */
+       mb->maccc = ENXMT | ENRCV;
+       /* enable all interrupts except receive interrupts */
+       mb->imr = RCVINT;
        return 0;
+
+out2:
+       dma_free_coherent(mp->device, N_TX_RING * MACE_BUFF_SIZE,
+                         mp->tx_ring, mp->tx_ring_phys);
+out1:
+       free_irq(dev->irq, dev);
+       free_irq(mp->dma_intr, dev);
+       return -ENOMEM;
 }
 
 /*
@@ -384,19 +442,13 @@ static int mace_open(struct net_device *dev)
 
 static int mace_close(struct net_device *dev)
 {
-       struct mace_data *mp = (struct mace_data *) dev->priv;
+       struct mace_data *mp = netdev_priv(dev);
        volatile struct mace *mb = mp->mace;
 
        mb->maccc = 0;          /* disable rx and tx     */
        mb->imr = 0xFF;         /* disable all irqs      */
        mace_dma_off(dev);      /* disable rx and tx dma */
 
-       free_irq(dev->irq, dev);
-       free_irq(IRQ_MAC_MACE_DMA, dev);
-
-       free_pages((u32) mp->rx_ring, N_RX_PAGES);
-       free_pages((u32) mp->tx_ring, 0);
-
        return 0;
 }
 
@@ -406,15 +458,20 @@ static int mace_close(struct net_device *dev)
 
 static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
 {
-       struct mace_data *mp = (struct mace_data *) dev->priv;
+       struct mace_data *mp = netdev_priv(dev);
+       unsigned long flags;
 
-       /* Stop the queue if the buffer is full */
+       /* Stop the queue since there's only the one buffer */
 
+       local_irq_save(flags);
+       netif_stop_queue(dev);
        if (!mp->tx_count) {
-               netif_stop_queue(dev);
-               return 1;
+               printk(KERN_ERR "macmace: tx queue running but no free buffers.\n");
+               local_irq_restore(flags);
+               return NETDEV_TX_BUSY;
        }
        mp->tx_count--;
+       local_irq_restore(flags);
 
        mp->stats.tx_packets++;
        mp->stats.tx_bytes += skb->len;
@@ -432,23 +489,26 @@ static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
 
        dev_kfree_skb(skb);
 
-       return 0;
+       dev->trans_start = jiffies;
+       return NETDEV_TX_OK;
 }
 
 static struct net_device_stats *mace_stats(struct net_device *dev)
 {
-       struct mace_data *p = (struct mace_data *) dev->priv;
-       return &p->stats;
+       struct mace_data *mp = netdev_priv(dev);
+       return &mp->stats;
 }
 
 static void mace_set_multicast(struct net_device *dev)
 {
-       struct mace_data *mp = (struct mace_data *) dev->priv;
+       struct mace_data *mp = netdev_priv(dev);
        volatile struct mace *mb = mp->mace;
        int i, j;
        u32 crc;
        u8 maccc;
+       unsigned long flags;
 
+       local_irq_save(flags);
        maccc = mb->maccc;
        mb->maccc &= ~PROM;
 
@@ -473,116 +533,122 @@ static void mace_set_multicast(struct net_device *dev)
                        }
                }
 
-               mb->iac = ADDRCHG | LOGADDR;
-               while (mb->iac & ADDRCHG);
-
-               for (i = 0; i < 8; ++i) {
-                       mb->ladrf = multicast_filter[i];
+               if (mp->chipid == BROKEN_ADDRCHG_REV)
+                       mb->iac = LOGADDR;
+               else {
+                       mb->iac = ADDRCHG | LOGADDR;
+                       while ((mb->iac & ADDRCHG) != 0)
+                               ;
                }
+               for (i = 0; i < 8; ++i)
+                       mb->ladrf = multicast_filter[i];
+               if (mp->chipid != BROKEN_ADDRCHG_REV)
+                       mb->iac = 0;
        }
 
        mb->maccc = maccc;
+       local_irq_restore(flags);
 }
 
-/*
- * Miscellaneous interrupts are handled here. We may end up
- * having to bash the chip on the head for bad errors
- */
-
 static void mace_handle_misc_intrs(struct mace_data *mp, int intr)
 {
        volatile struct mace *mb = mp->mace;
        static int mace_babbles, mace_jabbers;
 
-       if (intr & MPCO) {
+       if (intr & MPCO)
                mp->stats.rx_missed_errors += 256;
-       }
-       mp->stats.rx_missed_errors += mb->mpc;  /* reading clears it */
-
-       if (intr & RNTPCO) {
+       mp->stats.rx_missed_errors += mb->mpc;   /* reading clears it */
+       if (intr & RNTPCO)
                mp->stats.rx_length_errors += 256;
-       }
-       mp->stats.rx_length_errors += mb->rntpc;        /* reading clears it */
-
-       if (intr & CERR) {
+       mp->stats.rx_length_errors += mb->rntpc; /* reading clears it */
+       if (intr & CERR)
                ++mp->stats.tx_heartbeat_errors;
-       }
-       if (intr & BABBLE) {
-               if (mace_babbles++ < 4) {
-                       printk(KERN_DEBUG "mace: babbling transmitter\n");
-               }
-       }
-       if (intr & JABBER) {
-               if (mace_jabbers++ < 4) {
-                       printk(KERN_DEBUG "mace: jabbering transceiver\n");
-               }
-       }
+       if (intr & BABBLE)
+               if (mace_babbles++ < 4)
+                       printk(KERN_DEBUG "macmace: babbling transmitter\n");
+       if (intr & JABBER)
+               if (mace_jabbers++ < 4)
+                       printk(KERN_DEBUG "macmace: jabbering transceiver\n");
 }
 
-/*
- *     A transmit error has occurred. (We kick the transmit side from
- *     the DMA completion)
- */
-
-static void mace_xmit_error(struct net_device *dev)
+static irqreturn_t mace_interrupt(int irq, void *dev_id)
 {
-       struct mace_data *mp = (struct mace_data *) dev->priv;
+       struct net_device *dev = (struct net_device *) dev_id;
+       struct mace_data *mp = netdev_priv(dev);
        volatile struct mace *mb = mp->mace;
-       u8 xmtfs, xmtrc;
+       int intr, fs;
+       unsigned int flags;
 
-       xmtfs = mb->xmtfs;
-       xmtrc = mb->xmtrc;
+       /* don't want the dma interrupt handler to fire */
+       local_irq_save(flags);
 
-       if (xmtfs & XMTSV) {
-               if (xmtfs & UFLO) {
-                       printk("%s: DMA underrun.\n", dev->name);
-                       mp->stats.tx_errors++;
-                       mp->stats.tx_fifo_errors++;
-                       mace_txdma_reset(dev);
+       intr = mb->ir; /* read interrupt register */
+       mace_handle_misc_intrs(mp, intr);
+
+       if (intr & XMTINT) {
+               fs = mb->xmtfs;
+               if ((fs & XMTSV) == 0) {
+                       printk(KERN_ERR "macmace: xmtfs not valid! (fs=%x)\n", fs);
+                       mace_reset(dev);
+                       /*
+                        * XXX mace likes to hang the machine after a xmtfs error.
+                        * This is hard to reproduce, reseting *may* help
+                        */
                }
-               if (xmtfs & RTRY) {
-                       mp->stats.collisions++;
+               /* dma should have finished */
+               if (!mp->tx_count) {
+                       printk(KERN_DEBUG "macmace: tx ring ran out? (fs=%x)\n", fs);
+               }
+               /* Update stats */
+               if (fs & (UFLO|LCOL|LCAR|RTRY)) {
+                       ++mp->stats.tx_errors;
+                       if (fs & LCAR)
+                               ++mp->stats.tx_carrier_errors;
+                       else if (fs & (UFLO|LCOL|RTRY)) {
+                               ++mp->stats.tx_aborted_errors;
+                               if (mb->xmtfs & UFLO) {
+                                       printk(KERN_ERR "%s: DMA underrun.\n", dev->name);
+                                       mp->stats.tx_fifo_errors++;
+                                       mace_txdma_reset(dev);
+                               }
+                       }
                }
        }
-}
 
-/*
- *     A receive interrupt occurred.
- */
+       if (mp->tx_count)
+               netif_wake_queue(dev);
 
-static void mace_recv_interrupt(struct net_device *dev)
-{
-/*     struct mace_data *mp = (struct mace_data *) dev->priv; */
-//     volatile struct mace *mb = mp->mace;
-}
+       local_irq_restore(flags);
 
-/*
- * Process the chip interrupt
- */
+       return IRQ_HANDLED;
+}
 
-static irqreturn_t mace_interrupt(int irq, void *dev_id)
+static void mace_tx_timeout(struct net_device *dev)
 {
-       struct net_device *dev = (struct net_device *) dev_id;
-       struct mace_data *mp = (struct mace_data *) dev->priv;
+       struct mace_data *mp = netdev_priv(dev);
        volatile struct mace *mb = mp->mace;
-       u8 ir;
+       unsigned long flags;
 
-       ir = mb->ir;
-       mace_handle_misc_intrs(mp, ir);
+       local_irq_save(flags);
 
-       if (ir & XMTINT) {
-               mace_xmit_error(dev);
-       }
-       if (ir & RCVINT) {
-               mace_recv_interrupt(dev);
-       }
-       return IRQ_HANDLED;
-}
+       /* turn off both tx and rx and reset the chip */
+       mb->maccc = 0;
+       printk(KERN_ERR "macmace: transmit timeout - resetting\n");
+       mace_txdma_reset(dev);
+       mace_reset(dev);
 
-static void mace_tx_timeout(struct net_device *dev)
-{
-/*     struct mace_data *mp = (struct mace_data *) dev->priv; */
-//     volatile struct mace *mb = mp->mace;
+       /* restart rx dma */
+       mace_rxdma_reset(dev);
+
+       mp->tx_count = N_TX_RING;
+       netif_wake_queue(dev);
+
+       /* turn it on! */
+       mb->maccc = ENXMT | ENRCV;
+       /* enable all interrupts except receive interrupts */
+       mb->imr = RCVINT;
+
+       local_irq_restore(flags);
 }
 
 /*
@@ -591,40 +657,39 @@ static void mace_tx_timeout(struct net_device *dev)
 
 static void mace_dma_rx_frame(struct net_device *dev, struct mace_frame *mf)
 {
-       struct mace_data *mp = (struct mace_data *) dev->priv;
+       struct mace_data *mp = netdev_priv(dev);
        struct sk_buff *skb;
+       unsigned int frame_status = mf->rcvsts;
 
-       if (mf->status & RS_OFLO) {
-               printk("%s: fifo overflow.\n", dev->name);
-               mp->stats.rx_errors++;
-               mp->stats.rx_fifo_errors++;
-       }
-       if (mf->status&(RS_CLSN|RS_FRAMERR|RS_FCSERR))
+       if (frame_status & (RS_OFLO | RS_CLSN | RS_FRAMERR | RS_FCSERR)) {
                mp->stats.rx_errors++;
+               if (frame_status & RS_OFLO) {
+                       printk(KERN_DEBUG "%s: fifo overflow.\n", dev->name);
+                       mp->stats.rx_fifo_errors++;
+               }
+               if (frame_status & RS_CLSN)
+                       mp->stats.collisions++;
+               if (frame_status & RS_FRAMERR)
+                       mp->stats.rx_frame_errors++;
+               if (frame_status & RS_FCSERR)
+                       mp->stats.rx_crc_errors++;
+       } else {
+               unsigned int frame_length = mf->rcvcnt + ((frame_status & 0x0F) << 8 );
 
-       if (mf->status&RS_CLSN) {
-               mp->stats.collisions++;
-       }
-       if (mf->status&RS_FRAMERR) {
-               mp->stats.rx_frame_errors++;
-       }
-       if (mf->status&RS_FCSERR) {
-               mp->stats.rx_crc_errors++;
-       }
-
-       skb = dev_alloc_skb(mf->len+2);
-       if (!skb) {
-               mp->stats.rx_dropped++;
-               return;
+               skb = dev_alloc_skb(frame_length + 2);
+               if (!skb) {
+                       mp->stats.rx_dropped++;
+                       return;
+               }
+               skb_reserve(skb, 2);
+               memcpy(skb_put(skb, frame_length), mf->data, frame_length);
+
+               skb->protocol = eth_type_trans(skb, dev);
+               netif_rx(skb);
+               dev->last_rx = jiffies;
+               mp->stats.rx_packets++;
+               mp->stats.rx_bytes += frame_length;
        }
-       skb_reserve(skb,2);
-       memcpy(skb_put(skb, mf->len), mf->data, mf->len);
-
-       skb->protocol = eth_type_trans(skb, dev);
-       netif_rx(skb);
-       dev->last_rx = jiffies;
-       mp->stats.rx_packets++;
-       mp->stats.rx_bytes += mf->len;
 }
 
 /*
@@ -634,7 +699,7 @@ static void mace_dma_rx_frame(struct net_device *dev, struct mace_frame *mf)
 static irqreturn_t mace_dma_intr(int irq, void *dev_id)
 {
        struct net_device *dev = (struct net_device *) dev_id;
-       struct mace_data *mp = (struct mace_data *) dev->priv;
+       struct mace_data *mp = netdev_priv(dev);
        int left, head;
        u16 status;
        u32 baka;
@@ -661,7 +726,8 @@ static irqreturn_t mace_dma_intr(int irq, void *dev_id)
                /* Loop through the ring buffer and process new packages */
 
                while (mp->rx_tail < head) {
-                       mace_dma_rx_frame(dev, (struct mace_frame *) (mp->rx_ring + (mp->rx_tail * 0x0800)));
+                       mace_dma_rx_frame(dev, (struct mace_frame*) (mp->rx_ring
+                               + (mp->rx_tail * MACE_BUFF_SIZE)));
                        mp->rx_tail++;
                }
 
@@ -688,9 +754,76 @@ static irqreturn_t mace_dma_intr(int irq, void *dev_id)
                psc_write_word(PSC_ENETWR_CMD + mp->tx_sloti, 0x0100);
                mp->tx_sloti ^= 0x10;
                mp->tx_count++;
-               netif_wake_queue(dev);
        }
        return IRQ_HANDLED;
 }
 
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Macintosh MACE ethernet driver");
+
+static int __devexit mac_mace_device_remove (struct platform_device *pdev)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+       struct mace_data *mp = netdev_priv(dev);
+
+       unregister_netdev(dev);
+
+       free_irq(dev->irq, dev);
+       free_irq(IRQ_MAC_MACE_DMA, dev);
+
+       dma_free_coherent(mp->device, N_RX_RING * MACE_BUFF_SIZE,
+                         mp->rx_ring, mp->rx_ring_phys);
+       dma_free_coherent(mp->device, N_TX_RING * MACE_BUFF_SIZE,
+                         mp->tx_ring, mp->tx_ring_phys);
+
+       free_netdev(dev);
+
+       return 0;
+}
+
+static struct platform_driver mac_mace_driver = {
+       .probe  = mace_probe,
+       .remove = __devexit_p(mac_mace_device_remove),
+       .driver = {
+               .name = mac_mace_string,
+       },
+};
+
+static int __init mac_mace_init_module(void)
+{
+       int err;
+
+       if ((err = platform_driver_register(&mac_mace_driver))) {
+               printk(KERN_ERR "Driver registration failed\n");
+               return err;
+       }
+
+       mac_mace_device = platform_device_alloc(mac_mace_string, 0);
+       if (!mac_mace_device)
+               goto out_unregister;
+
+       if (platform_device_add(mac_mace_device)) {
+               platform_device_put(mac_mace_device);
+               mac_mace_device = NULL;
+       }
+
+       return 0;
+
+out_unregister:
+       platform_driver_unregister(&mac_mace_driver);
+
+       return -ENOMEM;
+}
+
+static void __exit mac_mace_cleanup_module(void)
+{
+       platform_driver_unregister(&mac_mace_driver);
+
+       if (mac_mace_device) {
+               platform_device_unregister(mac_mace_device);
+               mac_mace_device = NULL;
+       }
+}
+
+module_init(mac_mace_init_module);
+module_exit(mac_mace_cleanup_module);
index 8ca57a0..e9ecdbf 100644 (file)
@@ -130,6 +130,46 @@ static inline void bit_reverse_addr(unsigned char addr[6])
                addr[i] = bitrev8(addr[i]);
 }
 
+static irqreturn_t macsonic_interrupt(int irq, void *dev_id)
+{
+       irqreturn_t result;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       result = sonic_interrupt(irq, dev_id);
+       local_irq_restore(flags);
+       return result;
+}
+
+static int macsonic_open(struct net_device* dev)
+{
+       if (request_irq(dev->irq, &sonic_interrupt, IRQ_FLG_FAST, "sonic", dev)) {
+               printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq);
+               return -EAGAIN;
+       }
+       /* Under the A/UX interrupt scheme, the onboard SONIC interrupt comes
+        * in at priority level 3. However, we sometimes get the level 2 inter-
+        * rupt as well, which must prevent re-entrance of the sonic handler.
+        */
+       if (dev->irq == IRQ_AUTO_3)
+               if (request_irq(IRQ_NUBUS_9, &macsonic_interrupt, IRQ_FLG_FAST, "sonic", dev)) {
+                       printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, IRQ_NUBUS_9);
+                       free_irq(dev->irq, dev);
+                       return -EAGAIN;
+               }
+       return sonic_open(dev);
+}
+
+static int macsonic_close(struct net_device* dev)
+{
+       int err;
+       err = sonic_close(dev);
+       free_irq(dev->irq, dev);
+       if (dev->irq == IRQ_AUTO_3)
+               free_irq(IRQ_NUBUS_9, dev);
+       return err;
+}
+
 int __init macsonic_init(struct net_device* dev)
 {
        struct sonic_local* lp = netdev_priv(dev);
@@ -160,8 +200,8 @@ int __init macsonic_init(struct net_device* dev)
        lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
                             * SONIC_BUS_SCALE(lp->dma_bitmode));
 
-       dev->open = sonic_open;
-       dev->stop = sonic_close;
+       dev->open = macsonic_open;
+       dev->stop = macsonic_close;
        dev->hard_start_xmit = sonic_send_packet;
        dev->get_stats = sonic_get_stats;
        dev->set_multicast_list = &sonic_multicast_list;
@@ -402,7 +442,7 @@ int __init macsonic_ident(struct nubus_dev* ndev)
            ndev->dr_sw == NUBUS_DRSW_DAYNA)
                return MACSONIC_DAYNA;
 
-       if (ndev->dr_hw == NUBUS_DRHW_SONIC_LC &&
+       if (ndev->dr_hw == NUBUS_DRHW_APPLE_SONIC_LC &&
            ndev->dr_sw == 0) { /* huh? */
                return MACSONIC_APPLE16;
        }
@@ -522,7 +562,7 @@ int __init mac_nubus_sonic_probe(struct net_device* dev)
        return macsonic_init(dev);
 }
 
-static int __init mac_sonic_probe(struct platform_device *device)
+static int __init mac_sonic_probe(struct platform_device *pdev)
 {
        struct net_device *dev;
        struct sonic_local *lp;
@@ -534,8 +574,8 @@ static int __init mac_sonic_probe(struct platform_device *device)
                return -ENOMEM;
 
        lp = netdev_priv(dev);
-       lp->device = &device->dev;
-       SET_NETDEV_DEV(dev, &device->dev);
+       lp->device = &pdev->dev;
+       SET_NETDEV_DEV(dev, &pdev->dev);
        SET_MODULE_OWNER(dev);
 
        /* This will catch fatal stuff like -ENOMEM as well as success */
@@ -572,19 +612,17 @@ MODULE_DESCRIPTION("Macintosh SONIC ethernet driver");
 module_param(sonic_debug, int, 0);
 MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)");
 
-#define SONIC_IRQ_FLAG IRQ_FLG_FAST
-
 #include "sonic.c"
 
-static int __devexit mac_sonic_device_remove (struct platform_device *device)
+static int __devexit mac_sonic_device_remove (struct platform_device *pdev)
 {
-       struct net_device *dev = platform_get_drvdata(device);
+       struct net_device *dev = platform_get_drvdata(pdev);
        struct sonic_local* lp = netdev_priv(dev);
 
-       unregister_netdev (dev);
+       unregister_netdev(dev);
        dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
                          lp->descriptors, lp->descriptors_laddr);
-       free_netdev (dev);
+       free_netdev(dev);
 
        return 0;
 }
@@ -607,9 +645,8 @@ static int __init mac_sonic_init_module(void)
        }
 
        mac_sonic_device = platform_device_alloc(mac_sonic_string, 0);
-       if (!mac_sonic_device) {
+       if (!mac_sonic_device)
                goto out_unregister;
-       }
 
        if (platform_device_add(mac_sonic_device)) {
                platform_device_put(mac_sonic_device);
index c6320c7..8069f3e 100644 (file)
@@ -50,29 +50,6 @@ static int sonic_open(struct net_device *dev)
        if (sonic_debug > 2)
                printk("sonic_open: initializing sonic driver.\n");
 
-       /*
-        * We don't need to deal with auto-irq stuff since we
-        * hardwire the sonic interrupt.
-        */
-/*
- * XXX Horrible work around:  We install sonic_interrupt as fast interrupt.
- * This means that during execution of the handler interrupt are disabled
- * covering another bug otherwise corrupting data.  This doesn't mean
- * this glue works ok under all situations.
- *
- * Note (dhd): this also appears to prevent lockups on the Macintrash
- * when more than one Ethernet card is installed (knock on wood)
- *
- * Note (fthain): whether the above is still true is anyones guess. Certainly
- * the buffer handling algorithms will not tolerate re-entrance without some
- * mutual exclusion added. Anyway, the memcpy has now been eliminated from the
- * rx code to make this a faster "fast interrupt".
- */
-       if (request_irq(dev->irq, &sonic_interrupt, SONIC_IRQ_FLAG, "sonic", dev)) {
-               printk(KERN_ERR "\n%s: unable to get IRQ %d .\n", dev->name, dev->irq);
-               return -EAGAIN;
-       }
-
        for (i = 0; i < SONIC_NUM_RRS; i++) {
                struct sk_buff *skb = dev_alloc_skb(SONIC_RBSIZE + 2);
                if (skb == NULL) {
@@ -169,8 +146,6 @@ static int sonic_close(struct net_device *dev)
                }
        }
 
-       free_irq(dev->irq, dev);        /* release the IRQ */
-
        return 0;
 }
 
@@ -178,8 +153,13 @@ static void sonic_tx_timeout(struct net_device *dev)
 {
        struct sonic_local *lp = netdev_priv(dev);
        int i;
-       /* Stop the interrupts for this */
+       /*
+        * put the Sonic into software-reset mode and
+        * disable all interrupts before releasing DMA buffers
+        */
        SONIC_WRITE(SONIC_IMR, 0);
+       SONIC_WRITE(SONIC_ISR, 0x7fff);
+       SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
        /* We could resend the original skbs. Easier to re-initialise. */
        for (i = 0; i < SONIC_NUM_TDS; i++) {
                if(lp->tx_laddr[i]) {
index 396c3d9..a123ea8 100644 (file)
@@ -1023,10 +1023,11 @@ static int sun3_82586_send_packet(struct sk_buff *skb, struct net_device *dev)
        {
                len = skb->len;
                if (len < ETH_ZLEN) {
-                       memset((char *)p->xmit_cbuffs[p->xmit_count], 0, ETH_ZLEN);
+                       memset((void *)p->xmit_cbuffs[p->xmit_count], 0,
+                              ETH_ZLEN);
                        len = ETH_ZLEN;
                }
-               skb_copy_from_linear_data(skb, p->xmit_cbuffs[p->xmit_count], skb->len);
+               skb_copy_from_linear_data(skb, (void *)p->xmit_cbuffs[p->xmit_count], skb->len);
 
 #if (NUM_XMIT_BUFFS == 1)
 #      ifdef NO_NOPCOMMANDS
index 9488f49..59d6e74 100644 (file)
@@ -1300,9 +1300,11 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
                        msleep(1);
                }
        }
-       tg3_write_mem(tp, NIC_SRAM_WOL_MBOX, WOL_SIGNATURE |
-                                            WOL_DRV_STATE_SHUTDOWN |
-                                            WOL_DRV_WOL | WOL_SET_MAGIC_PKT);
+       if (tp->tg3_flags & TG3_FLAG_WOL_CAP)
+               tg3_write_mem(tp, NIC_SRAM_WOL_MBOX, WOL_SIGNATURE |
+                                                    WOL_DRV_STATE_SHUTDOWN |
+                                                    WOL_DRV_WOL |
+                                                    WOL_SET_MAGIC_PKT);
 
        pci_read_config_word(tp->pdev, pm + PCI_PM_PMC, &power_caps);
 
@@ -2593,10 +2595,8 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
 {
        int current_link_up = 0;
 
-       if (!(mac_status & MAC_STATUS_PCS_SYNCED)) {
-               tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL;
+       if (!(mac_status & MAC_STATUS_PCS_SYNCED))
                goto out;
-       }
 
        if (tp->link_config.autoneg == AUTONEG_ENABLE) {
                u32 flags;
@@ -2614,7 +2614,6 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
 
                        tg3_setup_flow_control(tp, local_adv, remote_adv);
 
-                       tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
                        current_link_up = 1;
                }
                for (i = 0; i < 30; i++) {
@@ -2637,7 +2636,6 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
        } else {
                /* Forcing 1000FD link up. */
                current_link_up = 1;
-               tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
 
                tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS));
                udelay(40);
@@ -3895,8 +3893,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
        entry = tp->tx_prod;
        base_flags = 0;
        mss = 0;
-       if (skb->len > (tp->dev->mtu + ETH_HLEN) &&
-           (mss = skb_shinfo(skb)->gso_size) != 0) {
+       if ((mss = skb_shinfo(skb)->gso_size) != 0) {
                int tcp_opt_len, ip_tcp_len;
 
                if (skb_header_cloned(skb) &&
@@ -4053,8 +4050,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
        if (skb->ip_summed == CHECKSUM_PARTIAL)
                base_flags |= TXD_FLAG_TCPUDP_CSUM;
        mss = 0;
-       if (skb->len > (tp->dev->mtu + ETH_HLEN) &&
-           (mss = skb_shinfo(skb)->gso_size) != 0) {
+       if ((mss = skb_shinfo(skb)->gso_size) != 0) {
                struct iphdr *iph;
                int tcp_opt_len, ip_tcp_len, hdr_len;
 
@@ -5934,7 +5930,7 @@ static int tg3_load_tso_firmware(struct tg3 *tp)
 
 
 /* tp->lock is held. */
-static void __tg3_set_mac_addr(struct tg3 *tp)
+static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1)
 {
        u32 addr_high, addr_low;
        int i;
@@ -5946,6 +5942,8 @@ static void __tg3_set_mac_addr(struct tg3 *tp)
                    (tp->dev->dev_addr[4] <<  8) |
                    (tp->dev->dev_addr[5] <<  0));
        for (i = 0; i < 4; i++) {
+               if (i == 1 && skip_mac_1)
+                       continue;
                tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
                tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
        }
@@ -5972,7 +5970,7 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
 {
        struct tg3 *tp = netdev_priv(dev);
        struct sockaddr *addr = p;
-       int err = 0;
+       int err = 0, skip_mac_1 = 0;
 
        if (!is_valid_ether_addr(addr->sa_data))
                return -EINVAL;
@@ -5983,22 +5981,21 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
                return 0;
 
        if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
-               /* Reset chip so that ASF can re-init any MAC addresses it
-                * needs.
-                */
-               tg3_netif_stop(tp);
-               tg3_full_lock(tp, 1);
+               u32 addr0_high, addr0_low, addr1_high, addr1_low;
 
-               tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
-               err = tg3_restart_hw(tp, 0);
-               if (!err)
-                       tg3_netif_start(tp);
-               tg3_full_unlock(tp);
-       } else {
-               spin_lock_bh(&tp->lock);
-               __tg3_set_mac_addr(tp);
-               spin_unlock_bh(&tp->lock);
+               addr0_high = tr32(MAC_ADDR_0_HIGH);
+               addr0_low = tr32(MAC_ADDR_0_LOW);
+               addr1_high = tr32(MAC_ADDR_1_HIGH);
+               addr1_low = tr32(MAC_ADDR_1_LOW);
+
+               /* Skip MAC addr 1 if ASF is using it. */
+               if ((addr0_high != addr1_high || addr0_low != addr1_low) &&
+                   !(addr1_high == 0 && addr1_low == 0))
+                       skip_mac_1 = 1;
        }
+       spin_lock_bh(&tp->lock);
+       __tg3_set_mac_addr(tp, skip_mac_1);
+       spin_unlock_bh(&tp->lock);
 
        return err;
 }
@@ -6315,7 +6312,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                     tp->rx_jumbo_ptr);
 
        /* Initialize MAC address and backoff seed. */
-       __tg3_set_mac_addr(tp);
+       __tg3_set_mac_addr(tp, 0);
 
        /* MTU + ethernet header + FCS + optional VLAN tag */
        tw32(MAC_RX_MTU_SIZE, tp->dev->mtu + ETH_HLEN + 8);
@@ -6346,8 +6343,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
             tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) ||
            (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)) {
                if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE &&
-                   (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 ||
-                    tp->pci_chip_rev_id == CHIPREV_ID_5705_A2)) {
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
                        rdmac_mode |= RDMAC_MODE_FIFO_SIZE_128;
                } else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) &&
                           !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) {
@@ -6457,6 +6453,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
                        gpio_mask |= GRC_LCLCTRL_GPIO_UART_SEL;
 
+               tp->grc_local_ctrl &= ~gpio_mask;
                tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask;
 
                /* GPIO1 must be driven high for eeprom write protect */
@@ -7036,11 +7033,7 @@ static int tg3_open(struct net_device *dev)
        if (err)
                return err;
 
-       if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
-           (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_AX) &&
-           (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_BX) &&
-           !((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) &&
-             (tp->pdev_peer == tp->pdev))) {
+       if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSI) {
                /* All MSI supporting chips should support tagged
                 * status.  Assert that this is the case.
                 */
@@ -7399,9 +7392,7 @@ static int tg3_close(struct net_device *dev)
 
        tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
        tg3_free_rings(tp);
-       tp->tg3_flags &=
-               ~(TG3_FLAG_INIT_COMPLETE |
-                 TG3_FLAG_GOT_SERDES_FLOWCTL);
+       tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
 
        tg3_full_unlock(tp);
 
@@ -8036,7 +8027,10 @@ static void tg3_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
        struct tg3 *tp = netdev_priv(dev);
 
-       wol->supported = WAKE_MAGIC;
+       if (tp->tg3_flags & TG3_FLAG_WOL_CAP)
+               wol->supported = WAKE_MAGIC;
+       else
+               wol->supported = 0;
        wol->wolopts = 0;
        if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)
                wol->wolopts = WAKE_MAGIC;
@@ -8050,8 +8044,7 @@ static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
        if (wol->wolopts & ~WAKE_MAGIC)
                return -EINVAL;
        if ((wol->wolopts & WAKE_MAGIC) &&
-           tp->tg3_flags2 & TG3_FLG2_ANY_SERDES &&
-           !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP))
+           !(tp->tg3_flags & TG3_FLAG_WOL_CAP))
                return -EINVAL;
 
        spin_lock_bh(&tp->lock);
@@ -9289,7 +9282,7 @@ static void __devinit tg3_get_nvram_size(struct tg3 *tp)
                        return;
                }
        }
-       tp->nvram_size = 0x20000;
+       tp->nvram_size = 0x80000;
 }
 
 static void __devinit tg3_get_nvram_info(struct tg3 *tp)
@@ -9408,33 +9401,31 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp)
 
 static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
 {
-       u32 nvcfg1;
+       u32 nvcfg1, protect = 0;
 
        nvcfg1 = tr32(NVRAM_CFG1);
 
        /* NVRAM protection for TPM */
-       if (nvcfg1 & (1 << 27))
+       if (nvcfg1 & (1 << 27)) {
                tp->tg3_flags2 |= TG3_FLG2_PROTECTED_NVRAM;
+               protect = 1;
+       }
 
-       switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
-               case FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ:
-               case FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ:
-                       tp->nvram_jedecnum = JEDEC_ATMEL;
-                       tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
-                       tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
-
-                       nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
-                       tw32(NVRAM_CFG1, nvcfg1);
-                       break;
-               case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED:
+       nvcfg1 &= NVRAM_CFG1_5752VENDOR_MASK;
+       switch (nvcfg1) {
                case FLASH_5755VENDOR_ATMEL_FLASH_1:
                case FLASH_5755VENDOR_ATMEL_FLASH_2:
                case FLASH_5755VENDOR_ATMEL_FLASH_3:
-               case FLASH_5755VENDOR_ATMEL_FLASH_4:
                        tp->nvram_jedecnum = JEDEC_ATMEL;
                        tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
                        tp->tg3_flags2 |= TG3_FLG2_FLASH;
                        tp->nvram_pagesize = 264;
+                       if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1)
+                               tp->nvram_size = (protect ? 0x3e200 : 0x80000);
+                       else if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_2)
+                               tp->nvram_size = (protect ? 0x1f200 : 0x40000);
+                       else
+                               tp->nvram_size = (protect ? 0x1f200 : 0x20000);
                        break;
                case FLASH_5752VENDOR_ST_M45PE10:
                case FLASH_5752VENDOR_ST_M45PE20:
@@ -9443,6 +9434,12 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
                        tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
                        tp->tg3_flags2 |= TG3_FLG2_FLASH;
                        tp->nvram_pagesize = 256;
+                       if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE10)
+                               tp->nvram_size = (protect ? 0x10000 : 0x20000);
+                       else if (nvcfg1 == FLASH_5752VENDOR_ST_M45PE20)
+                               tp->nvram_size = (protect ? 0x10000 : 0x40000);
+                       else
+                               tp->nvram_size = (protect ? 0x20000 : 0x80000);
                        break;
        }
 }
@@ -9518,6 +9515,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
                }
                tg3_enable_nvram_access(tp);
 
+               tp->nvram_size = 0;
+
                if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
                        tg3_get_5752_nvram_info(tp);
                else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
@@ -9529,7 +9528,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
                else
                        tg3_get_nvram_info(tp);
 
-               tg3_get_nvram_size(tp);
+               if (tp->nvram_size == 0)
+                       tg3_get_nvram_size(tp);
 
                tg3_disable_nvram_access(tp);
                tg3_nvram_unlock(tp);
@@ -9996,8 +9996,8 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
        tp->phy_id = PHY_ID_INVALID;
        tp->led_ctrl = LED_CTRL_MODE_PHY_1;
 
-       /* Assume an onboard device by default.  */
-       tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
+       /* Assume an onboard device and WOL capable by default.  */
+       tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT | TG3_FLAG_WOL_CAP;
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
                if (!(tr32(PCIE_TRANSACTION_CFG) & PCIE_TRANS_CFG_LOM)) {
@@ -10120,8 +10120,9 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                        if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
                                tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE;
                }
-               if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)
-                       tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP;
+               if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES &&
+                   !(nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL))
+                       tp->tg3_flags &= ~TG3_FLAG_WOL_CAP;
 
                if (cfg2 & (1 << 17))
                        tp->tg3_flags2 |= TG3_FLG2_CAPACITIVE_COUPLING;
@@ -10399,6 +10400,8 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp)
        }
 }
 
+static struct pci_dev * __devinit tg3_find_peer(struct tg3 *);
+
 static int __devinit tg3_get_invariants(struct tg3 *tp)
 {
        static struct pci_device_id write_reorder_chipsets[] = {
@@ -10554,6 +10557,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        tp->pci_hdr_type     = (cacheline_sz_reg >> 16) & 0xff;
        tp->pci_bist         = (cacheline_sz_reg >> 24) & 0xff;
 
+       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
+           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714))
+               tp->pdev_peer = tg3_find_peer(tp);
+
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
@@ -10567,6 +10574,14 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                tp->tg3_flags2 |= TG3_FLG2_5705_PLUS;
 
        if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
+               tp->tg3_flags |= TG3_FLAG_SUPPORT_MSI;
+               if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX ||
+                   GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX ||
+                   (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 &&
+                    tp->pci_chip_rev_id <= CHIPREV_ID_5714_A2 &&
+                    tp->pdev_peer == tp->pdev))
+                       tp->tg3_flags &= ~TG3_FLAG_SUPPORT_MSI;
+
                if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
                    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
                    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
@@ -10668,17 +10683,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX)
                tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG;
 
-       /* Back to back register writes can cause problems on this chip,
-        * the workaround is to read back all reg writes except those to
-        * mailbox regs.  See tg3_write_indirect_reg32().
-        *
-        * PCI Express 5750_A0 rev chips need this workaround too.
-        */
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 ||
-           ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
-            tp->pci_chip_rev_id == CHIPREV_ID_5750_A0))
-               tp->tg3_flags |= TG3_FLAG_5701_REG_WRITE_BUG;
-
        if ((pci_state_reg & PCISTATE_BUS_SPEED_HIGH) != 0)
                tp->tg3_flags |= TG3_FLAG_PCI_HIGH_SPEED;
        if ((pci_state_reg & PCISTATE_BUS_32BIT) != 0)
@@ -10702,8 +10706,19 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        /* Various workaround register access methods */
        if (tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG)
                tp->write32 = tg3_write_indirect_reg32;
-       else if (tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG)
+       else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 ||
+                ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
+                 tp->pci_chip_rev_id == CHIPREV_ID_5750_A0)) {
+               /*
+                * Back to back register writes can cause problems on these
+                * chips, the workaround is to read back all reg writes
+                * except those to mailbox regs.
+                *
+                * See tg3_write_indirect_reg32().
+                */
                tp->write32 = tg3_write_flush_reg32;
+       }
+
 
        if ((tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) ||
            (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)) {
@@ -11892,10 +11907,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
                tp->rx_pending = 63;
        }
 
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
-           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714))
-               tp->pdev_peer = tg3_find_peer(tp);
-
        err = tg3_get_device_address(tp);
        if (err) {
                printk(KERN_ERR PFX "Could not obtain valid ethernet address, "
index d515ed2..dcdfc08 100644 (file)
 #define  CHIPREV_ID_5752_A0_HW          0x5000
 #define  CHIPREV_ID_5752_A0             0x6000
 #define  CHIPREV_ID_5752_A1             0x6001
+#define  CHIPREV_ID_5714_A2             0x9002
 #define  CHIPREV_ID_5906_A1             0xc001
 #define  GET_ASIC_REV(CHIP_REV_ID)     ((CHIP_REV_ID) >> 12)
 #define   ASIC_REV_5700                         0x07
@@ -2199,7 +2200,6 @@ struct tg3 {
 #define TG3_FLAG_USE_LINKCHG_REG       0x00000008
 #define TG3_FLAG_USE_MI_INTERRUPT      0x00000010
 #define TG3_FLAG_ENABLE_ASF            0x00000020
-#define TG3_FLAG_5701_REG_WRITE_BUG    0x00000040
 #define TG3_FLAG_POLL_SERDES           0x00000080
 #define TG3_FLAG_MBOX_WRITE_REORDER    0x00000100
 #define TG3_FLAG_PCIX_TARGET_HWBUG     0x00000200
@@ -2215,14 +2215,14 @@ struct tg3 {
 #define TG3_FLAG_PCI_32BIT             0x00080000
 #define TG3_FLAG_SRAM_USE_CONFIG       0x00100000
 #define TG3_FLAG_TX_RECOVERY_PENDING   0x00200000
-#define TG3_FLAG_SERDES_WOL_CAP                0x00400000
+#define TG3_FLAG_WOL_CAP               0x00400000
 #define TG3_FLAG_JUMBO_RING_ENABLE     0x00800000
 #define TG3_FLAG_10_100_ONLY           0x01000000
 #define TG3_FLAG_PAUSE_AUTONEG         0x02000000
 #define TG3_FLAG_IN_RESET_TASK         0x04000000
 #define TG3_FLAG_40BIT_DMA_BUG         0x08000000
 #define TG3_FLAG_BROKEN_CHECKSUMS      0x10000000
-#define TG3_FLAG_GOT_SERDES_FLOWCTL    0x20000000
+#define TG3_FLAG_SUPPORT_MSI           0x20000000
 #define TG3_FLAG_CHIP_RESETTING                0x40000000
 #define TG3_FLAG_INIT_COMPLETE         0x80000000
        u32                             tg3_flags2;
index ed274d6..f8f4d74 100644 (file)
@@ -23,7 +23,6 @@ static const char version[] = "madgemc.c: v0.91 23/01/2000 by Adam Fritzler\n";
 #include <linux/mca.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/trdevice.h>
index 9bbea5c..58d7e5d 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <linux/mca-legacy.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
index 942b839..6c400cc 100644 (file)
@@ -14,7 +14,6 @@
 
 */
 
-#include <linux/pci.h>
 #include <linux/delay.h>
 #include "tulip.h"
 
index 85a521e..be82a2e 100644 (file)
@@ -15,7 +15,6 @@
 */
 
 #include <linux/kernel.h>
-#include <linux/pci.h>
 #include <linux/jiffies.h>
 #include "tulip.h"
 
index c31be0e..4e4a879 100644 (file)
@@ -76,7 +76,6 @@
 
 
 
-#include <linux/pci.h>
 #include "tulip.h"
 #include <linux/delay.h>
 
index df326fe..d2c1f42 100644 (file)
@@ -14,7 +14,6 @@
 
 */
 
-#include <linux/pci.h>
 #include "tulip.h"
 
 
index c840d2e..16f26a8 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/netdevice.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
+#include <linux/pci.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
index ae01555..574737b 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/in.h>
 #include <linux/if_arp.h>
 #include <linux/netdevice.h>
index 74876c0..31e1799 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/in.h>
 #include <linux/if_arp.h>
 #include <linux/netdevice.h>
index 07dbdfb..e24a7b0 100644 (file)
@@ -38,7 +38,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/pci.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/init.h>
index 2a299a0..ef32a5c 100644 (file)
@@ -1971,8 +1971,7 @@ static struct net_device *get_strip_dev(struct strip *strip_info)
                      sizeof(zero_address))) {
                struct net_device *dev;
                read_lock_bh(&dev_base_lock);
-               dev = dev_base;
-               while (dev) {
+               for_each_netdev(dev) {
                        if (dev->type == strip_info->dev->type &&
                            !memcmp(dev->dev_addr,
                                    &strip_info->true_dev_addr,
@@ -1983,7 +1982,6 @@ static struct net_device *get_strip_dev(struct strip *strip_info)
                                read_unlock_bh(&dev_base_lock);
                                return (dev);
                        }
-                       dev = dev->next;
                }
                read_unlock_bh(&dev_base_lock);
        }
index 9bb4db5..a68b3b3 100644 (file)
@@ -22,8 +22,6 @@
 #include <asm/hardware.h>
 #include <asm/parisc-device.h>
 
-#include <linux/pci.h>
-
 struct hppb_card {
        unsigned long hpa;
        struct resource mmio_region;
index 3df82fe..98be288 100644 (file)
@@ -365,7 +365,7 @@ static __inline__ int led_get_net_activity(void)
         * for reading should be OK */
        read_lock(&dev_base_lock);
        rcu_read_lock();
-       for (dev = dev_base; dev; dev = dev->next) {
+       for_each_netdev(dev) {
            struct net_device_stats *stats;
            struct in_device *in_dev = __in_dev_get_rcu(dev);
            if (!in_dev || !in_dev->ifa_list)
index ea1b7a6..815e445 100644 (file)
@@ -520,17 +520,17 @@ static struct pdcspath_entry *pdcspath_entries[] = {
 
 /**
  * pdcs_size_read - Stable Storage size output.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The output buffer to write to.
  */
 static ssize_t
-pdcs_size_read(struct subsystem *entry, char *buf)
+pdcs_size_read(struct kset *kset, char *buf)
 {
        char *out = buf;
-       
-       if (!entry || !buf)
+
+       if (!kset || !buf)
                return -EINVAL;
-               
+
        /* show the size of the stable storage */
        out += sprintf(out, "%ld\n", pdcs_size);
 
@@ -539,17 +539,17 @@ pdcs_size_read(struct subsystem *entry, char *buf)
 
 /**
  * pdcs_auto_read - Stable Storage autoboot/search flag output.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The output buffer to write to.
  * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag
  */
 static ssize_t
-pdcs_auto_read(struct subsystem *entry, char *buf, int knob)
+pdcs_auto_read(struct kset *kset, char *buf, int knob)
 {
        char *out = buf;
        struct pdcspath_entry *pathentry;
 
-       if (!entry || !buf)
+       if (!kset || !buf)
                return -EINVAL;
 
        /* Current flags are stored in primary boot path entry */
@@ -565,40 +565,40 @@ pdcs_auto_read(struct subsystem *entry, char *buf, int knob)
 
 /**
  * pdcs_autoboot_read - Stable Storage autoboot flag output.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The output buffer to write to.
  */
 static inline ssize_t
-pdcs_autoboot_read(struct subsystem *entry, char *buf)
+pdcs_autoboot_read(struct kset *kset, char *buf)
 {
-       return pdcs_auto_read(entry, buf, PF_AUTOBOOT);
+       return pdcs_auto_read(kset, buf, PF_AUTOBOOT);
 }
 
 /**
  * pdcs_autosearch_read - Stable Storage autoboot flag output.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The output buffer to write to.
  */
 static inline ssize_t
-pdcs_autosearch_read(struct subsystem *entry, char *buf)
+pdcs_autosearch_read(struct kset *kset, char *buf)
 {
-       return pdcs_auto_read(entry, buf, PF_AUTOSEARCH);
+       return pdcs_auto_read(kset, buf, PF_AUTOSEARCH);
 }
 
 /**
  * pdcs_timer_read - Stable Storage timer count output (in seconds).
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The output buffer to write to.
  *
  * The value of the timer field correponds to a number of seconds in powers of 2.
  */
 static ssize_t
-pdcs_timer_read(struct subsystem *entry, char *buf)
+pdcs_timer_read(struct kset *kset, char *buf)
 {
        char *out = buf;
        struct pdcspath_entry *pathentry;
 
-       if (!entry || !buf)
+       if (!kset || !buf)
                return -EINVAL;
 
        /* Current flags are stored in primary boot path entry */
@@ -615,15 +615,15 @@ pdcs_timer_read(struct subsystem *entry, char *buf)
 
 /**
  * pdcs_osid_read - Stable Storage OS ID register output.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The output buffer to write to.
  */
 static ssize_t
-pdcs_osid_read(struct subsystem *entry, char *buf)
+pdcs_osid_read(struct kset *kset, char *buf)
 {
        char *out = buf;
 
-       if (!entry || !buf)
+       if (!kset || !buf)
                return -EINVAL;
 
        out += sprintf(out, "%s dependent data (0x%.4x)\n",
@@ -634,18 +634,18 @@ pdcs_osid_read(struct subsystem *entry, char *buf)
 
 /**
  * pdcs_osdep1_read - Stable Storage OS-Dependent data area 1 output.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The output buffer to write to.
  *
  * This can hold 16 bytes of OS-Dependent data.
  */
 static ssize_t
-pdcs_osdep1_read(struct subsystem *entry, char *buf)
+pdcs_osdep1_read(struct kset *kset, char *buf)
 {
        char *out = buf;
        u32 result[4];
 
-       if (!entry || !buf)
+       if (!kset || !buf)
                return -EINVAL;
 
        if (pdc_stable_read(PDCS_ADDR_OSD1, &result, sizeof(result)) != PDC_OK)
@@ -661,18 +661,18 @@ pdcs_osdep1_read(struct subsystem *entry, char *buf)
 
 /**
  * pdcs_diagnostic_read - Stable Storage Diagnostic register output.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The output buffer to write to.
  *
  * I have NFC how to interpret the content of that register ;-).
  */
 static ssize_t
-pdcs_diagnostic_read(struct subsystem *entry, char *buf)
+pdcs_diagnostic_read(struct kset *kset, char *buf)
 {
        char *out = buf;
        u32 result;
 
-       if (!entry || !buf)
+       if (!kset || !buf)
                return -EINVAL;
 
        /* get diagnostic */
@@ -686,18 +686,18 @@ pdcs_diagnostic_read(struct subsystem *entry, char *buf)
 
 /**
  * pdcs_fastsize_read - Stable Storage FastSize register output.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The output buffer to write to.
  *
  * This register holds the amount of system RAM to be tested during boot sequence.
  */
 static ssize_t
-pdcs_fastsize_read(struct subsystem *entry, char *buf)
+pdcs_fastsize_read(struct kset *kset, char *buf)
 {
        char *out = buf;
        u32 result;
 
-       if (!entry || !buf)
+       if (!kset || !buf)
                return -EINVAL;
 
        /* get fast-size */
@@ -715,13 +715,13 @@ pdcs_fastsize_read(struct subsystem *entry, char *buf)
 
 /**
  * pdcs_osdep2_read - Stable Storage OS-Dependent data area 2 output.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The output buffer to write to.
  *
  * This can hold pdcs_size - 224 bytes of OS-Dependent data, when available.
  */
 static ssize_t
-pdcs_osdep2_read(struct subsystem *entry, char *buf)
+pdcs_osdep2_read(struct kset *kset, char *buf)
 {
        char *out = buf;
        unsigned long size;
@@ -733,7 +733,7 @@ pdcs_osdep2_read(struct subsystem *entry, char *buf)
 
        size = pdcs_size - 224;
 
-       if (!entry || !buf)
+       if (!kset || !buf)
                return -EINVAL;
 
        for (i=0; i<size; i+=4) {
@@ -748,7 +748,7 @@ pdcs_osdep2_read(struct subsystem *entry, char *buf)
 
 /**
  * pdcs_auto_write - This function handles autoboot/search flag modifying.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The input buffer to read from.
  * @count: The number of bytes to be read.
  * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag
@@ -758,7 +758,7 @@ pdcs_osdep2_read(struct subsystem *entry, char *buf)
  *     \"n\" (n == 0 or 1) to toggle AutoBoot Off or On
  */
 static ssize_t
-pdcs_auto_write(struct subsystem *entry, const char *buf, size_t count, int knob)
+pdcs_auto_write(struct kset *kset, const char *buf, size_t count, int knob)
 {
        struct pdcspath_entry *pathentry;
        unsigned char flags;
@@ -768,7 +768,7 @@ pdcs_auto_write(struct subsystem *entry, const char *buf, size_t count, int knob
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
 
-       if (!entry || !buf || !count)
+       if (!kset || !buf || !count)
                return -EINVAL;
 
        /* We'll use a local copy of buf */
@@ -823,7 +823,7 @@ parse_error:
 
 /**
  * pdcs_autoboot_write - This function handles autoboot flag modifying.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The input buffer to read from.
  * @count: The number of bytes to be read.
  *
@@ -832,14 +832,14 @@ parse_error:
  *     \"n\" (n == 0 or 1) to toggle AutoSearch Off or On
  */
 static inline ssize_t
-pdcs_autoboot_write(struct subsystem *entry, const char *buf, size_t count)
+pdcs_autoboot_write(struct kset *kset, const char *buf, size_t count)
 {
-       return pdcs_auto_write(entry, buf, count, PF_AUTOBOOT);
+       return pdcs_auto_write(kset, buf, count, PF_AUTOBOOT);
 }
 
 /**
  * pdcs_autosearch_write - This function handles autosearch flag modifying.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The input buffer to read from.
  * @count: The number of bytes to be read.
  *
@@ -848,14 +848,14 @@ pdcs_autoboot_write(struct subsystem *entry, const char *buf, size_t count)
  *     \"n\" (n == 0 or 1) to toggle AutoSearch Off or On
  */
 static inline ssize_t
-pdcs_autosearch_write(struct subsystem *entry, const char *buf, size_t count)
+pdcs_autosearch_write(struct kset *kset, const char *buf, size_t count)
 {
-       return pdcs_auto_write(entry, buf, count, PF_AUTOSEARCH);
+       return pdcs_auto_write(kset, buf, count, PF_AUTOSEARCH);
 }
 
 /**
  * pdcs_osdep1_write - Stable Storage OS-Dependent data area 1 input.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The input buffer to read from.
  * @count: The number of bytes to be read.
  *
@@ -864,14 +864,14 @@ pdcs_autosearch_write(struct subsystem *entry, const char *buf, size_t count)
  * its input buffer.
  */
 static ssize_t
-pdcs_osdep1_write(struct subsystem *entry, const char *buf, size_t count)
+pdcs_osdep1_write(struct kset *kset, const char *buf, size_t count)
 {
        u8 in[16];
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
 
-       if (!entry || !buf || !count)
+       if (!kset || !buf || !count)
                return -EINVAL;
 
        if (unlikely(pdcs_osid != OS_ID_LINUX))
@@ -892,7 +892,7 @@ pdcs_osdep1_write(struct subsystem *entry, const char *buf, size_t count)
 
 /**
  * pdcs_osdep2_write - Stable Storage OS-Dependent data area 2 input.
- * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @kset: An allocated and populated struct kset. We don't use it tho.
  * @buf: The input buffer to read from.
  * @count: The number of bytes to be read.
  *
@@ -901,7 +901,7 @@ pdcs_osdep1_write(struct subsystem *entry, const char *buf, size_t count)
  * constructing its input buffer.
  */
 static ssize_t
-pdcs_osdep2_write(struct subsystem *entry, const char *buf, size_t count)
+pdcs_osdep2_write(struct kset *kset, const char *buf, size_t count)
 {
        unsigned long size;
        unsigned short i;
@@ -910,7 +910,7 @@ pdcs_osdep2_write(struct subsystem *entry, const char *buf, size_t count)
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
 
-       if (!entry || !buf || !count)
+       if (!kset || !buf || !count)
                return -EINVAL;
 
        if (unlikely(pdcs_size <= 224))
index 5ea5bc7..7a1d6d5 100644 (file)
@@ -1,10 +1,14 @@
 #
 # PCI configuration
 #
+config ARCH_SUPPORTS_MSI
+       bool
+       default n
+
 config PCI_MSI
        bool "Message Signaled Interrupts (MSI and MSI-X)"
        depends on PCI
-       depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64 || SPARC64
+       depends on ARCH_SUPPORTS_MSI
        help
           This allows device drivers to enable MSI (Message Signaled
           Interrupts).  Message Signaled Interrupts enable a device to
@@ -17,31 +21,6 @@ config PCI_MSI
 
           If you don't know what to do here, say N.
 
-config PCI_MULTITHREAD_PROBE
-       bool "PCI Multi-threaded probe (EXPERIMENTAL)"
-       depends on PCI && EXPERIMENTAL && BROKEN
-       help
-         Say Y here if you want the PCI core to spawn a new thread for
-         every PCI device that is probed.  This can cause a huge
-         speedup in boot times on multiprocessor machines, and even a
-         smaller speedup on single processor machines.
-
-         But it can also cause lots of bad things to happen.  A number
-         of PCI drivers cannot properly handle running in this way,
-         some will just not work properly at all, while others might
-         decide to blow up power supplies with a huge load all at once,
-         so use this option at your own risk.
-
-         It is very unwise to use this option if you are not using a
-         boot process that can handle devices being created in any
-         order.  A program that can create persistent block and network
-         device names (like udev) is a good idea if you wish to use
-         this option.
-
-         Again, use this option at your own risk, you have been warned!
-
-         When in doubt, say N.
-
 config PCI_DEBUG
        bool "PCI Debugging"
        depends on PCI && DEBUG_KERNEL
index aadaa3c..9e5ea07 100644 (file)
@@ -77,7 +77,7 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
  * This adds a single pci device to the global
  * device list and adds sysfs and procfs entries
  */
-int __devinit pci_bus_add_device(struct pci_dev *dev)
+int pci_bus_add_device(struct pci_dev *dev)
 {
        int retval;
        retval = device_add(&dev->dev);
@@ -105,7 +105,7 @@ int __devinit pci_bus_add_device(struct pci_dev *dev)
  *
  * Call hotplug for each new devices.
  */
-void __devinit pci_bus_add_devices(struct pci_bus *bus)
+void pci_bus_add_devices(struct pci_bus *bus)
 {
        struct pci_dev *dev;
        int retval;
index be92695..63d6275 100644 (file)
@@ -2,9 +2,7 @@
 # PCI Hotplug support
 #
 
-menu "PCI Hotplug Support"
-
-config HOTPLUG_PCI
+menuconfig HOTPLUG_PCI
        tristate "Support for PCI Hotplug (EXPERIMENTAL)"
        depends on PCI && EXPERIMENTAL && HOTPLUG
        ---help---
@@ -17,9 +15,10 @@ config HOTPLUG_PCI
 
          When in doubt, say N.
 
+if HOTPLUG_PCI
+
 config HOTPLUG_PCI_FAKE
        tristate "Fake PCI Hotplug driver"
-       depends on HOTPLUG_PCI
        help
          Say Y here if you want to use the fake PCI hotplug driver. It can
          be used to simulate PCI hotplug events if even if your system is
@@ -42,7 +41,7 @@ config HOTPLUG_PCI_FAKE
 
 config HOTPLUG_PCI_COMPAQ
        tristate "Compaq PCI Hotplug driver"
-       depends on HOTPLUG_PCI && X86 && PCI_BIOS
+       depends on X86 && PCI_BIOS
        help
          Say Y here if you have a motherboard with a Compaq PCI Hotplug
          controller.
@@ -64,7 +63,7 @@ config HOTPLUG_PCI_COMPAQ_NVRAM
 
 config HOTPLUG_PCI_IBM
        tristate "IBM PCI Hotplug driver"
-       depends on HOTPLUG_PCI && X86_IO_APIC && X86 && PCI_BIOS
+       depends on X86_IO_APIC && X86 && PCI_BIOS
        help
          Say Y here if you have a motherboard with a IBM PCI Hotplug
          controller.
@@ -76,7 +75,6 @@ config HOTPLUG_PCI_IBM
 
 config HOTPLUG_PCI_ACPI
        tristate "ACPI PCI Hotplug driver"
-       depends on HOTPLUG_PCI
        depends on (!ACPI_DOCK && ACPI) || (ACPI_DOCK)
        help
          Say Y here if you have a system that supports PCI Hotplug using
@@ -101,7 +99,6 @@ config HOTPLUG_PCI_ACPI_IBM
 
 config HOTPLUG_PCI_CPCI
        bool "CompactPCI Hotplug driver"
-       depends on HOTPLUG_PCI
        help
          Say Y here if you have a CompactPCI system card with CompactPCI
          hotswap support per the PICMG 2.1 specification.
@@ -110,7 +107,7 @@ config HOTPLUG_PCI_CPCI
 
 config HOTPLUG_PCI_CPCI_ZT5550
        tristate "Ziatech ZT5550 CompactPCI Hotplug driver"
-       depends on HOTPLUG_PCI && HOTPLUG_PCI_CPCI && X86
+       depends on HOTPLUG_PCI_CPCI && X86
        help
          Say Y here if you have an Performance Technologies (formerly Intel,
           formerly just Ziatech) Ziatech ZT5550 CompactPCI system card.
@@ -122,7 +119,7 @@ config HOTPLUG_PCI_CPCI_ZT5550
 
 config HOTPLUG_PCI_CPCI_GENERIC
        tristate "Generic port I/O CompactPCI Hotplug driver"
-       depends on HOTPLUG_PCI && HOTPLUG_PCI_CPCI && X86
+       depends on HOTPLUG_PCI_CPCI && X86
        help
          Say Y here if you have a CompactPCI system card that exposes the #ENUM
          hotswap signal as a bit in a system register that can be read through
@@ -135,7 +132,6 @@ config HOTPLUG_PCI_CPCI_GENERIC
 
 config HOTPLUG_PCI_SHPC
        tristate "SHPC PCI Hotplug driver"
-       depends on HOTPLUG_PCI
        help
          Say Y here if you have a motherboard with a SHPC PCI Hotplug
          controller.
@@ -147,7 +143,7 @@ config HOTPLUG_PCI_SHPC
 
 config HOTPLUG_PCI_RPA
        tristate "RPA PCI Hotplug driver"
-       depends on HOTPLUG_PCI && PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE
+       depends on PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE
        help
          Say Y here if you have a RPA system that supports PCI Hotplug.
 
@@ -170,12 +166,11 @@ config HOTPLUG_PCI_RPA_DLPAR
 
 config HOTPLUG_PCI_SGI
        tristate "SGI PCI Hotplug Support"
-       depends on HOTPLUG_PCI && (IA64_SGI_SN2 || IA64_GENERIC)
+       depends on IA64_SGI_SN2 || IA64_GENERIC
        help
          Say Y here if you want to use the SGI Altix Hotplug
          Driver for PCI devices.
 
          When in doubt, say N.
 
-endmenu
-
+endif # HOTPLUG_PCI
index 7f03881..e7322c2 100644 (file)
@@ -424,7 +424,7 @@ static int __init ibm_acpiphp_init(void)
        int retval = 0;
        acpi_status status;
        struct acpi_device *device;
-       struct kobject *sysdir = &pci_hotplug_slots_subsys.kset.kobj;
+       struct kobject *sysdir = &pci_hotplug_slots_subsys.kobj;
 
        dbg("%s\n", __FUNCTION__);
 
@@ -471,7 +471,7 @@ init_return:
 static void __exit ibm_acpiphp_exit(void)
 {
        acpi_status status;
-       struct kobject *sysdir = &pci_hotplug_slots_subsys.kset.kobj;
+       struct kobject *sysdir = &pci_hotplug_slots_subsys.kobj;
 
        dbg("%s\n", __FUNCTION__);
 
index 1c12e91..41f6a8d 100644 (file)
@@ -296,13 +296,17 @@ static struct pci_driver zt5550_hc_driver = {
 static int __init zt5550_init(void)
 {
        struct resource* r;
+       int rc;
 
        info(DRIVER_DESC " version: " DRIVER_VERSION);
        r = request_region(ENUM_PORT, 1, "#ENUM hotswap signal register");
        if(!r)
                return -EBUSY;
 
-       return pci_register_driver(&zt5550_hc_driver);
+       rc = pci_register_driver(&zt5550_hc_driver);
+       if(rc < 0)
+               release_region(ENUM_PORT, 1);
+       return rc;
 }
 
 static void __exit
index e27907c..027f686 100644 (file)
@@ -238,7 +238,7 @@ static void pci_rescan_bus(const struct pci_bus *bus)
 {
        unsigned int devfn;
        struct pci_dev *dev;
-       dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
+       dev = alloc_pci_dev();
        if (!dev)
                return;
 
index f5d632e..63f3bd1 100644 (file)
@@ -62,7 +62,7 @@ static int debug;
 
 static LIST_HEAD(pci_hotplug_slot_list);
 
-struct subsystem pci_hotplug_slots_subsys;
+struct kset pci_hotplug_slots_subsys;
 
 static ssize_t hotplug_slot_attr_show(struct kobject *kobj,
                struct attribute *attr, char *buf)
@@ -764,7 +764,7 @@ static int __init pci_hotplug_init (void)
 {
        int result;
 
-       kset_set_kset_s(&pci_hotplug_slots_subsys, pci_bus_type.subsys);
+       kobj_set_kset_s(&pci_hotplug_slots_subsys, pci_bus_type.subsys);
        result = subsystem_register(&pci_hotplug_slots_subsys);
        if (result) {
                err("Register subsys with error %d\n", result);
index d19fcae..ccc5762 100644 (file)
@@ -43,6 +43,7 @@ extern int pciehp_poll_mode;
 extern int pciehp_poll_time;
 extern int pciehp_debug;
 extern int pciehp_force;
+extern struct workqueue_struct *pciehp_wq;
 
 #define dbg(format, arg...)                                            \
        do {                                                            \
@@ -70,14 +71,16 @@ struct slot {
        struct list_head        slot_list;
        char name[SLOT_NAME_SIZE];
        unsigned long last_emi_toggle;
+       struct delayed_work work;       /* work for button event */
+       struct mutex lock;
 };
 
 struct event_info {
        u32 event_type;
-       u8 hp_slot;
+       struct slot *p_slot;
+       struct work_struct work;
 };
 
-#define MAX_EVENTS             10
 struct controller {
        struct controller *next;
        struct mutex crit_sect;         /* critical section mutex */
@@ -86,11 +89,9 @@ struct controller {
        int slot_num_inc;               /* 1 or -1 */
        struct pci_dev *pci_dev;
        struct list_head slot_list;
-       struct event_info event_queue[MAX_EVENTS];
        struct slot *slot;
        struct hpc_ops *hpc_ops;
        wait_queue_head_t queue;        /* sleep & wake process */
-       u8 next_event;
        u8 bus;
        u8 device;
        u8 function;
@@ -149,21 +150,17 @@ struct controller {
 #define HP_SUPR_RM(cap)                (cap & HP_SUPR_RM_SUP)
 #define EMI(cap)               (cap & EMI_PRSN)
 
-extern int pciehp_event_start_thread(void);
-extern void pciehp_event_stop_thread(void);
-extern int pciehp_enable_slot(struct slot *slot);
-extern int pciehp_disable_slot(struct slot *slot);
+extern int pciehp_sysfs_enable_slot(struct slot *slot);
+extern int pciehp_sysfs_disable_slot(struct slot *slot);
 extern u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl);
 extern u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl);
 extern u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl);
 extern u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl);
 extern int pciehp_configure_device(struct slot *p_slot);
 extern int pciehp_unconfigure_device(struct slot *p_slot);
+extern void pciehp_queue_pushbutton_work(struct work_struct *work);
 int pcie_init(struct controller *ctrl, struct pcie_device *dev);
 
-/* Global variables */
-extern struct controller *pciehp_ctrl_list;
-
 static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
 {
        struct slot *slot;
index a92eda6..e5d3f0b 100644 (file)
@@ -41,7 +41,7 @@ int pciehp_debug;
 int pciehp_poll_mode;
 int pciehp_poll_time;
 int pciehp_force;
-struct controller *pciehp_ctrl_list;
+struct workqueue_struct *pciehp_wq;
 
 #define DRIVER_VERSION "0.4"
 #define DRIVER_AUTHOR  "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -62,7 +62,6 @@ MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing"
 
 #define PCIE_MODULE_NAME "pciehp"
 
-static int pcie_start_thread (void);
 static int set_attention_status (struct hotplug_slot *slot, u8 value);
 static int enable_slot         (struct hotplug_slot *slot);
 static int disable_slot                (struct hotplug_slot *slot);
@@ -229,6 +228,8 @@ static int init_slots(struct controller *ctrl)
                slot->device = ctrl->slot_device_offset + i;
                slot->hpc_ops = ctrl->hpc_ops;
                slot->number = ctrl->first_slot;
+               mutex_init(&slot->lock);
+               INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
 
                /* register this slot with the hotplug pci core */
                hotplug_slot->private = slot;
@@ -286,6 +287,9 @@ static void cleanup_slots(struct controller *ctrl)
                if (EMI(ctrl->ctrlcap))
                        sysfs_remove_file(&slot->hotplug_slot->kobj,
                                &hotplug_slot_attr_lock.attr);
+               cancel_delayed_work(&slot->work);
+               flush_scheduled_work();
+               flush_workqueue(pciehp_wq);
                pci_hp_deregister(slot->hotplug_slot);
        }
 }
@@ -314,7 +318,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
 
        dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 
-       return pciehp_enable_slot(slot);
+       return pciehp_sysfs_enable_slot(slot);
 }
 
 
@@ -324,7 +328,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
 
        dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 
-       return pciehp_disable_slot(slot);
+       return pciehp_sysfs_disable_slot(slot);
 }
 
 static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
@@ -466,17 +470,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
 
        t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
 
-       /*      Finish setting up the hot plug ctrl device */
-       ctrl->next_event = 0;
-
-       if (!pciehp_ctrl_list) {
-               pciehp_ctrl_list = ctrl;
-               ctrl->next = NULL;
-       } else {
-               ctrl->next = pciehp_ctrl_list;
-               pciehp_ctrl_list = ctrl;
-       }
-
        t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
        if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
                rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
@@ -496,48 +489,14 @@ err_out_none:
        return -ENODEV;
 }
 
-
-static int pcie_start_thread(void)
+static void pciehp_remove (struct pcie_device *dev)
 {
-       int retval = 0;
-       
-       dbg("Initialize + Start the notification/polling mechanism \n");
-
-       retval = pciehp_event_start_thread();
-       if (retval) {
-               dbg("pciehp_event_start_thread() failed\n");
-               return retval;
-       }
-
-       return retval;
-}
-
-static void __exit unload_pciehpd(void)
-{
-       struct controller *ctrl;
-       struct controller *tctrl;
-
-       ctrl = pciehp_ctrl_list;
-
-       while (ctrl) {
-               cleanup_slots(ctrl);
+       struct pci_dev *pdev = dev->port;
+       struct controller *ctrl = pci_get_drvdata(pdev);
 
-               ctrl->hpc_ops->release_ctlr(ctrl);
-
-               tctrl = ctrl;
-               ctrl = ctrl->next;
-
-               kfree(tctrl);
-       }
-
-       /* Stop the notification mechanism */
-       pciehp_event_stop_thread();
-
-}
-
-static void pciehp_remove (struct pcie_device *device)
-{
-       /* XXX - Needs to be adapted to device driver model */
+       cleanup_slots(ctrl);
+       ctrl->hpc_ops->release_ctlr(ctrl);
+       kfree(ctrl);
 }
 
 #ifdef CONFIG_PM
@@ -585,31 +544,18 @@ static int __init pcied_init(void)
        pciehp_poll_mode = 1;
 #endif
 
-       retval = pcie_start_thread();
-       if (retval)
-               goto error_hpc_init;
-
        retval = pcie_port_service_register(&hpdriver_portdrv);
        dbg("pcie_port_service_register = %d\n", retval);
        info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
        if (retval)
                dbg("%s: Failure to register service\n", __FUNCTION__);
-
-error_hpc_init:
-       if (retval) {
-               pciehp_event_stop_thread();
-       };
-
        return retval;
 }
 
 static void __exit pcied_cleanup(void)
 {
        dbg("unload_pciehpd()\n");
-       unload_pciehpd();
-
        pcie_port_service_unregister(&hpdriver_portdrv);
-
        info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
 }
 
index 4283ef5..7f22caa 100644 (file)
 #include <linux/types.h>
 #include <linux/smp_lock.h>
 #include <linux/pci.h>
+#include <linux/workqueue.h>
 #include "../pci.h"
 #include "pciehp.h"
 
-static void interrupt_event_handler(struct controller *ctrl);
+static void interrupt_event_handler(struct work_struct *work);
+static int pciehp_enable_slot(struct slot *p_slot);
+static int pciehp_disable_slot(struct slot *p_slot);
 
-static struct semaphore event_semaphore;       /* mutex for process loop (up if something to process) */
-static struct semaphore event_exit;            /* guard ensure thread has exited before calling it quits */
-static int event_finished;
-static unsigned long pushbutton_pending;       /* = 0 */
-static unsigned long surprise_rm_pending;      /* = 0 */
-
-static inline char *slot_name(struct slot *p_slot)
+static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
 {
-       return p_slot->hotplug_slot->name;
+       struct event_info *info;
+
+       info = kmalloc(sizeof(*info), GFP_ATOMIC);
+       if (!info)
+               return -ENOMEM;
+
+       info->event_type = event_type;
+       info->p_slot = p_slot;
+       INIT_WORK(&info->work, interrupt_event_handler);
+
+       schedule_work(&info->work);
+
+       return 0;
 }
 
 u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl)
 {
        struct slot *p_slot;
-       u8 rc = 0;
-       u8 getstatus;
-       struct event_info *taskInfo;
+       u32 event_type;
 
        /* Attention Button Change */
        dbg("pciehp:  Attention button interrupt received.\n");
-       
-       /* This is the structure that tells the worker thread what to do */
-       taskInfo = &(ctrl->event_queue[ctrl->next_event]);
-       p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
-
-       p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
-       
-       ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
-       taskInfo->hp_slot = hp_slot;
 
-       rc++;
+       p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 
        /*
         *  Button pressed - See if need to TAKE ACTION!!!
         */
-       info("Button pressed on Slot(%s)\n", slot_name(p_slot));
-       taskInfo->event_type = INT_BUTTON_PRESS;
-
-       if ((p_slot->state == BLINKINGON_STATE)
-           || (p_slot->state == BLINKINGOFF_STATE)) {
-               /* Cancel if we are still blinking; this means that we press the
-                * attention again before the 5 sec. limit expires to cancel hot-add
-                * or hot-remove
-                */
-               taskInfo->event_type = INT_BUTTON_CANCEL;
-               info("Button cancel on Slot(%s)\n", slot_name(p_slot));
-       } else if ((p_slot->state == POWERON_STATE)
-                  || (p_slot->state == POWEROFF_STATE)) {
-               /* Ignore if the slot is on power-on or power-off state; this 
-                * means that the previous attention button action to hot-add or
-                * hot-remove is undergoing
-                */
-               taskInfo->event_type = INT_BUTTON_IGNORE;
-               info("Button ignore on Slot(%s)\n", slot_name(p_slot));
-       }
+       info("Button pressed on Slot(%s)\n", p_slot->name);
+       event_type = INT_BUTTON_PRESS;
 
-       if (rc)
-               up(&event_semaphore);   /* signal event thread that new event is posted */
+       queue_interrupt_event(p_slot, event_type);
 
        return 0;
-
 }
 
 u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl)
 {
        struct slot *p_slot;
-       u8 rc = 0;
        u8 getstatus;
-       struct event_info *taskInfo;
+       u32 event_type;
 
        /* Switch Change */
        dbg("pciehp:  Switch interrupt received.\n");
 
-       /* This is the structure that tells the worker thread
-        * what to do
-        */
-       taskInfo = &(ctrl->event_queue[ctrl->next_event]);
-       ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
-       taskInfo->hp_slot = hp_slot;
-
-       rc++;
        p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
        p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 
@@ -125,39 +94,30 @@ u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl)
                /*
                 * Switch opened
                 */
-               info("Latch open on Slot(%s)\n", slot_name(p_slot));
-               taskInfo->event_type = INT_SWITCH_OPEN;
+               info("Latch open on Slot(%s)\n", p_slot->name);
+               event_type = INT_SWITCH_OPEN;
        } else {
                /*
                 *  Switch closed
                 */
-               info("Latch close on Slot(%s)\n", slot_name(p_slot));
-               taskInfo->event_type = INT_SWITCH_CLOSE;
+               info("Latch close on Slot(%s)\n", p_slot->name);
+               event_type = INT_SWITCH_CLOSE;
        }
 
-       if (rc)
-               up(&event_semaphore);   /* signal event thread that new event is posted */
+       queue_interrupt_event(p_slot, event_type);
 
-       return rc;
+       return 1;
 }
 
 u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl)
 {
        struct slot *p_slot;
-       u8 presence_save, rc = 0;
-       struct event_info *taskInfo;
+       u32 event_type;
+       u8 presence_save;
 
        /* Presence Change */
        dbg("pciehp:  Presence/Notify input change.\n");
 
-       /* This is the structure that tells the worker thread
-        * what to do
-        */
-       taskInfo = &(ctrl->event_queue[ctrl->next_event]);
-       ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
-       taskInfo->hp_slot = hp_slot;
-
-       rc++;
        p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 
        /* Switch is open, assume a presence change
@@ -168,59 +128,49 @@ u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl)
                /*
                 * Card Present
                 */
-               info("Card present on Slot(%s)\n", slot_name(p_slot));
-               taskInfo->event_type = INT_PRESENCE_ON;
+               info("Card present on Slot(%s)\n", p_slot->name);
+               event_type = INT_PRESENCE_ON;
        } else {
                /*
                 * Not Present
                 */
-               info("Card not present on Slot(%s)\n", slot_name(p_slot));
-               taskInfo->event_type = INT_PRESENCE_OFF;
+               info("Card not present on Slot(%s)\n", p_slot->name);
+               event_type = INT_PRESENCE_OFF;
        }
 
-       if (rc)
-               up(&event_semaphore);   /* signal event thread that new event is posted */
+       queue_interrupt_event(p_slot, event_type);
 
-       return rc;
+       return 1;
 }
 
 u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
 {
        struct slot *p_slot;
-       u8 rc = 0;
-       struct event_info *taskInfo;
+       u32 event_type;
 
        /* power fault */
        dbg("pciehp:  Power fault interrupt received.\n");
 
-       /* this is the structure that tells the worker thread
-        * what to do
-        */
-       taskInfo = &(ctrl->event_queue[ctrl->next_event]);
-       ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
-       taskInfo->hp_slot = hp_slot;
-
-       rc++;
        p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 
        if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) {
                /*
                 * power fault Cleared
                 */
-               info("Power fault cleared on Slot(%s)\n", slot_name(p_slot));
-               taskInfo->event_type = INT_POWER_FAULT_CLEAR;
+               info("Power fault cleared on Slot(%s)\n", p_slot->name);
+               event_type = INT_POWER_FAULT_CLEAR;
        } else {
                /*
                 *   power fault
                 */
-               info("Power fault on Slot(%s)\n", slot_name(p_slot));
-               taskInfo->event_type = INT_POWER_FAULT;
+               info("Power fault on Slot(%s)\n", p_slot->name);
+               event_type = INT_POWER_FAULT;
                info("power fault bit %x set\n", hp_slot);
        }
-       if (rc)
-               up(&event_semaphore);   /* signal event thread that new event is posted */
 
-       return rc;
+       queue_interrupt_event(p_slot, event_type);
+
+       return 1;
 }
 
 /* The following routines constitute the bulk of the 
@@ -357,13 +307,10 @@ static int remove_board(struct slot *p_slot)
        return 0;
 }
 
-
-static void pushbutton_helper_thread(unsigned long data)
-{
-       pushbutton_pending = data;
-
-       up(&event_semaphore);
-}
+struct power_work_info {
+       struct slot *p_slot;
+       struct work_struct work;
+};
 
 /**
  * pciehp_pushbutton_thread
@@ -372,276 +319,214 @@ static void pushbutton_helper_thread(unsigned long data)
  * Handles all pending events and exits.
  *
  */
-static void pciehp_pushbutton_thread(unsigned long slot)
+static void pciehp_power_thread(struct work_struct *work)
 {
-       struct slot *p_slot = (struct slot *) slot;
-       u8 getstatus;
-       
-       pushbutton_pending = 0;
-
-       if (!p_slot) {
-               dbg("%s: Error! slot NULL\n", __FUNCTION__);
-               return;
-       }
-
-       p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
-       if (getstatus) {
-               p_slot->state = POWEROFF_STATE;
-               dbg("%s: disabling bus:device(%x:%x)\n", __FUNCTION__,
-                               p_slot->bus, p_slot->device);
-
+       struct power_work_info *info =
+               container_of(work, struct power_work_info, work);
+       struct slot *p_slot = info->p_slot;
+
+       mutex_lock(&p_slot->lock);
+       switch (p_slot->state) {
+       case POWEROFF_STATE:
+               mutex_unlock(&p_slot->lock);
+               dbg("%s: disabling bus:device(%x:%x)\n",
+                   __FUNCTION__, p_slot->bus, p_slot->device);
                pciehp_disable_slot(p_slot);
+               mutex_lock(&p_slot->lock);
                p_slot->state = STATIC_STATE;
-       } else {
-               p_slot->state = POWERON_STATE;
-               dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__,
-                               p_slot->bus, p_slot->device);
-
+               break;
+       case POWERON_STATE:
+               mutex_unlock(&p_slot->lock);
                if (pciehp_enable_slot(p_slot) &&
                    PWR_LED(p_slot->ctrl->ctrlcap))
                        p_slot->hpc_ops->green_led_off(p_slot);
-
+               mutex_lock(&p_slot->lock);
                p_slot->state = STATIC_STATE;
+               break;
+       default:
+               break;
        }
+       mutex_unlock(&p_slot->lock);
 
-       return;
+       kfree(info);
 }
 
-/**
- * pciehp_surprise_rm_thread
- *
- * Scheduled procedure to handle blocking stuff for the surprise removal
- * Handles all pending events and exits.
- *
- */
-static void pciehp_surprise_rm_thread(unsigned long slot)
+void pciehp_queue_pushbutton_work(struct work_struct *work)
 {
-       struct slot *p_slot = (struct slot *) slot;
-       u8 getstatus;
-       
-       surprise_rm_pending = 0;
+       struct slot *p_slot = container_of(work, struct slot, work.work);
+       struct power_work_info *info;
 
-       if (!p_slot) {
-               dbg("%s: Error! slot NULL\n", __FUNCTION__);
+       info = kmalloc(sizeof(*info), GFP_KERNEL);
+       if (!info) {
+               err("%s: Cannot allocate memory\n", __FUNCTION__);
                return;
        }
+       info->p_slot = p_slot;
+       INIT_WORK(&info->work, pciehp_power_thread);
 
-       p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
-       if (!getstatus) {
+       mutex_lock(&p_slot->lock);
+       switch (p_slot->state) {
+       case BLINKINGOFF_STATE:
                p_slot->state = POWEROFF_STATE;
-               dbg("%s: removing bus:device(%x:%x)\n",
-                               __FUNCTION__, p_slot->bus, p_slot->device);
-
-               pciehp_disable_slot(p_slot);
-               p_slot->state = STATIC_STATE;
-       } else {
+               break;
+       case BLINKINGON_STATE:
                p_slot->state = POWERON_STATE;
-               dbg("%s: adding bus:device(%x:%x)\n",
-                               __FUNCTION__, p_slot->bus, p_slot->device);
-
-               if (pciehp_enable_slot(p_slot) &&
-                   PWR_LED(p_slot->ctrl->ctrlcap))
-                       p_slot->hpc_ops->green_led_off(p_slot);
-
-               p_slot->state = STATIC_STATE;
+               break;
+       default:
+               goto out;
        }
-
-       return;
+       queue_work(pciehp_wq, &info->work);
+ out:
+       mutex_unlock(&p_slot->lock);
 }
 
-
-
-/* this is the main worker thread */
-static int event_thread(void* data)
-{
-       struct controller *ctrl;
-       lock_kernel();
-       daemonize("pciehpd_event");
-
-       unlock_kernel();
-
-       while (1) {
-               dbg("!!!!event_thread sleeping\n");
-               down_interruptible (&event_semaphore);
-               dbg("event_thread woken finished = %d\n", event_finished);
-               if (event_finished || signal_pending(current))
-                       break;
-               /* Do stuff here */
-               if (pushbutton_pending)
-                       pciehp_pushbutton_thread(pushbutton_pending);
-               else if (surprise_rm_pending)
-                       pciehp_surprise_rm_thread(surprise_rm_pending);
-               else
-                       for (ctrl = pciehp_ctrl_list; ctrl; ctrl=ctrl->next)
-                               interrupt_event_handler(ctrl);
-       }
-       dbg("event_thread signals exit\n");
-       up(&event_exit);
-       return 0;
-}
-
-int pciehp_event_start_thread(void)
-{
-       int pid;
-
-       /* initialize our semaphores */
-       init_MUTEX_LOCKED(&event_exit);
-       event_finished=0;
-
-       init_MUTEX_LOCKED(&event_semaphore);
-       pid = kernel_thread(event_thread, NULL, 0);
-
-       if (pid < 0) {
-               err ("Can't start up our event thread\n");
-               return -1;
-       }
-       return 0;
-}
-
-
-void pciehp_event_stop_thread(void)
-{
-       event_finished = 1;
-       up(&event_semaphore);
-       down(&event_exit);
-}
-
-
 static int update_slot_info(struct slot *slot)
 {
        struct hotplug_slot_info *info;
-       /* char buffer[SLOT_NAME_SIZE]; */
        int result;
 
-       info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
+       info = kmalloc(sizeof(*info), GFP_KERNEL);
        if (!info)
                return -ENOMEM;
 
-       /* make_slot_name (&buffer[0], SLOT_NAME_SIZE, slot); */
-
        slot->hpc_ops->get_power_status(slot, &(info->power_status));
        slot->hpc_ops->get_attention_status(slot, &(info->attention_status));
        slot->hpc_ops->get_latch_status(slot, &(info->latch_status));
        slot->hpc_ops->get_adapter_status(slot, &(info->adapter_status));
 
-       /* result = pci_hp_change_slot_info(buffer, info); */
        result = pci_hp_change_slot_info(slot->hotplug_slot, info);
        kfree (info);
        return result;
 }
 
-static void interrupt_event_handler(struct controller *ctrl)
+/*
+ * Note: This function must be called with slot->lock held
+ */
+static void handle_button_press_event(struct slot *p_slot)
 {
-       int loop = 0;
-       int change = 1;
-       u8 hp_slot;
+       struct controller *ctrl = p_slot->ctrl;
        u8 getstatus;
-       struct slot *p_slot;
 
-       while (change) {
-               change = 0;
-
-               for (loop = 0; loop < MAX_EVENTS; loop++) {
-                       if (ctrl->event_queue[loop].event_type != 0) {
-                               hp_slot = ctrl->event_queue[loop].hp_slot;
-
-                               p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
-
-                               if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) {
-                                       dbg("button cancel\n");
-                                       del_timer(&p_slot->task_event);
-
-                                       switch (p_slot->state) {
-                                       case BLINKINGOFF_STATE:
-                                               if (PWR_LED(ctrl->ctrlcap))
-                                                       p_slot->hpc_ops->green_led_on(p_slot);
-
-                                               if (ATTN_LED(ctrl->ctrlcap))
-                                                       p_slot->hpc_ops->set_attention_status(p_slot, 0);
-                                               break;
-                                       case BLINKINGON_STATE:
-                                               if (PWR_LED(ctrl->ctrlcap))
-                                                       p_slot->hpc_ops->green_led_off(p_slot);
-
-                                               if (ATTN_LED(ctrl->ctrlcap))
-                                                       p_slot->hpc_ops->set_attention_status(p_slot, 0);
-                                               break;
-                                       default:
-                                               warn("Not a valid state\n");
-                                               return;
-                                       }
-                                       info("PCI slot #%s - action canceled due to button press.\n", slot_name(p_slot));
-                                       p_slot->state = STATIC_STATE;
-                               }
-                               /* ***********Button Pressed (No action on 1st press...) */
-                               else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) {
-                                       
-                                       if (ATTN_BUTTN(ctrl->ctrlcap)) {
-                                               dbg("Button pressed\n");
-                                               p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
-                                               if (getstatus) {
-                                                       /* slot is on */
-                                                       dbg("slot is on\n");
-                                                       p_slot->state = BLINKINGOFF_STATE;
-                                                       info("PCI slot #%s - powering off due to button press.\n", slot_name(p_slot));
-                                               } else {
-                                                       /* slot is off */
-                                                       dbg("slot is off\n");
-                                                       p_slot->state = BLINKINGON_STATE;
-                                                       info("PCI slot #%s - powering on due to button press.\n", slot_name(p_slot));
-                                               }
-
-                                               /* blink green LED and turn off amber */
-                                               if (PWR_LED(ctrl->ctrlcap))
-                                                       p_slot->hpc_ops->green_led_blink(p_slot);
-
-                                               if (ATTN_LED(ctrl->ctrlcap))
-                                                       p_slot->hpc_ops->set_attention_status(p_slot, 0);
-
-                                               init_timer(&p_slot->task_event);
-                                               p_slot->task_event.expires = jiffies + 5 * HZ;   /* 5 second delay */
-                                               p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread;
-                                               p_slot->task_event.data = (unsigned long) p_slot;
-
-                                               add_timer(&p_slot->task_event);
-                                       }
-                               }
-                               /***********POWER FAULT********************/
-                               else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {
-                                       if (POWER_CTRL(ctrl->ctrlcap)) {
-                                               dbg("power fault\n");
-                                               if (ATTN_LED(ctrl->ctrlcap))
-                                                       p_slot->hpc_ops->set_attention_status(p_slot, 1);
-
-                                               if (PWR_LED(ctrl->ctrlcap))
-                                                       p_slot->hpc_ops->green_led_off(p_slot);
-                                       }
-                               }
-                               /***********SURPRISE REMOVAL********************/
-                               else if ((ctrl->event_queue[loop].event_type == INT_PRESENCE_ON) || 
-                                       (ctrl->event_queue[loop].event_type == INT_PRESENCE_OFF)) {
-                                       if (HP_SUPR_RM(ctrl->ctrlcap)) {
-                                               dbg("Surprise Removal\n");
-                                               if (p_slot) {
-                                                       surprise_rm_pending = (unsigned long) p_slot;
-                                                       up(&event_semaphore);
-                                                       update_slot_info(p_slot);
-                                               }
-                                       }
-                               } else {
-                                       /* refresh notification */
-                                       if (p_slot)
-                                               update_slot_info(p_slot);
-                               }
-
-                               ctrl->event_queue[loop].event_type = 0;
-
-                               change = 1;
-                       }
-               }               /* End of FOR loop */
+       switch (p_slot->state) {
+       case STATIC_STATE:
+               p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
+               if (getstatus) {
+                       p_slot->state = BLINKINGOFF_STATE;
+                       info("PCI slot #%s - powering off due to button "
+                            "press.\n", p_slot->name);
+               } else {
+                       p_slot->state = BLINKINGON_STATE;
+                       info("PCI slot #%s - powering on due to button "
+                            "press.\n", p_slot->name);
+               }
+               /* blink green LED and turn off amber */
+               if (PWR_LED(ctrl->ctrlcap))
+                       p_slot->hpc_ops->green_led_blink(p_slot);
+               if (ATTN_LED(ctrl->ctrlcap))
+                       p_slot->hpc_ops->set_attention_status(p_slot, 0);
+
+               schedule_delayed_work(&p_slot->work, 5*HZ);
+               break;
+       case BLINKINGOFF_STATE:
+       case BLINKINGON_STATE:
+               /*
+                * Cancel if we are still blinking; this means that we
+                * press the attention again before the 5 sec. limit
+                * expires to cancel hot-add or hot-remove
+                */
+               info("Button cancel on Slot(%s)\n", p_slot->name);
+               dbg("%s: button cancel\n", __FUNCTION__);
+               cancel_delayed_work(&p_slot->work);
+               if (p_slot->state == BLINKINGOFF_STATE) {
+                       if (PWR_LED(ctrl->ctrlcap))
+                               p_slot->hpc_ops->green_led_on(p_slot);
+               } else {
+                       if (PWR_LED(ctrl->ctrlcap))
+                               p_slot->hpc_ops->green_led_off(p_slot);
+               }
+               if (ATTN_LED(ctrl->ctrlcap))
+                       p_slot->hpc_ops->set_attention_status(p_slot, 0);
+               info("PCI slot #%s - action canceled due to button press\n",
+                    p_slot->name);
+               p_slot->state = STATIC_STATE;
+               break;
+       case POWEROFF_STATE:
+       case POWERON_STATE:
+               /*
+                * Ignore if the slot is on power-on or power-off state;
+                * this means that the previous attention button action
+                * to hot-add or hot-remove is undergoing
+                */
+               info("Button ignore on Slot(%s)\n", p_slot->name);
+               update_slot_info(p_slot);
+               break;
+       default:
+               warn("Not a valid state\n");
+               break;
        }
 }
 
+/*
+ * Note: This function must be called with slot->lock held
+ */
+static void handle_surprise_event(struct slot *p_slot)
+{
+       u8 getstatus;
+       struct power_work_info *info;
+
+       info = kmalloc(sizeof(*info), GFP_KERNEL);
+       if (!info) {
+               err("%s: Cannot allocate memory\n", __FUNCTION__);
+               return;
+       }
+       info->p_slot = p_slot;
+       INIT_WORK(&info->work, pciehp_power_thread);
+
+       p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
+       if (!getstatus)
+               p_slot->state = POWEROFF_STATE;
+       else
+               p_slot->state = POWERON_STATE;
+
+       queue_work(pciehp_wq, &info->work);
+}
+
+static void interrupt_event_handler(struct work_struct *work)
+{
+       struct event_info *info = container_of(work, struct event_info, work);
+       struct slot *p_slot = info->p_slot;
+       struct controller *ctrl = p_slot->ctrl;
+
+       mutex_lock(&p_slot->lock);
+       switch (info->event_type) {
+       case INT_BUTTON_PRESS:
+               handle_button_press_event(p_slot);
+               break;
+       case INT_POWER_FAULT:
+               if (!POWER_CTRL(ctrl->ctrlcap))
+                       break;
+               if (ATTN_LED(ctrl->ctrlcap))
+                       p_slot->hpc_ops->set_attention_status(p_slot, 1);
+               if (PWR_LED(ctrl->ctrlcap))
+                       p_slot->hpc_ops->green_led_off(p_slot);
+               break;
+       case INT_PRESENCE_ON:
+       case INT_PRESENCE_OFF:
+               if (!HP_SUPR_RM(ctrl->ctrlcap))
+                       break;
+               dbg("Surprise Removal\n");
+               update_slot_info(p_slot);
+               handle_surprise_event(p_slot);
+               break;
+       default:
+               update_slot_info(p_slot);
+               break;
+       }
+       mutex_unlock(&p_slot->lock);
+
+       kfree(info);
+}
+
 int pciehp_enable_slot(struct slot *p_slot)
 {
        u8 getstatus = 0;
@@ -653,7 +538,7 @@ int pciehp_enable_slot(struct slot *p_slot)
        rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
        if (rc || !getstatus) {
                info("%s: no adapter on slot(%s)\n", __FUNCTION__,
-                    slot_name(p_slot));
+                    p_slot->name);
                mutex_unlock(&p_slot->ctrl->crit_sect);
                return -ENODEV;
        }
@@ -661,7 +546,7 @@ int pciehp_enable_slot(struct slot *p_slot)
                rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
                if (rc || getstatus) {
                        info("%s: latch open on slot(%s)\n", __FUNCTION__,
-                            slot_name(p_slot));
+                            p_slot->name);
                        mutex_unlock(&p_slot->ctrl->crit_sect);
                        return -ENODEV;
                }
@@ -671,7 +556,7 @@ int pciehp_enable_slot(struct slot *p_slot)
                rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
                if (rc || getstatus) {
                        info("%s: already enabled on slot(%s)\n", __FUNCTION__,
-                            slot_name(p_slot));
+                            p_slot->name);
                        mutex_unlock(&p_slot->ctrl->crit_sect);
                        return -EINVAL;
                }
@@ -706,7 +591,7 @@ int pciehp_disable_slot(struct slot *p_slot)
                ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
                if (ret || !getstatus) {
                        info("%s: no adapter on slot(%s)\n", __FUNCTION__,
-                            slot_name(p_slot));
+                            p_slot->name);
                        mutex_unlock(&p_slot->ctrl->crit_sect);
                        return -ENODEV;
                }
@@ -716,7 +601,7 @@ int pciehp_disable_slot(struct slot *p_slot)
                ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
                if (ret || getstatus) {
                        info("%s: latch open on slot(%s)\n", __FUNCTION__,
-                            slot_name(p_slot));
+                            p_slot->name);
                        mutex_unlock(&p_slot->ctrl->crit_sect);
                        return -ENODEV;
                }
@@ -726,7 +611,7 @@ int pciehp_disable_slot(struct slot *p_slot)
                ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
                if (ret || !getstatus) {
                        info("%s: already disabled slot(%s)\n", __FUNCTION__,
-                            slot_name(p_slot));
+                            p_slot->name);
                        mutex_unlock(&p_slot->ctrl->crit_sect);
                        return -EINVAL;
                }
@@ -739,3 +624,66 @@ int pciehp_disable_slot(struct slot *p_slot)
        return ret;
 }
 
+int pciehp_sysfs_enable_slot(struct slot *p_slot)
+{
+       int retval = -ENODEV;
+
+       mutex_lock(&p_slot->lock);
+       switch (p_slot->state) {
+       case BLINKINGON_STATE:
+               cancel_delayed_work(&p_slot->work);
+       case STATIC_STATE:
+               p_slot->state = POWERON_STATE;
+               mutex_unlock(&p_slot->lock);
+               retval = pciehp_enable_slot(p_slot);
+               mutex_lock(&p_slot->lock);
+               p_slot->state = STATIC_STATE;
+               break;
+       case POWERON_STATE:
+               info("Slot %s is already in powering on state\n",
+                    p_slot->name);
+               break;
+       case BLINKINGOFF_STATE:
+       case POWEROFF_STATE:
+               info("Already enabled on slot %s\n", p_slot->name);
+               break;
+       default:
+               err("Not a valid state on slot %s\n", p_slot->name);
+               break;
+       }
+       mutex_unlock(&p_slot->lock);
+
+       return retval;
+}
+
+int pciehp_sysfs_disable_slot(struct slot *p_slot)
+{
+       int retval = -ENODEV;
+
+       mutex_lock(&p_slot->lock);
+       switch (p_slot->state) {
+       case BLINKINGOFF_STATE:
+               cancel_delayed_work(&p_slot->work);
+       case STATIC_STATE:
+               p_slot->state = POWEROFF_STATE;
+               mutex_unlock(&p_slot->lock);
+               retval = pciehp_disable_slot(p_slot);
+               mutex_lock(&p_slot->lock);
+               p_slot->state = STATIC_STATE;
+               break;
+       case POWEROFF_STATE:
+               info("Slot %s is already in powering off state\n",
+                    p_slot->name);
+               break;
+       case BLINKINGON_STATE:
+       case POWERON_STATE:
+               info("Already disabled on slot %s\n", p_slot->name);
+               break;
+       default:
+               err("Not a valid state on slot %s\n", p_slot->name);
+               break;
+       }
+       mutex_unlock(&p_slot->lock);
+
+       return retval;
+}
index fbc64aa..9aac6a8 100644 (file)
@@ -71,6 +71,8 @@
 #define DBG_LEAVE_ROUTINE
 #endif                         /* DEBUG */
 
+static atomic_t pciehp_num_controllers = ATOMIC_INIT(0);
+
 struct ctrl_reg {
        u8 cap_id;
        u8 nxt_ptr;
@@ -219,10 +221,7 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value)
 #define EMI_STATE              0x0080
 #define EMI_STATUS_BIT         7
 
-static spinlock_t hpc_event_lock;
-
 DEFINE_DBG_BUFFER              /* Debug string buffer for entire HPC defined here */
-static int ctlr_seq_num = 0;   /* Controller sequence # */
 
 static irqreturn_t pcie_isr(int irq, void *dev_id);
 static void start_int_poll_timer(struct controller *ctrl, int sec);
@@ -656,6 +655,13 @@ static void hpc_release_ctlr(struct controller *ctrl)
        else
                free_irq(ctrl->pci_dev->irq, ctrl);
 
+       /*
+        * If this is the last controller to be released, destroy the
+        * pciehp work queue
+        */
+       if (atomic_dec_and_test(&pciehp_num_controllers))
+               destroy_workqueue(pciehp_wq);
+
        DBG_LEAVE_ROUTINE
 }
 
@@ -1152,7 +1158,6 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
 int pcie_init(struct controller * ctrl, struct pcie_device *dev)
 {
        int rc;
-       static int first = 1;
        u16 temp_word;
        u16 cap_reg;
        u16 intr_enable = 0;
@@ -1221,11 +1226,6 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
        dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
            __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
 
-       if (first) {
-               spin_lock_init(&hpc_event_lock);
-               first = 0;
-       }
-
        for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
                if (pci_resource_len(pdev, rc) > 0)
                        dbg("pci resource[%d] start=0x%llx(len=0x%llx)\n", rc,
@@ -1286,7 +1286,8 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
                rc = request_irq(ctrl->pci_dev->irq, pcie_isr, IRQF_SHARED,
                                 MY_NAME, (void *)ctrl);
                dbg("%s: request_irq %d for hpc%d (returns %d)\n",
-                   __FUNCTION__, ctrl->pci_dev->irq, ctlr_seq_num, rc);
+                   __FUNCTION__, ctrl->pci_dev->irq,
+                   atomic_read(&pciehp_num_controllers), rc);
                if (rc) {
                        err("Can't get irq %d for the hotplug controller\n",
                            ctrl->pci_dev->irq);
@@ -1296,6 +1297,18 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
        dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number,
                PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq);
 
+       /*
+        * If this is the first controller to be initialized,
+        * initialize the pciehp work queue
+        */
+       if (atomic_add_return(1, &pciehp_num_controllers) == 1) {
+               pciehp_wq = create_singlethread_workqueue("pciehpd");
+               if (!pciehp_wq) {
+                       rc = -ENOMEM;
+                       goto abort_free_irq;
+               }
+       }
+
        rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
        if (rc) {
                err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
@@ -1349,7 +1362,6 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
                        goto abort_disable_intr;
        }
 
-       ctlr_seq_num++;
        ctrl->hpc_ops = &pciehp_hpc_ops;
 
        DBG_LEAVE_ROUTINE
index 7238346..bb3c101 100644 (file)
@@ -98,7 +98,15 @@ static struct device_node *find_dlpar_node(char *drc_name, int *node_type)
        return NULL;
 }
 
-static struct slot *find_slot(struct device_node *dn)
+/**
+ * find_php_slot - return hotplug slot structure for device node
+ *
+ * This routine will return the hotplug slot structure
+ * for a given device node. Note that built-in PCI slots
+ * may be dlpar-able, but not hot-pluggable, so this routine
+ * will return NULL for built-in PCI slots.
+ */
+static struct slot *find_php_slot(struct device_node *dn)
 {
        struct list_head *tmp, *n;
        struct slot *slot;
@@ -224,9 +232,9 @@ static int dlpar_remove_phb(char *drc_name, struct device_node *dn)
        if (!pcibios_find_pci_bus(dn))
                return -EINVAL;
 
-       slot = find_slot(dn);
+       /* If pci slot is hotplugable, use hotplug to remove it */
+       slot = find_php_slot(dn);
        if (slot) {
-               /* Remove hotplug slot */
                if (rpaphp_deregister_slot(slot)) {
                        printk(KERN_ERR
                                "%s: unable to remove hotplug slot %s\n",
@@ -370,22 +378,17 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
        if (!bus)
                return -EINVAL;
 
-       slot = find_slot(dn);
+       /* If pci slot is hotplugable, use hotplug to remove it */
+       slot = find_php_slot(dn);
        if (slot) {
-               /* Remove hotplug slot */
                if (rpaphp_deregister_slot(slot)) {
                        printk(KERN_ERR
                                "%s: unable to remove hotplug slot %s\n",
                                __FUNCTION__, drc_name);
                        return -EIO;
                }
-       } else {
-               struct pci_dev *dev, *tmp;
-               list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
-                       eeh_remove_bus_device(dev);
-                       pci_remove_bus_device(dev);
-               }
-       }
+       } else
+               pcibios_remove_pci_devices(bus);
 
        if (unmap_bus_range(bus)) {
                printk(KERN_ERR "%s: failed to unmap bus range\n",
index 2e7accf..c822a77 100644 (file)
@@ -83,19 +83,15 @@ struct slot {
 
 extern struct hotplug_slot_ops rpaphp_hotplug_slot_ops;
 extern struct list_head rpaphp_slot_head;
-extern int num_slots;
 
 /* function prototypes */
 
 /* rpaphp_pci.c */
-extern int rpaphp_enable_pci_slot(struct slot *slot);
-extern int rpaphp_register_pci_slot(struct slot *slot);
-extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value);
+extern int rpaphp_enable_slot(struct slot *slot);
 extern int rpaphp_get_sensor_state(struct slot *slot, int *state);
 
 /* rpaphp_core.c */
 extern int rpaphp_add_slot(struct device_node *dn);
-extern int rpaphp_remove_slot(struct slot *slot);
 extern int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
                char **drc_name, char **drc_type, int *drc_power_domain);
 
@@ -104,7 +100,5 @@ extern void dealloc_slot_struct(struct slot *slot);
 extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain);
 extern int rpaphp_register_slot(struct slot *slot);
 extern int rpaphp_deregister_slot(struct slot *slot);
-extern int rpaphp_get_power_status(struct slot *slot, u8 * value);
-extern int rpaphp_set_attention_status(struct slot *slot, u8 status);
        
 #endif                         /* _PPC64PHP_H */
index 71a2cb8..847936f 100644 (file)
@@ -39,9 +39,7 @@
 #include "rpaphp.h"
 
 int debug;
-static struct semaphore rpaphp_sem;
 LIST_HEAD(rpaphp_slot_head);
-int num_slots;
 
 #define DRIVER_VERSION "0.1"
 #define DRIVER_AUTHOR  "Linda Xie <lxie@us.ibm.com>"
@@ -55,11 +53,6 @@ MODULE_LICENSE("GPL");
 
 module_param(debug, bool, 0644);
 
-static int rpaphp_get_attention_status(struct slot *slot)
-{
-       return slot->hotplug_slot->info->attention_status;
-}
-
 /**
  * set_attention_status - set attention LED
  * echo 0 > attention -- set LED OFF
@@ -69,79 +62,75 @@ static int rpaphp_get_attention_status(struct slot *slot)
  */
 static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value)
 {
-       int retval = 0;
+       int rc;
        struct slot *slot = (struct slot *)hotplug_slot->private;
 
-       down(&rpaphp_sem);
        switch (value) {
        case 0:
-               retval = rpaphp_set_attention_status(slot, LED_OFF);
-               hotplug_slot->info->attention_status = 0;
-               break;
        case 1:
-       default:
-               retval = rpaphp_set_attention_status(slot, LED_ON);
-               hotplug_slot->info->attention_status = 1;
-               break;
        case 2:
-               retval = rpaphp_set_attention_status(slot, LED_ID);
-               hotplug_slot->info->attention_status = 2;
+               break;
+       default:
+               value = 1;
                break;
        }
-       up(&rpaphp_sem);
-       return retval;
+
+       rc = rtas_set_indicator(DR_INDICATOR, slot->index, value);
+       if (!rc)
+               hotplug_slot->info->attention_status = value;
+
+       return rc;
 }
 
 /**
  * get_power_status - get power status of a slot
  * @hotplug_slot: slot to get status
  * @value: pointer to store status
- *
- *
  */
 static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value)
 {
-       int retval;
+       int retval, level;
        struct slot *slot = (struct slot *)hotplug_slot->private;
 
-       down(&rpaphp_sem);
-       retval = rpaphp_get_power_status(slot, value);
-       up(&rpaphp_sem);
+       retval = rtas_get_power_level (slot->power_domain, &level);
+       if (!retval)
+               *value = level;
        return retval;
 }
 
 /**
  * get_attention_status - get attention LED status
- *
- *
  */
 static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value)
 {
-       int retval = 0;
        struct slot *slot = (struct slot *)hotplug_slot->private;
-
-       down(&rpaphp_sem);
-       *value = rpaphp_get_attention_status(slot);
-       up(&rpaphp_sem);
-       return retval;
+       *value = slot->hotplug_slot->info->attention_status;
+       return 0;
 }
 
 static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value)
 {
        struct slot *slot = (struct slot *)hotplug_slot->private;
-       int retval = 0;
+       int rc, state;
 
-       down(&rpaphp_sem);
-       retval = rpaphp_get_pci_adapter_status(slot, 0, value);
-       up(&rpaphp_sem);
-       return retval;
+       rc = rpaphp_get_sensor_state(slot, &state);
+
+       *value = NOT_VALID;
+       if (rc)
+               return rc;
+
+       if (state == EMPTY)
+               *value = EMPTY;
+       else if (state == PRESENT)
+               *value = slot->state;
+
+       return 0;
 }
 
 static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
 {
        struct slot *slot = (struct slot *)hotplug_slot->private;
 
-       down(&rpaphp_sem);
        switch (slot->type) {
        case 1:
        case 2:
@@ -172,7 +161,6 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
                break;
 
        }
-       up(&rpaphp_sem);
        return 0;
 }
 
@@ -265,6 +253,14 @@ static int is_php_type(char *drc_type)
        return 1;
 }
 
+/**
+ * is_php_dn() - return 1 if this is a hotpluggable pci slot, else 0
+ *
+ * This routine will return true only if the device node is
+ * a hotpluggable slot. This routine will return false
+ * for built-in pci slots (even when the built-in slots are
+ * dlparable.)
+ */
 static int is_php_dn(struct device_node *dn, const int **indexes,
                const int **names, const int **types, const int **power_domains)
 {
@@ -272,24 +268,31 @@ static int is_php_dn(struct device_node *dn, const int **indexes,
        int rc;
 
        rc = get_children_props(dn, indexes, names, &drc_types, power_domains);
-       if (rc >= 0) {
-               if (is_php_type((char *) &drc_types[1])) {
-                       *types = drc_types;
-                       return 1;
-               }
-       }
+       if (rc < 0)
+               return 0;
 
-       return 0;
+       if (!is_php_type((char *) &drc_types[1]))
+               return 0;
+
+       *types = drc_types;
+       return 1;
 }
 
 /**
- * rpaphp_add_slot -- add hotplug or dlpar slot
+ * rpaphp_add_slot -- declare a hotplug slot to the hotplug subsystem.
+ * @dn device node of slot
+ *
+ * This subroutine will register a hotplugable slot with the
+ * PCI hotplug infrastructure. This routine is typicaly called
+ * during boot time, if the hotplug slots are present at boot time,
+ * or is called later, by the dlpar add code, if the slot is
+ * being dynamically added during runtime.
+ *
+ * If the device node points at an embedded (built-in) slot, this
+ * routine will just return without doing anything, since embedded
+ * slots cannot be hotplugged.
  *
- *     rpaphp not only registers PCI hotplug slots(HOTPLUG), 
- *     but also logical DR slots(EMBEDDED).
- *     HOTPLUG slot: An adapter can be physically added/removed. 
- *     EMBEDDED slot: An adapter can be logically removed/added
- *               from/to a partition with the slot.
+ * To remove a slot, it suffices to call rpaphp_deregister_slot()
  */
 int rpaphp_add_slot(struct device_node *dn)
 {
@@ -299,34 +302,42 @@ int rpaphp_add_slot(struct device_node *dn)
        const int *indexes, *names, *types, *power_domains;
        char *name, *type;
 
+       if (!dn->name || strcmp(dn->name, "pci"))
+               return 0;
+
+       /* If this is not a hotplug slot, return without doing anything. */
+       if (!is_php_dn(dn, &indexes, &names, &types, &power_domains))
+               return 0;
+
        dbg("Entry %s: dn->full_name=%s\n", __FUNCTION__, dn->full_name);
 
        /* register PCI devices */
-       if (dn->name != 0 && strcmp(dn->name, "pci") == 0) {
-               if (!is_php_dn(dn, &indexes, &names, &types, &power_domains))
-                       goto exit;
-
-               name = (char *) &names[1];
-               type = (char *) &types[1];
-               for (i = 0; i < indexes[0]; i++,
-                       name += (strlen(name) + 1), type += (strlen(type) + 1))                 {
-
-                       if (!(slot = alloc_slot_struct(dn, indexes[i + 1], name,
-                                      power_domains[i + 1]))) {
-                               retval = -ENOMEM;
-                               goto exit;
-                       }
-                       slot->type = simple_strtoul(type, NULL, 10);
+       name = (char *) &names[1];
+       type = (char *) &types[1];
+       for (i = 0; i < indexes[0]; i++) {
+
+               slot = alloc_slot_struct(dn, indexes[i + 1], name, power_domains[i + 1]);
+               if (!slot)
+                       return -ENOMEM;
+
+               slot->type = simple_strtoul(type, NULL, 10);
                                
-                       dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n",
-                                       indexes[i + 1], name, type);
+               dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n",
+                               indexes[i + 1], name, type);
 
-                       retval = rpaphp_register_pci_slot(slot);
-               }
+               retval = rpaphp_enable_slot(slot);
+               if (!retval)
+                       retval = rpaphp_register_slot(slot);
+
+               if (retval)
+                       dealloc_slot_struct(slot);
+
+               name += strlen(name) + 1;
+               type += strlen(type) + 1;
        }
-exit:
-       dbg("%s - Exit: num_slots=%d rc[%d]\n",
-           __FUNCTION__, num_slots, retval);
+       dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
+
+       /* XXX FIXME: reports a failure only if last entry in loop failed */
        return retval;
 }
 
@@ -354,7 +365,6 @@ static int __init rpaphp_init(void)
        struct device_node *dn = NULL;
 
        info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
-       init_MUTEX(&rpaphp_sem);
 
        while ((dn = of_find_node_by_name(dn, "pci")))
                rpaphp_add_slot(dn);
@@ -367,8 +377,9 @@ static void __exit rpaphp_exit(void)
        cleanup_slots();
 }
 
-static int __enable_slot(struct slot *slot)
+static int enable_slot(struct hotplug_slot *hotplug_slot)
 {
+       struct slot *slot = (struct slot *)hotplug_slot->private;
        int state;
        int retval;
 
@@ -392,46 +403,17 @@ static int __enable_slot(struct slot *slot)
        return 0;
 }
 
-static int enable_slot(struct hotplug_slot *hotplug_slot)
+static int disable_slot(struct hotplug_slot *hotplug_slot)
 {
-       int retval;
        struct slot *slot = (struct slot *)hotplug_slot->private;
-
-       down(&rpaphp_sem);
-       retval = __enable_slot(slot);
-       up(&rpaphp_sem);
-
-       return retval;
-}
-
-static int __disable_slot(struct slot *slot)
-{
-       struct pci_dev *dev, *tmp;
-
        if (slot->state == NOT_CONFIGURED)
                return -EINVAL;
 
-       list_for_each_entry_safe(dev, tmp, &slot->bus->devices, bus_list) {
-               eeh_remove_bus_device(dev);
-               pci_remove_bus_device(dev);
-       }
-
+       pcibios_remove_pci_devices(slot->bus);
        slot->state = NOT_CONFIGURED;
        return 0;
 }
 
-static int disable_slot(struct hotplug_slot *hotplug_slot)
-{
-       struct slot *slot = (struct slot *)hotplug_slot->private;
-       int retval;
-
-       down(&rpaphp_sem);
-       retval = __disable_slot (slot);
-       up(&rpaphp_sem);
-
-       return retval;
-}
-
 struct hotplug_slot_ops rpaphp_hotplug_slot_ops = {
        .owner = THIS_MODULE,
        .enable_slot = enable_slot,
index 6f6cbed..54ca865 100644 (file)
@@ -64,75 +64,6 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state)
        return rc;
 }
 
-/**
- * get_pci_adapter_status - get the status of a slot
- * 
- * 0-- slot is empty
- * 1-- adapter is configured
- * 2-- adapter is not configured
- * 3-- not valid
- */
-int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value)
-{
-       struct pci_bus *bus;
-       int state, rc;
-
-       *value = NOT_VALID;
-       rc = rpaphp_get_sensor_state(slot, &state);
-       if (rc)
-               goto exit;
-
-       if (state == EMPTY)
-               *value = EMPTY;
-       else if (state == PRESENT) {
-               if (!is_init) {
-                       /* at run-time slot->state can be changed by */
-                       /* config/unconfig adapter */
-                       *value = slot->state;
-               } else {
-                       bus = pcibios_find_pci_bus(slot->dn);
-                       if (bus && !list_empty(&bus->devices))
-                               *value = CONFIGURED;
-                       else
-                               *value = NOT_CONFIGURED;
-               }
-       }
-exit:
-       return rc;
-}
-
-static void print_slot_pci_funcs(struct pci_bus *bus)
-{
-       struct device_node *dn;
-       struct pci_dev *dev;
-
-       dn = pci_bus_to_OF_node(bus);
-       if (!dn)
-               return;
-
-       dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, dn->full_name);
-       list_for_each_entry (dev, &bus->devices, bus_list)
-               dbg("\t%s\n", pci_name(dev));
-       return;
-}
-
-static int setup_pci_hotplug_slot_info(struct slot *slot)
-{
-       struct hotplug_slot_info *hotplug_slot_info = slot->hotplug_slot->info;
-
-       dbg("%s Initilize the PCI slot's hotplug->info structure ...\n",
-           __FUNCTION__);
-       rpaphp_get_power_status(slot, &hotplug_slot_info->power_status);
-       rpaphp_get_pci_adapter_status(slot, 1,
-                                     &hotplug_slot_info->adapter_status);
-       if (hotplug_slot_info->adapter_status == NOT_VALID) {
-               err("%s: NOT_VALID: skip dn->full_name=%s\n",
-                   __FUNCTION__, slot->dn->full_name);
-               return -EINVAL;
-       }
-       return 0;
-}
-
 static void set_slot_name(struct slot *slot)
 {
        struct pci_bus *bus = slot->bus;
@@ -146,69 +77,73 @@ static void set_slot_name(struct slot *slot)
                        bus->number);
 }
 
-static int setup_pci_slot(struct slot *slot)
+/**
+ * rpaphp_enable_slot - record slot state, config pci device
+ *
+ * Initialize values in the slot, and the hotplug_slot info
+ * structures to indicate if there is a pci card plugged into
+ * the slot. If the slot is not empty, run the pcibios routine
+ * to get pcibios stuff correctly set up.
+ */
+int rpaphp_enable_slot(struct slot *slot)
 {
-       struct device_node *dn = slot->dn;
+       int rc, level, state;
        struct pci_bus *bus;
+       struct hotplug_slot_info *info = slot->hotplug_slot->info;
+
+       info->adapter_status = NOT_VALID;
+       slot->state = EMPTY;
+
+       /* Find out if the power is turned on for the slot */
+       rc = rtas_get_power_level(slot->power_domain, &level);
+       if (rc)
+               return rc;
+       info->power_status = level;
+
+       /* Figure out if there is an adapter in the slot */
+       rc = rpaphp_get_sensor_state(slot, &state);
+       if (rc)
+               return rc;
 
-       BUG_ON(!dn);
-       bus = pcibios_find_pci_bus(dn);
+       bus = pcibios_find_pci_bus(slot->dn);
        if (!bus) {
-               err("%s: no pci_bus for dn %s\n", __FUNCTION__, dn->full_name);
-               goto exit_rc;
+               err("%s: no pci_bus for dn %s\n", __FUNCTION__, slot->dn->full_name);
+               return -EINVAL;
        }
 
+       info->adapter_status = EMPTY;
        slot->bus = bus;
        slot->pci_devs = &bus->devices;
        set_slot_name(slot);
 
-       /* find slot's pci_dev if it's not empty */
-       if (slot->hotplug_slot->info->adapter_status == EMPTY) {
-               slot->state = EMPTY;    /* slot is empty */
-       } else {
-               /* slot is occupied */
-               if (!dn->child) {
-                       /* non-empty slot has to have child */
-                       err("%s: slot[%s]'s device_node doesn't have child for adapter\n", 
-                               __FUNCTION__, slot->name);
-                       goto exit_rc;
+       /* if there's an adapter in the slot, go add the pci devices */
+       if (state == PRESENT) {
+               info->adapter_status = NOT_CONFIGURED;
+               slot->state = NOT_CONFIGURED;
+
+               /* non-empty slot has to have child */
+               if (!slot->dn->child) {
+                       err("%s: slot[%s]'s device_node doesn't have child for adapter\n",
+                           __FUNCTION__, slot->name);
+                       return -EINVAL;
                }
 
-               if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) {
-                       dbg("%s CONFIGURING pci adapter in slot[%s]\n",  
-                               __FUNCTION__, slot->name);
-                       pcibios_add_pci_devices(slot->bus);
+               if (list_empty(&bus->devices))
+                       pcibios_add_pci_devices(bus);
 
-               } else if (slot->hotplug_slot->info->adapter_status != CONFIGURED) {
-                       err("%s: slot[%s]'s adapter_status is NOT_VALID.\n",
-                               __FUNCTION__, slot->name);
-                       goto exit_rc;
-               }
-               print_slot_pci_funcs(slot->bus);
-               if (!list_empty(slot->pci_devs)) {
+               if (!list_empty(&bus->devices)) {
+                       info->adapter_status = CONFIGURED;
                        slot->state = CONFIGURED;
-               } else {
-                       /* DLPAR add as opposed to 
-                        * boot time */
-                       slot->state = NOT_CONFIGURED;
+               }
+
+               if (debug) {
+                       struct pci_dev *dev;
+                       dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, slot->dn->full_name);
+                       list_for_each_entry (dev, &bus->devices, bus_list)
+                               dbg("\t%s\n", pci_name(dev));
                }
        }
-       return 0;
-exit_rc:
-       dealloc_slot_struct(slot);
-       return -EINVAL;
-}
 
-int rpaphp_register_pci_slot(struct slot *slot)
-{
-       int rc = -EINVAL;
-
-       if (setup_pci_hotplug_slot_info(slot))
-               goto exit_rc;
-       if (setup_pci_slot(slot))
-               goto exit_rc;
-       rc = rpaphp_register_slot(slot);
-exit_rc:
-       return rc;
+       return 0;
 }
 
index 3009193..d4ee872 100644 (file)
@@ -56,7 +56,6 @@ static struct hotplug_slot_attribute php_attr_location = {
 static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot)
 {
        struct slot *slot = (struct slot *) hotplug_slot->private;
-
        dealloc_slot_struct(slot);
 }
 
@@ -65,12 +64,12 @@ void dealloc_slot_struct(struct slot *slot)
        kfree(slot->hotplug_slot->info);
        kfree(slot->hotplug_slot->name);
        kfree(slot->hotplug_slot);
+       kfree(slot->location);
        kfree(slot);
-       return;
 }
 
-struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name,
-                 int power_domain)
+struct slot *alloc_slot_struct(struct device_node *dn,
+                       int drc_index, char *drc_name, int power_domain)
 {
        struct slot *slot;
        
@@ -115,7 +114,7 @@ error_nomem:
 
 static int is_registered(struct slot *slot)
 {
-       struct slot             *tmp_slot;
+       struct slot *tmp_slot;
 
        list_for_each_entry(tmp_slot, &rpaphp_slot_head, rpaphp_slot_list) {
                if (!strcmp(tmp_slot->name, slot->name))
@@ -140,8 +139,6 @@ int rpaphp_deregister_slot(struct slot *slot)
        retval = pci_hp_deregister(php_slot);
        if (retval)
                err("Problem unregistering a slot %s\n", slot->name);
-       else
-               num_slots--;
 
        dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
        return retval;
@@ -160,14 +157,13 @@ int rpaphp_register_slot(struct slot *slot)
        /* should not try to register the same slot twice */
        if (is_registered(slot)) {
                err("rpaphp_register_slot: slot[%s] is already registered\n", slot->name);
-               retval = -EAGAIN;
-               goto register_fail;
+               return -EAGAIN;
        }       
 
        retval = pci_hp_register(php_slot);
        if (retval) {
                err("pci_hp_register failed with error %d\n", retval);
-               goto register_fail;
+               return retval;
        }
 
        /* create "phy_location" file */
@@ -181,43 +177,10 @@ int rpaphp_register_slot(struct slot *slot)
        list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
        info("Slot [%s](PCI location=%s) registered\n", slot->name,
                        slot->location);
-       num_slots++;
        return 0;
 
 sysfs_fail:
        pci_hp_deregister(php_slot);
-register_fail:
-       rpaphp_release_slot(php_slot);
        return retval;
 }
 
-int rpaphp_get_power_status(struct slot *slot, u8 * value)
-{
-       int rc = 0, level;
-       
-       rc = rtas_get_power_level(slot->power_domain, &level);
-       if (rc < 0) {
-               err("failed to get power-level for slot(%s), rc=0x%x\n",
-                       slot->location, rc);
-               return rc;
-       }
-
-       dbg("%s the power level of slot %s(pwd-domain:0x%x) is %d\n",
-               __FUNCTION__, slot->name, slot->power_domain, level);
-       *value = level;
-
-       return rc;
-}
-
-int rpaphp_set_attention_status(struct slot *slot, u8 status)
-{
-       int rc;
-
-       /* status: LED_OFF or LED_ON */
-       rc = rtas_set_indicator(DR_INDICATOR, slot->index, status);
-       if (rc < 0)
-               err("slot(name=%s location=%s index=0x%x) set attention-status(%d) failed! rc=0x%x\n",
-                   slot->name, slot->location, slot->index, status, rc);
-
-       return rc;
-}
index 01d31a1..37ed088 100644 (file)
@@ -166,7 +166,7 @@ extern u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl);
 extern int shpchp_configure_device(struct slot *p_slot);
 extern int shpchp_unconfigure_device(struct slot *p_slot);
 extern void cleanup_slots(struct controller *ctrl);
-extern void queue_pushbutton_work(struct work_struct *work);
+extern void shpchp_queue_pushbutton_work(struct work_struct *work);
 extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
 
 #ifdef CONFIG_ACPI
index 5f4bc08..80dec97 100644 (file)
@@ -136,7 +136,7 @@ static int init_slots(struct controller *ctrl)
                slot->hpc_ops = ctrl->hpc_ops;
                slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i);
                mutex_init(&slot->lock);
-               INIT_DELAYED_WORK(&slot->work, queue_pushbutton_work);
+               INIT_DELAYED_WORK(&slot->work, shpchp_queue_pushbutton_work);
 
                /* register this slot with the hotplug pci core */
                hotplug_slot->private = slot;
index b746bd2..2c94d44 100644 (file)
@@ -433,7 +433,7 @@ static void shpchp_pushbutton_thread(struct work_struct *work)
        kfree(info);
 }
 
-void queue_pushbutton_work(struct work_struct *work)
+void shpchp_queue_pushbutton_work(struct work_struct *work)
 {
        struct slot *p_slot = container_of(work, struct slot, work.work);
        struct pushbutton_work_info *info;
index 435c195..9e1321d 100644 (file)
 #include "pci.h"
 #include "msi.h"
 
-static struct kmem_cache* msi_cachep;
-
 static int pci_msi_enable = 1;
 
-static int msi_cache_init(void)
-{
-       msi_cachep = kmem_cache_create("msi_cache", sizeof(struct msi_desc),
-                                       0, SLAB_HWCACHE_ALIGN, NULL, NULL);
-       if (!msi_cachep)
-               return -ENOMEM;
-
-       return 0;
-}
-
 static void msi_set_enable(struct pci_dev *dev, int enable)
 {
        int pos;
@@ -68,6 +56,29 @@ static void msix_set_enable(struct pci_dev *dev, int enable)
        }
 }
 
+static void msix_flush_writes(unsigned int irq)
+{
+       struct msi_desc *entry;
+
+       entry = get_irq_msi(irq);
+       BUG_ON(!entry || !entry->dev);
+       switch (entry->msi_attrib.type) {
+       case PCI_CAP_ID_MSI:
+               /* nothing to do */
+               break;
+       case PCI_CAP_ID_MSIX:
+       {
+               int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
+                       PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET;
+               readl(entry->mask_base + offset);
+               break;
+       }
+       default:
+               BUG();
+               break;
+       }
+}
+
 static void msi_set_mask_bit(unsigned int irq, int flag)
 {
        struct msi_desc *entry;
@@ -187,41 +198,28 @@ void write_msi_msg(unsigned int irq, struct msi_msg *msg)
 void mask_msi_irq(unsigned int irq)
 {
        msi_set_mask_bit(irq, 1);
+       msix_flush_writes(irq);
 }
 
 void unmask_msi_irq(unsigned int irq)
 {
        msi_set_mask_bit(irq, 0);
+       msix_flush_writes(irq);
 }
 
-static int msi_free_irq(struct pci_dev* dev, int irq);
-
-static int msi_init(void)
-{
-       static int status = -ENOMEM;
-
-       if (!status)
-               return status;
+static int msi_free_irqs(struct pci_dev* dev);
 
-       status = msi_cache_init();
-       if (status < 0) {
-               pci_msi_enable = 0;
-               printk(KERN_WARNING "PCI: MSI cache init failed\n");
-               return status;
-       }
-
-       return status;
-}
 
 static struct msi_desc* alloc_msi_entry(void)
 {
        struct msi_desc *entry;
 
-       entry = kmem_cache_zalloc(msi_cachep, GFP_KERNEL);
+       entry = kzalloc(sizeof(struct msi_desc), GFP_KERNEL);
        if (!entry)
                return NULL;
 
-       entry->link.tail = entry->link.head = 0;        /* single message */
+       INIT_LIST_HEAD(&entry->list);
+       entry->irq = 0;
        entry->dev = NULL;
 
        return entry;
@@ -256,7 +254,6 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
 static void __pci_restore_msix_state(struct pci_dev *dev)
 {
        int pos;
-       int irq, head, tail = 0;
        struct msi_desc *entry;
        u16 control;
 
@@ -266,18 +263,15 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
        /* route the table */
        pci_intx(dev, 0);               /* disable intx */
        msix_set_enable(dev, 0);
-       irq = head = dev->first_msi_irq;
-       entry = get_irq_msi(irq);
-       pos = entry->msi_attrib.pos;
-       while (head != tail) {
-               entry = get_irq_msi(irq);
-               write_msi_msg(irq, &entry->msg);
-               msi_set_mask_bit(irq, entry->msi_attrib.masked);
 
-               tail = entry->link.tail;
-               irq = tail;
+       list_for_each_entry(entry, &dev->msi_list, list) {
+               write_msi_msg(entry->irq, &entry->msg);
+               msi_set_mask_bit(entry->irq, entry->msi_attrib.masked);
        }
 
+       BUG_ON(list_empty(&dev->msi_list));
+       entry = list_entry(dev->msi_list.next, struct msi_desc, list);
+       pos = entry->msi_attrib.pos;
        pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
        control &= ~PCI_MSIX_FLAGS_MASKALL;
        control |= PCI_MSIX_FLAGS_ENABLE;
@@ -303,7 +297,7 @@ void pci_restore_msi_state(struct pci_dev *dev)
 static int msi_capability_init(struct pci_dev *dev)
 {
        struct msi_desc *entry;
-       int pos, irq;
+       int pos, ret;
        u16 control;
 
        msi_set_enable(dev, 0); /* Ensure msi is disabled as I set it up */
@@ -340,23 +334,21 @@ static int msi_capability_init(struct pci_dev *dev)
                        msi_mask_bits_reg(pos, is_64bit_address(control)),
                        maskbits);
        }
+       list_add(&entry->list, &dev->msi_list);
+
        /* Configure MSI capability structure */
-       irq = arch_setup_msi_irq(dev, entry);
-       if (irq < 0) {
-               kmem_cache_free(msi_cachep, entry);
-               return irq;
+       ret = arch_setup_msi_irqs(dev, 1, PCI_CAP_ID_MSI);
+       if (ret) {
+               msi_free_irqs(dev);
+               return ret;
        }
-       entry->link.head = irq;
-       entry->link.tail = irq;
-       dev->first_msi_irq = irq;
-       set_irq_msi(irq, entry);
 
        /* Set MSI enabled bits  */
        pci_intx(dev, 0);               /* disable intx */
        msi_set_enable(dev, 1);
        dev->msi_enabled = 1;
 
-       dev->irq = irq;
+       dev->irq = entry->irq;
        return 0;
 }
 
@@ -373,8 +365,8 @@ static int msi_capability_init(struct pci_dev *dev)
 static int msix_capability_init(struct pci_dev *dev,
                                struct msix_entry *entries, int nvec)
 {
-       struct msi_desc *head = NULL, *tail = NULL, *entry = NULL;
-       int irq, pos, i, j, nr_entries, temp = 0;
+       struct msi_desc *entry;
+       int pos, i, j, nr_entries, ret;
        unsigned long phys_addr;
        u32 table_offset;
        u16 control;
@@ -413,44 +405,34 @@ static int msix_capability_init(struct pci_dev *dev,
                entry->dev = dev;
                entry->mask_base = base;
 
-               /* Configure MSI-X capability structure */
-               irq = arch_setup_msi_irq(dev, entry);
-               if (irq < 0) {
-                       kmem_cache_free(msi_cachep, entry);
-                       break;
-               }
-               entries[i].vector = irq;
-               if (!head) {
-                       entry->link.head = irq;
-                       entry->link.tail = irq;
-                       head = entry;
-               } else {
-                       entry->link.head = temp;
-                       entry->link.tail = tail->link.tail;
-                       tail->link.tail = irq;
-                       head->link.head = irq;
-               }
-               temp = irq;
-               tail = entry;
-
-               set_irq_msi(irq, entry);
+               list_add(&entry->list, &dev->msi_list);
        }
-       if (i != nvec) {
-               int avail = i - 1;
-               i--;
-               for (; i >= 0; i--) {
-                       irq = (entries + i)->vector;
-                       msi_free_irq(dev, irq);
-                       (entries + i)->vector = 0;
+
+       ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX);
+       if (ret) {
+               int avail = 0;
+               list_for_each_entry(entry, &dev->msi_list, list) {
+                       if (entry->irq != 0) {
+                               avail++;
+                       }
                }
+
+               msi_free_irqs(dev);
+
                /* If we had some success report the number of irqs
                 * we succeeded in setting up.
                 */
-               if (avail <= 0)
-                       avail = -EBUSY;
+               if (avail == 0)
+                       avail = ret;
                return avail;
        }
-       dev->first_msi_irq = entries[0].vector;
+
+       i = 0;
+       list_for_each_entry(entry, &dev->msi_list, list) {
+               entries[i].vector = entry->irq;
+               set_irq_msi(entry->irq, entry);
+               i++;
+       }
        /* Set MSI-X enabled bits */
        pci_intx(dev, 0);               /* disable intx */
        msix_set_enable(dev, 1);
@@ -460,21 +442,32 @@ static int msix_capability_init(struct pci_dev *dev,
 }
 
 /**
- * pci_msi_supported - check whether MSI may be enabled on device
+ * pci_msi_check_device - check whether MSI may be enabled on a device
  * @dev: pointer to the pci_dev data structure of MSI device function
+ * @nvec: how many MSIs have been requested ?
+ * @type: are we checking for MSI or MSI-X ?
  *
  * Look at global flags, the device itself, and its parent busses
- * to return 0 if MSI are supported for the device.
+ * to determine if MSI/-X are supported for the device. If MSI/-X is
+ * supported return 0, else return an error code.
  **/
-static
-int pci_msi_supported(struct pci_dev * dev)
+static int pci_msi_check_device(struct pci_dev* dev, int nvec, int type)
 {
        struct pci_bus *bus;
+       int ret;
 
        /* MSI must be globally enabled and supported by the device */
        if (!pci_msi_enable || !dev || dev->no_msi)
                return -EINVAL;
 
+       /*
+        * You can't ask to have 0 or less MSIs configured.
+        *  a) it's stupid ..
+        *  b) the list manipulation code assumes nvec >= 1.
+        */
+       if (nvec < 1)
+               return -ERANGE;
+
        /* Any bridge which does NOT route MSI transactions from it's
         * secondary bus to it's primary bus must set NO_MSI flag on
         * the secondary pci_bus.
@@ -485,6 +478,13 @@ int pci_msi_supported(struct pci_dev * dev)
                if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
                        return -EINVAL;
 
+       ret = arch_msi_check_device(dev, nvec, type);
+       if (ret)
+               return ret;
+
+       if (!pci_find_capability(dev, type))
+               return -EINVAL;
+
        return 0;
 }
 
@@ -500,19 +500,12 @@ int pci_msi_supported(struct pci_dev * dev)
  **/
 int pci_enable_msi(struct pci_dev* dev)
 {
-       int pos, status;
-
-       if (pci_msi_supported(dev) < 0)
-               return -EINVAL;
+       int status;
 
-       status = msi_init();
-       if (status < 0)
+       status = pci_msi_check_device(dev, 1, PCI_CAP_ID_MSI);
+       if (status)
                return status;
 
-       pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
-       if (!pos)
-               return -EINVAL;
-
        WARN_ON(!!dev->msi_enabled);
 
        /* Check whether driver already requested for MSI-X irqs */
@@ -525,69 +518,54 @@ int pci_enable_msi(struct pci_dev* dev)
        status = msi_capability_init(dev);
        return status;
 }
+EXPORT_SYMBOL(pci_enable_msi);
 
 void pci_disable_msi(struct pci_dev* dev)
 {
        struct msi_desc *entry;
        int default_irq;
 
-       if (!pci_msi_enable)
-               return;
-       if (!dev)
-               return;
-
-       if (!dev->msi_enabled)
+       if (!pci_msi_enable || !dev || !dev->msi_enabled)
                return;
 
        msi_set_enable(dev, 0);
        pci_intx(dev, 1);               /* enable intx */
        dev->msi_enabled = 0;
 
-       entry = get_irq_msi(dev->first_msi_irq);
-       if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) {
+       BUG_ON(list_empty(&dev->msi_list));
+       entry = list_entry(dev->msi_list.next, struct msi_desc, list);
+       if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) {
                return;
        }
-       if (irq_has_action(dev->first_msi_irq)) {
-               printk(KERN_WARNING "PCI: %s: pci_disable_msi() called without "
-                      "free_irq() on MSI irq %d\n",
-                      pci_name(dev), dev->first_msi_irq);
-               BUG_ON(irq_has_action(dev->first_msi_irq));
-       } else {
-               default_irq = entry->msi_attrib.default_irq;
-               msi_free_irq(dev, dev->first_msi_irq);
-
-               /* Restore dev->irq to its default pin-assertion irq */
-               dev->irq = default_irq;
-       }
-       dev->first_msi_irq = 0;
+
+       default_irq = entry->msi_attrib.default_irq;
+       msi_free_irqs(dev);
+
+       /* Restore dev->irq to its default pin-assertion irq */
+       dev->irq = default_irq;
 }
+EXPORT_SYMBOL(pci_disable_msi);
 
-static int msi_free_irq(struct pci_dev* dev, int irq)
+static int msi_free_irqs(struct pci_dev* dev)
 {
-       struct msi_desc *entry;
-       int head, entry_nr, type;
-       void __iomem *base;
+       struct msi_desc *entry, *tmp;
 
-       entry = get_irq_msi(irq);
-       if (!entry || entry->dev != dev) {
-               return -EINVAL;
-       }
-       type = entry->msi_attrib.type;
-       entry_nr = entry->msi_attrib.entry_nr;
-       head = entry->link.head;
-       base = entry->mask_base;
-       get_irq_msi(entry->link.head)->link.tail = entry->link.tail;
-       get_irq_msi(entry->link.tail)->link.head = entry->link.head;
-
-       arch_teardown_msi_irq(irq);
-       kmem_cache_free(msi_cachep, entry);
-
-       if (type == PCI_CAP_ID_MSIX) {
-               writel(1, base + entry_nr * PCI_MSIX_ENTRY_SIZE +
-                       PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
-
-               if (head == irq)
-                       iounmap(base);
+       list_for_each_entry(entry, &dev->msi_list, list)
+               BUG_ON(irq_has_action(entry->irq));
+
+       arch_teardown_msi_irqs(dev);
+
+       list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) {
+               if (entry->msi_attrib.type == PCI_CAP_ID_MSIX) {
+                       if (list_is_last(&entry->list, &dev->msi_list))
+                               iounmap(entry->mask_base);
+
+                       writel(1, entry->mask_base + entry->msi_attrib.entry_nr
+                                 * PCI_MSIX_ENTRY_SIZE
+                                 + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
+               }
+               list_del(&entry->list);
+               kfree(entry);
        }
 
        return 0;
@@ -614,17 +592,14 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
        int i, j;
        u16 control;
 
-       if (!entries || pci_msi_supported(dev) < 0)
+       if (!entries)
                return -EINVAL;
 
-       status = msi_init();
-       if (status < 0)
+       status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSIX);
+       if (status)
                return status;
 
        pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
-       if (!pos)
-               return -EINVAL;
-
        pci_read_config_word(dev, msi_control_reg(pos), &control);
        nr_entries = multi_msix_capable(control);
        if (nvec > nr_entries)
@@ -651,41 +626,25 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
        status = msix_capability_init(dev, entries, nvec);
        return status;
 }
+EXPORT_SYMBOL(pci_enable_msix);
 
-void pci_disable_msix(struct pci_dev* dev)
+static void msix_free_all_irqs(struct pci_dev *dev)
 {
-       int irq, head, tail = 0, warning = 0;
-
-       if (!pci_msi_enable)
-               return;
-       if (!dev)
-               return;
+       msi_free_irqs(dev);
+}
 
-       if (!dev->msix_enabled)
+void pci_disable_msix(struct pci_dev* dev)
+{
+       if (!pci_msi_enable || !dev || !dev->msix_enabled)
                return;
 
        msix_set_enable(dev, 0);
        pci_intx(dev, 1);               /* enable intx */
        dev->msix_enabled = 0;
 
-       irq = head = dev->first_msi_irq;
-       while (head != tail) {
-               tail = get_irq_msi(irq)->link.tail;
-               if (irq_has_action(irq))
-                       warning = 1;
-               else if (irq != head)   /* Release MSI-X irq */
-                       msi_free_irq(dev, irq);
-               irq = tail;
-       }
-       msi_free_irq(dev, irq);
-       if (warning) {
-               printk(KERN_WARNING "PCI: %s: pci_disable_msix() called without "
-                       "free_irq() on all MSI-X irqs\n",
-                       pci_name(dev));
-               BUG_ON(warning > 0);
-       }
-       dev->first_msi_irq = 0;
+       msix_free_all_irqs(dev);
 }
+EXPORT_SYMBOL(pci_disable_msix);
 
 /**
  * msi_remove_pci_irq_vectors - reclaim MSI(X) irqs to unused state
@@ -701,38 +660,11 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev)
        if (!pci_msi_enable || !dev)
                return;
 
-       if (dev->msi_enabled) {
-               if (irq_has_action(dev->first_msi_irq)) {
-                       printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() "
-                              "called without free_irq() on MSI irq %d\n",
-                              pci_name(dev), dev->first_msi_irq);
-                       BUG_ON(irq_has_action(dev->first_msi_irq));
-               } else /* Release MSI irq assigned to this device */
-                       msi_free_irq(dev, dev->first_msi_irq);
-       }
-       if (dev->msix_enabled) {
-               int irq, head, tail = 0, warning = 0;
-               void __iomem *base = NULL;
-
-               irq = head = dev->first_msi_irq;
-               while (head != tail) {
-                       tail = get_irq_msi(irq)->link.tail;
-                       base = get_irq_msi(irq)->mask_base;
-                       if (irq_has_action(irq))
-                               warning = 1;
-                       else if (irq != head) /* Release MSI-X irq */
-                               msi_free_irq(dev, irq);
-                       irq = tail;
-               }
-               msi_free_irq(dev, irq);
-               if (warning) {
-                       iounmap(base);
-                       printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() "
-                              "called without free_irq() on all MSI-X irqs\n",
-                              pci_name(dev));
-                       BUG_ON(warning > 0);
-               }
-       }
+       if (dev->msi_enabled)
+               msi_free_irqs(dev);
+
+       if (dev->msix_enabled)
+               msix_free_all_irqs(dev);
 }
 
 void pci_no_msi(void)
@@ -740,7 +672,53 @@ void pci_no_msi(void)
        pci_msi_enable = 0;
 }
 
-EXPORT_SYMBOL(pci_enable_msi);
-EXPORT_SYMBOL(pci_disable_msi);
-EXPORT_SYMBOL(pci_enable_msix);
-EXPORT_SYMBOL(pci_disable_msix);
+void pci_msi_init_pci_dev(struct pci_dev *dev)
+{
+       INIT_LIST_HEAD(&dev->msi_list);
+}
+
+
+/* Arch hooks */
+
+int __attribute__ ((weak))
+arch_msi_check_device(struct pci_dev* dev, int nvec, int type)
+{
+       return 0;
+}
+
+int __attribute__ ((weak))
+arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry)
+{
+       return 0;
+}
+
+int __attribute__ ((weak))
+arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+       struct msi_desc *entry;
+       int ret;
+
+       list_for_each_entry(entry, &dev->msi_list, list) {
+               ret = arch_setup_msi_irq(dev, entry);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq)
+{
+       return;
+}
+
+void __attribute__ ((weak))
+arch_teardown_msi_irqs(struct pci_dev *dev)
+{
+       struct msi_desc *entry;
+
+       list_for_each_entry(entry, &dev->msi_list, list) {
+               if (entry->irq != 0)
+                       arch_teardown_msi_irq(entry->irq);
+       }
+}
index 39e80fc..3bb7739 100644 (file)
 #include "pci.h"
 
 /*
- *  Registration of PCI drivers and handling of hot-pluggable devices.
- */
-
-/* multithreaded probe logic */
-static int pci_multithread_probe =
-#ifdef CONFIG_PCI_MULTITHREAD_PROBE
-       1;
-#else
-       0;
-#endif
-__module_param_call("", pci_multithread_probe, param_set_bool, param_get_bool, &pci_multithread_probe, 0644);
-
-
-/*
  * Dynamic device IDs are disabled for !CONFIG_HOTPLUG
  */
 
@@ -52,7 +38,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
 {
        struct pci_dynid *dynid;
        struct pci_driver *pdrv = to_pci_driver(driver);
-       __u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID,
+       __u32 vendor, device, subvendor=PCI_ANY_ID,
                subdevice=PCI_ANY_ID, class=0, class_mask=0;
        unsigned long driver_data=0;
        int fields=0;
@@ -61,7 +47,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
        fields = sscanf(buf, "%x %x %x %x %x %x %lux",
                        &vendor, &device, &subvendor, &subdevice,
                        &class, &class_mask, &driver_data);
-       if (fields < 0)
+       if (fields < 2)
                return -EINVAL;
 
        dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
@@ -569,7 +555,6 @@ struct bus_type pci_bus_type = {
 
 static int __init pci_driver_init(void)
 {
-       pci_bus_type.multithread_probe = pci_multithread_probe;
        return bus_register(&pci_bus_type);
 }
 
index cd913a2..284e83a 100644 (file)
@@ -620,7 +620,8 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
                goto err_bin_file;
 
        /* If the device has a ROM, try to expose it in sysfs. */
-       if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
+       if (pci_resource_len(pdev, PCI_ROM_RESOURCE) ||
+           (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)) {
                rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC);
                if (rom_attr) {
                        pdev->rom_attr = rom_attr;
@@ -635,7 +636,7 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
                                goto err_rom;
                } else {
                        retval = -ENOMEM;
-                       goto err_bin_file;
+                       goto err_resource_files;
                }
        }
        /* add platform-specific attributes */
@@ -645,6 +646,8 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
 
 err_rom:
        kfree(rom_attr);
+err_resource_files:
+       pci_remove_resource_files(pdev);
 err_bin_file:
        if (pdev->cfg_size < 4096)
                sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
@@ -695,4 +698,4 @@ static int __init pci_sysfs_init(void)
        return 0;
 }
 
-__initcall(pci_sysfs_init);
+late_initcall(pci_sysfs_init);
index 2a45827..fd47ac0 100644 (file)
@@ -35,8 +35,7 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
  * Given a PCI bus, returns the highest PCI bus number present in the set
  * including the given PCI bus and its list of child PCI buses.
  */
-unsigned char __devinit
-pci_bus_max_busnr(struct pci_bus* bus)
+unsigned char pci_bus_max_busnr(struct pci_bus* bus)
 {
        struct list_head *tmp;
        unsigned char max, n;
@@ -892,6 +891,34 @@ pci_disable_device(struct pci_dev *dev)
 }
 
 /**
+ * pcibios_set_pcie_reset_state - set reset state for device dev
+ * @dev: the PCI-E device reset
+ * @state: Reset state to enter into
+ *
+ *
+ * Sets the PCI-E reset state for the device. This is the default
+ * implementation. Architecture implementations can override this.
+ */
+int __attribute__ ((weak)) pcibios_set_pcie_reset_state(struct pci_dev *dev,
+                                                       enum pcie_reset_state state)
+{
+       return -EINVAL;
+}
+
+/**
+ * pci_set_pcie_reset_state - set reset state for device dev
+ * @dev: the PCI-E device reset
+ * @state: Reset state to enter into
+ *
+ *
+ * Sets the PCI reset state for the device.
+ */
+int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state)
+{
+       return pcibios_set_pcie_reset_state(dev, state);
+}
+
+/**
  * pci_enable_wake - enable PCI device as wakeup event source
  * @dev: PCI device affected
  * @state: PCI state from which device will issue wakeup events
@@ -1295,7 +1322,7 @@ pci_intx(struct pci_dev *pdev, int enable)
 
 /**
  * pci_msi_off - disables any msi or msix capabilities
- * @pdev: the PCI device to operate on
+ * @dev: the PCI device to operate on
  *
  * If you want to use msi see pci_enable_msi and friends.
  * This is a lower level primitive that allows us to disable
@@ -1427,4 +1454,5 @@ EXPORT_SYMBOL(pci_set_power_state);
 EXPORT_SYMBOL(pci_save_state);
 EXPORT_SYMBOL(pci_restore_state);
 EXPORT_SYMBOL(pci_enable_wake);
+EXPORT_SYMBOL_GPL(pci_set_pcie_reset_state);
 
index 62ea04c..3fec13d 100644 (file)
@@ -47,8 +47,10 @@ extern unsigned int pci_pm_d3_delay;
 
 #ifdef CONFIG_PCI_MSI
 void pci_no_msi(void);
+extern void pci_msi_init_pci_dev(struct pci_dev *dev);
 #else
 static inline void pci_no_msi(void) { }
+static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
 #endif
 
 #if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM)
index 2fe1d69..e48fcf0 100644 (file)
@@ -364,7 +364,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
        }
 }
 
-static struct pci_bus * __devinit pci_alloc_bus(void)
+static struct pci_bus * pci_alloc_bus(void)
 {
        struct pci_bus *b;
 
@@ -432,7 +432,7 @@ error_register:
        return NULL;
 }
 
-struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
+struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
 {
        struct pci_bus *child;
 
@@ -461,7 +461,7 @@ static void pci_enable_crs(struct pci_dev *dev)
        pci_write_config_word(dev, rpcap + PCI_EXP_RTCTL, rpctl);
 }
 
-static void __devinit pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
+static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
 {
        struct pci_bus *parent = child->parent;
 
@@ -477,7 +477,7 @@ static void __devinit pci_fixup_parent_subordinate_busnr(struct pci_bus *child,
        }
 }
 
-unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus);
+unsigned int pci_scan_child_bus(struct pci_bus *bus);
 
 /*
  * If it's a bridge, configure it and scan the bus behind it.
@@ -489,7 +489,7 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus);
  * them, we proceed to assigning numbers to the remaining buses in
  * order to avoid overlaps between old and new bus numbers.
  */
-int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass)
+int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass)
 {
        struct pci_bus *child;
        int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
@@ -846,6 +846,23 @@ static void pci_release_bus_bridge_dev(struct device *dev)
        kfree(dev);
 }
 
+struct pci_dev *alloc_pci_dev(void)
+{
+       struct pci_dev *dev;
+
+       dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
+       if (!dev)
+               return NULL;
+
+       INIT_LIST_HEAD(&dev->global_list);
+       INIT_LIST_HEAD(&dev->bus_list);
+
+       pci_msi_init_pci_dev(dev);
+
+       return dev;
+}
+EXPORT_SYMBOL(alloc_pci_dev);
+
 /*
  * Read the config data for a PCI device, sanity-check it
  * and fill in the dev structure...
@@ -885,7 +902,7 @@ pci_scan_device(struct pci_bus *bus, int devfn)
        if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type))
                return NULL;
 
-       dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
+       dev = alloc_pci_dev();
        if (!dev)
                return NULL;
 
@@ -912,7 +929,7 @@ pci_scan_device(struct pci_bus *bus, int devfn)
        return dev;
 }
 
-void __devinit pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
+void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
 {
        device_initialize(&dev->dev);
        dev->dev.release = pci_release_dev;
@@ -935,8 +952,7 @@ void __devinit pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
        up_write(&pci_bus_sem);
 }
 
-struct pci_dev * __devinit
-pci_scan_single_device(struct pci_bus *bus, int devfn)
+struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn)
 {
        struct pci_dev *dev;
 
@@ -958,7 +974,7 @@ pci_scan_single_device(struct pci_bus *bus, int devfn)
  * discovered devices to the @bus->devices list.  New devices
  * will have an empty dev->global_list head.
  */
-int __devinit pci_scan_slot(struct pci_bus *bus, int devfn)
+int pci_scan_slot(struct pci_bus *bus, int devfn)
 {
        int func, nr = 0;
        int scan_all_fns;
@@ -991,7 +1007,7 @@ int __devinit pci_scan_slot(struct pci_bus *bus, int devfn)
        return nr;
 }
 
-unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
+unsigned int pci_scan_child_bus(struct pci_bus *bus)
 {
        unsigned int devfn, pass, max = bus->secondary;
        struct pci_dev *dev;
@@ -1041,7 +1057,7 @@ unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus)
        return max;
 }
 
-struct pci_bus * __devinit pci_create_bus(struct device *parent,
+struct pci_bus * pci_create_bus(struct device *parent,
                int bus, struct pci_ops *ops, void *sysdata)
 {
        int error;
@@ -1119,7 +1135,7 @@ err_out:
 }
 EXPORT_SYMBOL_GPL(pci_create_bus);
 
-struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,
+struct pci_bus *pci_scan_bus_parented(struct device *parent,
                int bus, struct pci_ops *ops, void *sysdata)
 {
        struct pci_bus *b;
index 3411483..147d86f 100644 (file)
@@ -1648,6 +1648,8 @@ static void __devinit quirk_disable_msi(struct pci_dev *dev)
        }
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS400_200, quirk_disable_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disable_msi);
 
 /* Go through the list of Hypertransport capabilities and
  * return 1 if a HT MSI capability is found and enabled */
index 2dd8681..b137a27 100644 (file)
@@ -15,8 +15,7 @@
 
 DECLARE_RWSEM(pci_bus_sem);
 
-static struct pci_bus *
-pci_do_find_bus(struct pci_bus* bus, unsigned char busnr)
+static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)
 {
        struct pci_bus* child;
        struct list_head *tmp;
index 3554f39..5ec297d 100644 (file)
@@ -36,8 +36,7 @@
 
 #define ROUND_UP(x, a)         (((x) + (a) - 1) & ~((a) - 1))
 
-static void __devinit
-pbus_assign_resources_sorted(struct pci_bus *bus)
+static void pbus_assign_resources_sorted(struct pci_bus *bus)
 {
        struct pci_dev *dev;
        struct resource *res;
@@ -220,8 +219,7 @@ pci_setup_bridge(struct pci_bus *bus)
 /* Check whether the bridge supports optional I/O and
    prefetchable memory ranges. If not, the respective
    base/limit registers must be read-only and read as 0. */
-static void __devinit
-pci_bridge_check_ranges(struct pci_bus *bus)
+static void pci_bridge_check_ranges(struct pci_bus *bus)
 {
        u16 io;
        u32 pmem;
@@ -259,8 +257,7 @@ pci_bridge_check_ranges(struct pci_bus *bus)
    bus resource of a given type. Note: we intentionally skip
    the bus resources which have already been assigned (that is,
    have non-NULL parent resource). */
-static struct resource * __devinit
-find_free_bus_resource(struct pci_bus *bus, unsigned long type)
+static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned long type)
 {
        int i;
        struct resource *r;
@@ -281,8 +278,7 @@ find_free_bus_resource(struct pci_bus *bus, unsigned long type)
    since these windows have 4K granularity and the IO ranges
    of non-bridge PCI devices are limited to 256 bytes.
    We must be careful with the ISA aliasing though. */
-static void __devinit
-pbus_size_io(struct pci_bus *bus)
+static void pbus_size_io(struct pci_bus *bus)
 {
        struct pci_dev *dev;
        struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
@@ -326,8 +322,7 @@ pbus_size_io(struct pci_bus *bus)
 
 /* Calculate the size of the bus and minimal alignment which
    guarantees that all child resources fit in this size. */
-static int __devinit
-pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type)
+static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type)
 {
        struct pci_dev *dev;
        unsigned long min_align, align, size;
@@ -447,8 +442,7 @@ pci_bus_size_cardbus(struct pci_bus *bus)
        }
 }
 
-void __devinit
-pci_bus_size_bridges(struct pci_bus *bus)
+void pci_bus_size_bridges(struct pci_bus *bus)
 {
        struct pci_dev *dev;
        unsigned long mask, prefmask;
@@ -498,8 +492,7 @@ pci_bus_size_bridges(struct pci_bus *bus)
 }
 EXPORT_SYMBOL(pci_bus_size_bridges);
 
-void __devinit
-pci_bus_assign_resources(struct pci_bus *bus)
+void pci_bus_assign_resources(struct pci_bus *bus)
 {
        struct pci_bus *b;
        struct pci_dev *dev;
index cb4ced3..6dfd861 100644 (file)
@@ -101,8 +101,7 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
                new & ~PCI_REGION_FLAG_MASK);
 }
 
-int __devinit
-pci_claim_resource(struct pci_dev *dev, int resource)
+int pci_claim_resource(struct pci_dev *dev, int resource)
 {
        struct resource *res = &dev->resource[resource];
        struct resource *root = NULL;
@@ -212,8 +211,7 @@ EXPORT_SYMBOL_GPL(pci_assign_resource_fixed);
 #endif
 
 /* Sort resources by alignment */
-void __devinit
-pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
+void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
 {
        int i;
 
index ac00424..50cad3a 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
-#include <linux/pci.h>
 #include <linux/device.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
index ea5765c..a2bb465 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
-#include <linux/pci.h>
 #include <linux/device.h>
 #include <linux/mutex.h>
 #include <asm/system.h>
index d21e04c..1393e64 100644 (file)
 static int timeout = 5000;     /* in msec ( 5 sec ) */
 module_param(timeout, int, 0644);
 
-static struct ps3av ps3av;
+static struct ps3av {
+       int available;
+       struct mutex mutex;
+       struct work_struct work;
+       struct completion done;
+       struct workqueue_struct *wq;
+       int open_count;
+       struct ps3_vuart_port_device *dev;
+
+       int region;
+       struct ps3av_pkt_av_get_hw_conf av_hw_conf;
+       u32 av_port[PS3AV_AV_PORT_MAX + PS3AV_OPT_PORT_MAX];
+       u32 opt_port[PS3AV_OPT_PORT_MAX];
+       u32 head[PS3AV_HEAD_MAX];
+       u32 audio_port;
+       int ps3av_mode;
+       int ps3av_mode_old;
+} ps3av;
 
 static struct ps3_vuart_port_device ps3av_dev = {
        .match_id = PS3_MATCH_ID_AV_SETTINGS
@@ -159,7 +176,7 @@ static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr)
                else
                        printk(KERN_ERR
                               "%s: failed event packet, cid:%08x size:%d\n",
-                              __FUNCTION__, hdr->cid, hdr->size);
+                              __func__, hdr->cid, hdr->size);
                return 1;       /* receive event packet */
        }
        return 0;
@@ -181,7 +198,7 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
        if (res < 0) {
                dev_dbg(&ps3av_dev.core,
                        "%s: ps3av_vuart_write() failed (result=%d)\n",
-                       __FUNCTION__, res);
+                       __func__, res);
                return res;
        }
 
@@ -194,7 +211,7 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
                if (res != PS3AV_HDR_SIZE) {
                        dev_dbg(&ps3av_dev.core,
                                "%s: ps3av_vuart_read() failed (result=%d)\n",
-                               __FUNCTION__, res);
+                               __func__, res);
                        return res;
                }
 
@@ -204,7 +221,7 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
                if (res < 0) {
                        dev_dbg(&ps3av_dev.core,
                                "%s: ps3av_vuart_read() failed (result=%d)\n",
-                               __FUNCTION__, res);
+                               __func__, res);
                        return res;
                }
                res += PS3AV_HDR_SIZE;  /* total len */
@@ -214,7 +231,7 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
 
        if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) {
                dev_dbg(&ps3av_dev.core, "%s: reply err (result=%x)\n",
-                       __FUNCTION__, recv_buf->cid);
+                       __func__, recv_buf->cid);
                return -EINVAL;
        }
 
@@ -250,7 +267,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
                 struct ps3av_send_hdr *buf)
 {
        int res = 0;
-       union {
+       static union {
                struct ps3av_reply_hdr reply_hdr;
                u8 raw[PS3AV_BUF_SIZE];
        } recv_buf;
@@ -259,8 +276,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
 
        BUG_ON(!ps3av.available);
 
-       if (down_interruptible(&ps3av.sem))
-               return -ERESTARTSYS;
+       mutex_lock(&ps3av.mutex);
 
        table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK);
        BUG_ON(!table);
@@ -277,7 +293,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
        if (res < 0) {
                printk(KERN_ERR
                       "%s: ps3av_send_cmd_pkt() failed (result=%d)\n",
-                      __FUNCTION__, res);
+                      __func__, res);
                goto err;
        }
 
@@ -286,16 +302,16 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
                                         usr_buf_size);
        if (res < 0) {
                printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n",
-                      __FUNCTION__, res);
+                      __func__, res);
                goto err;
        }
 
-       up(&ps3av.sem);
+       mutex_unlock(&ps3av.mutex);
        return 0;
 
       err:
-       up(&ps3av.sem);
-       printk(KERN_ERR "%s: failed cid:%x res:%d\n", __FUNCTION__, cid, res);
+       mutex_unlock(&ps3av.mutex);
+       printk(KERN_ERR "%s: failed cid:%x res:%d\n", __func__, cid, res);
        return res;
 }
 
@@ -440,7 +456,7 @@ static int ps3av_set_videomode(void)
        ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON);
 
        /* wake up ps3avd to do the actual video mode setting */
-       up(&ps3av.ping);
+       queue_work(ps3av.wq, &ps3av.work);
 
        return 0;
 }
@@ -506,7 +522,7 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id)
        if (res == PS3AV_STATUS_NO_SYNC_HEAD)
                printk(KERN_WARNING
                       "%s: Command failed. Please try your request again. \n",
-                      __FUNCTION__);
+                      __func__);
        else if (res)
                dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n");
 
@@ -515,18 +531,10 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id)
        ps3av_set_av_video_mute(PS3AV_CMD_MUTE_OFF);
 }
 
-static int ps3avd(void *p)
+static void ps3avd(struct work_struct *work)
 {
-       struct ps3av *info = p;
-
-       daemonize("ps3avd");
-       while (1) {
-               down(&info->ping);
-               ps3av_set_videomode_cont(info->ps3av_mode,
-                                        info->ps3av_mode_old);
-               up(&info->pong);
-       }
-       return 0;
+       ps3av_set_videomode_cont(ps3av.ps3av_mode, ps3av.ps3av_mode_old);
+       complete(&ps3av.done);
 }
 
 static int ps3av_vid2table_id(int vid)
@@ -707,8 +715,7 @@ int ps3av_set_video_mode(u32 id, int boot)
 
        size = ARRAY_SIZE(video_mode_table);
        if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) {
-               dev_dbg(&ps3av_dev.core, "%s: error id :%d\n", __FUNCTION__,
-                       id);
+               dev_dbg(&ps3av_dev.core, "%s: error id :%d\n", __func__, id);
                return -EINVAL;
        }
 
@@ -717,15 +724,14 @@ int ps3av_set_video_mode(u32 id, int boot)
        if ((id & PS3AV_MODE_MASK) == 0) {
                id = ps3av_auto_videomode(&ps3av.av_hw_conf, boot);
                if (id < 1) {
-                       printk(KERN_ERR "%s: invalid id :%d\n", __FUNCTION__,
-                              id);
+                       printk(KERN_ERR "%s: invalid id :%d\n", __func__, id);
                        return -EINVAL;
                }
                id |= option;
        }
 
        /* set videomode */
-       down(&ps3av.pong);
+       wait_for_completion(&ps3av.done);
        ps3av.ps3av_mode_old = ps3av.ps3av_mode;
        ps3av.ps3av_mode = id;
        if (ps3av_set_videomode())
@@ -736,6 +742,13 @@ int ps3av_set_video_mode(u32 id, int boot)
 
 EXPORT_SYMBOL_GPL(ps3av_set_video_mode);
 
+int ps3av_get_auto_mode(int boot)
+{
+       return ps3av_auto_videomode(&ps3av.av_hw_conf, boot);
+}
+
+EXPORT_SYMBOL_GPL(ps3av_get_auto_mode);
+
 int ps3av_set_mode(u32 id, int boot)
 {
        int res;
@@ -771,7 +784,7 @@ int ps3av_get_scanmode(int id)
        id = id & PS3AV_MODE_MASK;
        size = ARRAY_SIZE(video_mode_table);
        if (id > size - 1 || id < 0) {
-               printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
+               printk(KERN_ERR "%s: invalid mode %d\n", __func__, id);
                return -EINVAL;
        }
        return video_mode_table[id].interlace;
@@ -786,7 +799,7 @@ int ps3av_get_refresh_rate(int id)
        id = id & PS3AV_MODE_MASK;
        size = ARRAY_SIZE(video_mode_table);
        if (id > size - 1 || id < 0) {
-               printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
+               printk(KERN_ERR "%s: invalid mode %d\n", __func__, id);
                return -EINVAL;
        }
        return video_mode_table[id].freq;
@@ -802,7 +815,7 @@ int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres)
        id = id & PS3AV_MODE_MASK;
        size = ARRAY_SIZE(video_mode_table);
        if (id > size - 1 || id < 0) {
-               printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
+               printk(KERN_ERR "%s: invalid mode %d\n", __func__, id);
                return -EINVAL;
        }
        *xres = video_mode_table[id].x;
@@ -838,7 +851,7 @@ int ps3av_dev_open(void)
                status = lv1_gpu_open(0);
                if (status) {
                        printk(KERN_ERR "%s: lv1_gpu_open failed %d\n",
-                              __FUNCTION__, status);
+                              __func__, status);
                        ps3av.open_count--;
                }
        }
@@ -855,13 +868,13 @@ int ps3av_dev_close(void)
 
        mutex_lock(&ps3av.mutex);
        if (ps3av.open_count <= 0) {
-               printk(KERN_ERR "%s: GPU already closed\n", __FUNCTION__);
+               printk(KERN_ERR "%s: GPU already closed\n", __func__);
                status = -1;
        } else if (!--ps3av.open_count) {
                status = lv1_gpu_close();
                if (status)
                        printk(KERN_WARNING "%s: lv1_gpu_close failed %d\n",
-                              __FUNCTION__, status);
+                              __func__, status);
        }
        mutex_unlock(&ps3av.mutex);
 
@@ -880,13 +893,16 @@ static int ps3av_probe(struct ps3_vuart_port_device *dev)
 
        memset(&ps3av, 0, sizeof(ps3av));
 
-       init_MUTEX(&ps3av.sem);
-       init_MUTEX_LOCKED(&ps3av.ping);
-       init_MUTEX(&ps3av.pong);
        mutex_init(&ps3av.mutex);
        ps3av.ps3av_mode = 0;
        ps3av.dev = dev;
-       kernel_thread(ps3avd, &ps3av, CLONE_KERNEL);
+
+       INIT_WORK(&ps3av.work, ps3avd);
+       init_completion(&ps3av.done);
+       complete(&ps3av.done);
+       ps3av.wq = create_singlethread_workqueue("ps3avd");
+       if (!ps3av.wq)
+               return -ENOMEM;
 
        ps3av.available = 1;
        switch (ps3_os_area_get_av_multi_out()) {
@@ -908,7 +924,7 @@ static int ps3av_probe(struct ps3_vuart_port_device *dev)
        /* init avsetting modules */
        res = ps3av_cmd_init();
        if (res < 0)
-               printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __FUNCTION__,
+               printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __func__,
                       res);
 
        ps3av_get_hw_conf(&ps3av);
@@ -926,6 +942,8 @@ static int ps3av_remove(struct ps3_vuart_port_device *dev)
 {
        if (ps3av.available) {
                ps3av_cmd_fin();
+               if (ps3av.wq)
+                       destroy_workqueue(ps3av.wq);
                ps3av.available = 0;
        }
 
@@ -958,7 +976,7 @@ static int ps3av_module_init(void)
        if (error) {
                printk(KERN_ERR
                       "%s: ps3_vuart_port_driver_register failed %d\n",
-                      __FUNCTION__, error);
+                      __func__, error);
                return error;
        }
 
@@ -966,7 +984,7 @@ static int ps3av_module_init(void)
        if (error)
                printk(KERN_ERR
                       "%s: ps3_vuart_port_device_register failed %d\n",
-                      __FUNCTION__, error);
+                      __func__, error);
 
        return error;
 }
index bc70e81..0145ea1 100644 (file)
@@ -395,7 +395,7 @@ u32 ps3av_cmd_set_video_mode(void *p, u32 head, int video_vid, int video_fmt,
        video_mode->video_order = ps3av_video_fmt_table[video_fmt].order;
 
        pr_debug("%s: video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n",
-               __FUNCTION__, video_vid, video_mode->width, video_mode->height,
+               __func__, video_vid, video_mode->width, video_mode->height,
                video_mode->pitch, video_mode->video_out_format,
                video_mode->video_format, video_mode->video_order);
        return sizeof(*video_mode);
@@ -477,7 +477,7 @@ static u8 ps3av_cnv_mclk(u32 fs)
                if (ps3av_cnv_mclk_table[i].fs == fs)
                        return ps3av_cnv_mclk_table[i].mclk;
 
-       printk(KERN_ERR "%s failed, fs:%x\n", __FUNCTION__, fs);
+       printk(KERN_ERR "%s failed, fs:%x\n", __func__, fs);
        return 0;
 }
 
@@ -526,13 +526,12 @@ static void ps3av_cnv_ns(u8 *ns, u32 fs, u32 video_vid)
                d = 4;
                break;
        default:
-               printk(KERN_ERR "%s failed, vid:%x\n", __FUNCTION__,
-                      video_vid);
+               printk(KERN_ERR "%s failed, vid:%x\n", __func__, video_vid);
                break;
        }
 
        if (fs < PS3AV_CMD_AUDIO_FS_44K || fs > PS3AV_CMD_AUDIO_FS_192K)
-               printk(KERN_ERR "%s failed, fs:%x\n", __FUNCTION__, fs);
+               printk(KERN_ERR "%s failed, fs:%x\n", __func__, fs);
        else
                ns_val = ps3av_ns_table[PS3AV_CMD_AUDIO_FS_44K-BASE][d];
 
@@ -555,8 +554,7 @@ static u8 ps3av_cnv_enable(u32 source, const u8 *enable)
                ret = ((p[0] << 4) + (p[1] << 5) + (p[2] << 6) + (p[3] << 7)) |
                      0x01;
        } else
-               printk(KERN_ERR "%s failed, source:%x\n", __FUNCTION__,
-                      source);
+               printk(KERN_ERR "%s failed, source:%x\n", __func__, source);
        return ret;
 }
 
@@ -585,7 +583,7 @@ static u8 ps3av_cnv_inputlen(u32 word_bits)
                ret = PS3AV_CMD_AV_INPUTLEN_24;
                break;
        default:
-               printk(KERN_ERR "%s failed, word_bits:%x\n", __FUNCTION__,
+               printk(KERN_ERR "%s failed, word_bits:%x\n", __func__,
                       word_bits);
                break;
        }
@@ -595,7 +593,7 @@ static u8 ps3av_cnv_inputlen(u32 word_bits)
 static u8 ps3av_cnv_layout(u32 num_of_ch)
 {
        if (num_of_ch > PS3AV_CMD_AUDIO_NUM_OF_CH_8) {
-               printk(KERN_ERR "%s failed, num_of_ch:%x\n", __FUNCTION__,
+               printk(KERN_ERR "%s failed, num_of_ch:%x\n", __func__,
                       num_of_ch);
                return 0;
        }
@@ -864,7 +862,7 @@ int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len)
 
        res = get_status(avb);
        if (res)
-               pr_debug("%s: PS3AV_CID_AVB_PARAM: failed %x\n", __FUNCTION__,
+               pr_debug("%s: PS3AV_CID_AVB_PARAM: failed %x\n", __func__,
                         res);
 
       out:
@@ -1013,7 +1011,7 @@ int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
                        return size;
                if (error != -EAGAIN) {
                        printk(KERN_ERR "%s: ps3_vuart_read failed %d\n",
-                              __FUNCTION__, error);
+                              __func__, error);
                        return error;
                }
                msleep(POLLING_INTERVAL);
index e71929d..9775210 100644 (file)
@@ -2174,6 +2174,51 @@ dasd_generic_notify(struct ccw_device *cdev, int event)
        return ret;
 }
 
+struct dasd_ccw_req * dasd_generic_build_rdc(struct dasd_device *device,
+                                            void *rdc_buffer,
+                                            int rdc_buffer_size, char *magic)
+{
+       struct dasd_ccw_req *cqr;
+       struct ccw1 *ccw;
+
+       cqr = dasd_smalloc_request(magic, 1 /* RDC */, rdc_buffer_size, device);
+
+       if (IS_ERR(cqr)) {
+               DEV_MESSAGE(KERN_WARNING, device, "%s",
+                           "Could not allocate RDC request");
+               return cqr;
+       }
+
+       ccw = cqr->cpaddr;
+       ccw->cmd_code = CCW_CMD_RDC;
+       ccw->cda = (__u32)(addr_t)rdc_buffer;
+       ccw->count = rdc_buffer_size;
+
+       cqr->device = device;
+       cqr->expires = 10*HZ;
+       clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+       cqr->retries = 2;
+       cqr->buildclk = get_clock();
+       cqr->status = DASD_CQR_FILLED;
+       return cqr;
+}
+
+
+int dasd_generic_read_dev_chars(struct dasd_device *device, char *magic,
+                               void **rdc_buffer, int rdc_buffer_size)
+{
+       int ret;
+       struct dasd_ccw_req *cqr;
+
+       cqr = dasd_generic_build_rdc(device, *rdc_buffer, rdc_buffer_size,
+                                    magic);
+       if (IS_ERR(cqr))
+               return PTR_ERR(cqr);
+
+       ret = dasd_sleep_on(cqr);
+       dasd_sfree_request(cqr, cqr->device);
+       return ret;
+}
 
 static int __init
 dasd_init(void)
index cecab22..c9583fb 100644 (file)
@@ -450,6 +450,81 @@ dasd_eckd_generate_uid(struct dasd_device *device, struct dasd_uid *uid)
        return 0;
 }
 
+struct dasd_ccw_req * dasd_eckd_build_rcd_lpm(struct dasd_device *device,
+                                             void *rcd_buffer,
+                                             struct ciw *ciw, __u8 lpm)
+{
+       struct dasd_ccw_req *cqr;
+       struct ccw1 *ccw;
+
+       cqr = dasd_smalloc_request("ECKD", 1 /* RCD */, ciw->count, device);
+
+       if (IS_ERR(cqr)) {
+               DEV_MESSAGE(KERN_WARNING, device, "%s",
+                           "Could not allocate RCD request");
+               return cqr;
+       }
+
+       ccw = cqr->cpaddr;
+       ccw->cmd_code = ciw->cmd;
+       ccw->cda = (__u32)(addr_t)rcd_buffer;
+       ccw->count = ciw->count;
+
+       cqr->device = device;
+       cqr->expires = 10*HZ;
+       cqr->lpm = lpm;
+       clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+       cqr->retries = 2;
+       cqr->buildclk = get_clock();
+       cqr->status = DASD_CQR_FILLED;
+       return cqr;
+}
+
+static int dasd_eckd_read_conf_lpm(struct dasd_device *device,
+                                  void **rcd_buffer,
+                                  int *rcd_buffer_size, __u8 lpm)
+{
+       struct ciw *ciw;
+       char *rcd_buf = NULL;
+       int ret;
+       struct dasd_ccw_req *cqr;
+
+       /*
+        * scan for RCD command in extended SenseID data
+        */
+       ciw = ccw_device_get_ciw(device->cdev, CIW_TYPE_RCD);
+       if (!ciw || ciw->cmd == 0) {
+               ret = -EOPNOTSUPP;
+               goto out_error;
+       }
+       rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA);
+       if (!rcd_buf) {
+               ret = -ENOMEM;
+               goto out_error;
+       }
+       cqr = dasd_eckd_build_rcd_lpm(device, rcd_buf, ciw, lpm);
+       if (IS_ERR(cqr)) {
+               ret =  PTR_ERR(cqr);
+               goto out_error;
+       }
+       ret = dasd_sleep_on(cqr);
+       /*
+        * on success we update the user input parms
+        */
+       dasd_sfree_request(cqr, cqr->device);
+       if (ret)
+               goto out_error;
+
+       *rcd_buffer_size = ciw->count;
+       *rcd_buffer = rcd_buf;
+       return 0;
+out_error:
+       kfree(rcd_buf);
+       *rcd_buffer = NULL;
+       *rcd_buffer_size = 0;
+       return ret;
+}
+
 static int
 dasd_eckd_read_conf(struct dasd_device *device)
 {
@@ -469,8 +544,8 @@ dasd_eckd_read_conf(struct dasd_device *device)
        /* get configuration data per operational path */
        for (lpm = 0x80; lpm; lpm>>= 1) {
                if (lpm & path_data->opm){
-                       rc = read_conf_data_lpm(device->cdev, &conf_data,
-                                               &conf_len, lpm);
+                       rc = dasd_eckd_read_conf_lpm(device, &conf_data,
+                                                    &conf_len, lpm);
                        if (rc && rc != -EOPNOTSUPP) {  /* -EOPNOTSUPP is ok */
                                MESSAGE(KERN_WARNING,
                                        "Read configuration data returned "
@@ -639,7 +714,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
        /* Read Device Characteristics */
        rdc_data = (void *) &(private->rdc_data);
        memset(rdc_data, 0, sizeof(rdc_data));
-       rc = read_dev_chars(device->cdev, &rdc_data, 64);
+       rc = dasd_generic_read_dev_chars(device, "ECKD", &rdc_data, 64);
        if (rc)
                DEV_MESSAGE(KERN_WARNING, device,
                            "Read device characteristics returned "
index be0909e..da16ead 100644 (file)
@@ -135,7 +135,7 @@ dasd_fba_check_characteristics(struct dasd_device *device)
        }
        /* Read Device Characteristics */
        rdc_data = (void *) &(private->rdc_data);
-       rc = read_dev_chars(device->cdev, &rdc_data, 32);
+       rc = dasd_generic_read_dev_chars(device, "FBA ", &rdc_data, 32);
        if (rc) {
                DEV_MESSAGE(KERN_WARNING, device,
                            "Read device characteristics returned error %d",
index a2cc69e..241294c 100644 (file)
@@ -509,6 +509,8 @@ int dasd_generic_set_online(struct ccw_device *, struct dasd_discipline *);
 int dasd_generic_set_offline (struct ccw_device *cdev);
 int dasd_generic_notify(struct ccw_device *, int);
 
+int dasd_generic_read_dev_chars(struct dasd_device *, char *, void **, int);
+
 /* externals in dasd_devmap.c */
 extern int dasd_max_devindex;
 extern int dasd_probeonly;
index bb4ff53..3b52f5c 100644 (file)
@@ -103,6 +103,7 @@ enum tape_op {
        TO_CRYPT_OFF,   /* Disable encrpytion */
        TO_KEKL_SET,    /* Set KEK label */
        TO_KEKL_QUERY,  /* Query KEK label */
+       TO_RDC,         /* Read device characteristics */
        TO_SIZE,        /* #entries in tape_op_t */
 };
 
index 50f5eda..7e2b2ab 100644 (file)
@@ -788,6 +788,7 @@ tape_3590_done(struct tape_device *device, struct tape_request *request)
        case TO_SIZE:
        case TO_KEKL_SET:
        case TO_KEKL_QUERY:
+       case TO_RDC:
                break;
        }
        return TAPE_IO_SUCCESS;
@@ -1549,6 +1550,26 @@ tape_3590_irq(struct tape_device *device, struct tape_request *request,
        return TAPE_IO_STOP;
 }
 
+
+static int tape_3590_read_dev_chars(struct tape_device *device,
+                                   struct tape_3590_rdc_data *rdc_data)
+{
+       int rc;
+       struct tape_request *request;
+
+       request = tape_alloc_request(1, sizeof(*rdc_data));
+       if (IS_ERR(request))
+               return PTR_ERR(request);
+       request->op = TO_RDC;
+       tape_ccw_end(request->cpaddr, CCW_CMD_RDC, sizeof(*rdc_data),
+                    request->cpdata);
+       rc = tape_do_io(device, request);
+       if (rc == 0)
+               memcpy(rdc_data, request->cpdata, sizeof(*rdc_data));
+       tape_free_request(request);
+       return rc;
+}
+
 /*
  * Setup device function
  */
@@ -1557,7 +1578,7 @@ tape_3590_setup_device(struct tape_device *device)
 {
        int rc;
        struct tape_3590_disc_data *data;
-       char *rdc_data;
+       struct tape_3590_rdc_data *rdc_data;
 
        DBF_EVENT(6, "3590 device setup\n");
        data = kzalloc(sizeof(struct tape_3590_disc_data), GFP_KERNEL | GFP_DMA);
@@ -1566,12 +1587,12 @@ tape_3590_setup_device(struct tape_device *device)
        data->read_back_op = READ_PREVIOUS;
        device->discdata = data;
 
-       rdc_data = kmalloc(64, GFP_KERNEL | GFP_DMA);
+       rdc_data = kmalloc(sizeof(*rdc_data), GFP_KERNEL | GFP_DMA);
        if (!rdc_data) {
                rc = -ENOMEM;
                goto fail_kmalloc;
        }
-       rc = read_dev_chars(device->cdev, (void**)&rdc_data, 64);
+       rc = tape_3590_read_dev_chars(device, rdc_data);
        if (rc) {
                DBF_LH(3, "Read device characteristics failed!\n");
                goto fail_kmalloc;
@@ -1579,7 +1600,7 @@ tape_3590_setup_device(struct tape_device *device)
        rc = tape_std_assign(device);
        if (rc)
                goto fail_rdc_data;
-       if (rdc_data[31] == 0x13) {
+       if (rdc_data->data[31] == 0x13) {
                PRINT_INFO("Device has crypto support\n");
                data->crypt_info.capability |= TAPE390_CRYPT_SUPPORTED_MASK;
                tape_3592_disable_crypt(device);
index aa51388..4534055 100644 (file)
@@ -129,6 +129,10 @@ struct tape_3590_med_sense {
        char pad2[116];
 } __attribute__ ((packed));
 
+struct tape_3590_rdc_data {
+       char data[64];
+} __attribute__ ((packed));
+
 /* Datastructures for 3592 encryption support */
 
 struct tape3592_kekl {
index e2a8a1a..2fae633 100644 (file)
@@ -73,7 +73,7 @@ const char *tape_op_verbose[TO_SIZE] =
        [TO_DIS] = "DIS",       [TO_ASSIGN] = "ASS",
        [TO_UNASSIGN] = "UAS",  [TO_CRYPT_ON] = "CON",
        [TO_CRYPT_OFF] = "COF", [TO_KEKL_SET] = "KLS",
-       [TO_KEKL_QUERY] = "KLQ",
+       [TO_KEKL_QUERY] = "KLQ",[TO_RDC] = "RDC",
 };
 
 static int
@@ -911,6 +911,7 @@ __tape_start_request(struct tape_device *device, struct tape_request *request)
                case TO_ASSIGN:
                case TO_UNASSIGN:
                case TO_READ_ATTMSG:
+               case TO_RDC:
                        if (device->tape_state == TS_INIT)
                                break;
                        if (device->tape_state == TS_UNUSED)
index 05fac07..cba64e4 100644 (file)
@@ -69,7 +69,6 @@ static const char version[] = "QDIO base support version 2";
 
 static int qdio_performance_stats = 0;
 static int proc_perf_file_registration;
-static unsigned long i_p_c, i_p_nc, o_p_c, o_p_nc, ii_p_c, ii_p_nc;
 static struct qdio_perf_stats perf_stats;
 
 static int hydra_thinints;
@@ -111,6 +110,31 @@ qdio_min(int a,int b)
 }
 
 /***************** SCRUBBER HELPER ROUTINES **********************/
+#ifdef CONFIG_64BIT
+static inline void qdio_perf_stat_inc(atomic64_t *count)
+{
+       if (qdio_performance_stats)
+               atomic64_inc(count);
+}
+
+static inline void qdio_perf_stat_dec(atomic64_t *count)
+{
+       if (qdio_performance_stats)
+               atomic64_dec(count);
+}
+#else /* CONFIG_64BIT */
+static inline void qdio_perf_stat_inc(atomic_t *count)
+{
+       if (qdio_performance_stats)
+               atomic_inc(count);
+}
+
+static inline void qdio_perf_stat_dec(atomic_t *count)
+{
+       if (qdio_performance_stats)
+               atomic_dec(count);
+}
+#endif /* CONFIG_64BIT */
 
 static inline __u64 
 qdio_get_micros(void)
@@ -277,8 +301,7 @@ qdio_siga_sync(struct qdio_q *q, unsigned int gpr2,
        QDIO_DBF_TEXT4(0,trace,"sigasync");
        QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
 
-       if (qdio_performance_stats)
-               perf_stats.siga_syncs++;
+       qdio_perf_stat_inc(&perf_stats.siga_syncs);
 
        cc = do_siga_sync(q->schid, gpr2, gpr3);
        if (cc)
@@ -323,8 +346,7 @@ qdio_siga_output(struct qdio_q *q)
        __u32 busy_bit;
        __u64 start_time=0;
 
-       if (qdio_performance_stats)
-               perf_stats.siga_outs++;
+       qdio_perf_stat_inc(&perf_stats.siga_outs);
 
        QDIO_DBF_TEXT4(0,trace,"sigaout");
        QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
@@ -358,8 +380,7 @@ qdio_siga_input(struct qdio_q *q)
        QDIO_DBF_TEXT4(0,trace,"sigain");
        QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
 
-       if (qdio_performance_stats)
-               perf_stats.siga_ins++;
+       qdio_perf_stat_inc(&perf_stats.siga_ins);
 
        cc = do_siga_input(q->schid, q->mask);
        
@@ -953,8 +974,7 @@ __qdio_outbound_processing(struct qdio_q *q)
 
        if (unlikely(qdio_reserve_q(q))) {
                qdio_release_q(q);
-               if (qdio_performance_stats)
-                       o_p_c++;
+               qdio_perf_stat_inc(&perf_stats.outbound_tl_runs_resched);
                /* as we're sissies, we'll check next time */
                if (likely(!atomic_read(&q->is_in_shutdown))) {
                        qdio_mark_q(q);
@@ -962,10 +982,8 @@ __qdio_outbound_processing(struct qdio_q *q)
                }
                return;
        }
-       if (qdio_performance_stats) {
-               o_p_nc++;
-               perf_stats.tl_runs++;
-       }
+       qdio_perf_stat_inc(&perf_stats.outbound_tl_runs);
+       qdio_perf_stat_inc(&perf_stats.tl_runs);
 
        /* see comment in qdio_kick_outbound_q */
        siga_attempts=atomic_read(&q->busy_siga_counter);
@@ -1139,17 +1157,6 @@ qdio_has_inbound_q_moved(struct qdio_q *q)
 {
        int i;
 
-       static int old_pcis=0;
-       static int old_thinints=0;
-
-       if (qdio_performance_stats) {
-               if ((old_pcis==perf_stats.pcis)&&
-                   (old_thinints==perf_stats.thinints))
-                       perf_stats.start_time_inbound=NOW;
-               else
-                       old_pcis=perf_stats.pcis;
-       }
-
        i=qdio_get_inbound_buffer_frontier(q);
        if ( (i!=GET_SAVED_FRONTIER(q)) ||
             (q->error_status_flags&QDIO_STATUS_LOOK_FOR_ERROR) ) {
@@ -1337,10 +1344,7 @@ qdio_kick_inbound_handler(struct qdio_q *q)
        q->siga_error=0;
        q->error_status_flags=0;
 
-       if (qdio_performance_stats) {
-               perf_stats.inbound_time+=NOW-perf_stats.start_time_inbound;
-               perf_stats.inbound_cnt++;
-       }
+       qdio_perf_stat_inc(&perf_stats.inbound_cnt);
 }
 
 static void
@@ -1360,8 +1364,7 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set)
         */
        if (unlikely(qdio_reserve_q(q))) {
                qdio_release_q(q);
-               if (qdio_performance_stats)
-                       ii_p_c++;
+               qdio_perf_stat_inc(&perf_stats.inbound_thin_tl_runs_resched);
                /* 
                 * as we might just be about to stop polling, we make
                 * sure that we check again at least once more 
@@ -1369,8 +1372,7 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set)
                tiqdio_sched_tl();
                return;
        }
-       if (qdio_performance_stats)
-               ii_p_nc++;
+       qdio_perf_stat_inc(&perf_stats.inbound_thin_tl_runs);
        if (unlikely(atomic_read(&q->is_in_shutdown))) {
                qdio_unmark_q(q);
                goto out;
@@ -1412,8 +1414,7 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set)
                for (i=0;i<irq_ptr->no_output_qs;i++) {
                        oq = irq_ptr->output_qs[i];
                        if (!qdio_is_outbound_q_done(oq)) {
-                               if (qdio_performance_stats)
-                                       perf_stats.tl_runs--;
+                               qdio_perf_stat_dec(&perf_stats.tl_runs);
                                __qdio_outbound_processing(oq);
                        }
                }
@@ -1452,8 +1453,7 @@ __qdio_inbound_processing(struct qdio_q *q)
 
        if (unlikely(qdio_reserve_q(q))) {
                qdio_release_q(q);
-               if (qdio_performance_stats)
-                       i_p_c++;
+               qdio_perf_stat_inc(&perf_stats.inbound_tl_runs_resched);
                /* as we're sissies, we'll check next time */
                if (likely(!atomic_read(&q->is_in_shutdown))) {
                        qdio_mark_q(q);
@@ -1461,10 +1461,8 @@ __qdio_inbound_processing(struct qdio_q *q)
                }
                return;
        }
-       if (qdio_performance_stats) {
-               i_p_nc++;
-               perf_stats.tl_runs++;
-       }
+       qdio_perf_stat_inc(&perf_stats.inbound_tl_runs);
+       qdio_perf_stat_inc(&perf_stats.tl_runs);
 
 again:
        if (qdio_has_inbound_q_moved(q)) {
@@ -1510,8 +1508,7 @@ tiqdio_reset_processing_state(struct qdio_q *q, int q_laps)
 
        if (unlikely(qdio_reserve_q(q))) {
                qdio_release_q(q);
-               if (qdio_performance_stats)
-                       ii_p_c++;
+               qdio_perf_stat_inc(&perf_stats.inbound_thin_tl_runs_resched);
                /* 
                 * as we might just be about to stop polling, we make
                 * sure that we check again at least once more 
@@ -1602,8 +1599,7 @@ tiqdio_tl(unsigned long data)
 {
        QDIO_DBF_TEXT4(0,trace,"iqdio_tl");
 
-       if (qdio_performance_stats)
-               perf_stats.tl_runs++;
+       qdio_perf_stat_inc(&perf_stats.tl_runs);
 
        tiqdio_inbound_checks();
 }
@@ -1914,10 +1910,7 @@ tiqdio_thinint_handler(void)
 {
        QDIO_DBF_TEXT4(0,trace,"thin_int");
 
-       if (qdio_performance_stats) {
-               perf_stats.thinints++;
-               perf_stats.start_time_inbound=NOW;
-       }
+       qdio_perf_stat_inc(&perf_stats.thinints);
 
        /* SVS only when needed:
         * issue SVS to benefit from iqdio interrupt avoidance
@@ -1972,17 +1965,12 @@ qdio_handle_pci(struct qdio_irq *irq_ptr)
        int i;
        struct qdio_q *q;
 
-       if (qdio_performance_stats) {
-               perf_stats.pcis++;
-               perf_stats.start_time_inbound=NOW;
-       }
+       qdio_perf_stat_inc(&perf_stats.pcis);
        for (i=0;i<irq_ptr->no_input_qs;i++) {
                q=irq_ptr->input_qs[i];
                if (q->is_input_q&QDIO_FLAG_NO_INPUT_INTERRUPT_CONTEXT)
                        qdio_mark_q(q);
                else {
-                       if (qdio_performance_stats)
-                               perf_stats.tl_runs--;
                        __qdio_inbound_processing(q);
                }
        }
@@ -1992,8 +1980,7 @@ qdio_handle_pci(struct qdio_irq *irq_ptr)
                q=irq_ptr->output_qs[i];
                if (qdio_is_outbound_q_done(q))
                        continue;
-               if (qdio_performance_stats)
-                       perf_stats.tl_runs--;
+               qdio_perf_stat_dec(&perf_stats.tl_runs);
                if (!irq_ptr->sync_done_on_outb_pcis)
                        SYNC_MEMORY;
                __qdio_outbound_processing(q);
@@ -3463,18 +3450,12 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
        struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
 
        /* This is the outbound handling of queues */
-       if (qdio_performance_stats)
-               perf_stats.start_time_outbound=NOW;
-
        qdio_do_qdio_fill_output(q,qidx,count,buffers);
 
        used_elements=atomic_add_return(count, &q->number_of_buffers_used) - count;
 
        if (callflags&QDIO_FLAG_DONT_SIGA) {
-               if (qdio_performance_stats) {
-                       perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound;
-                       perf_stats.outbound_cnt++;
-               }
+               qdio_perf_stat_inc(&perf_stats.outbound_cnt);
                return;
        }
        if (q->is_iqdio_q) {
@@ -3504,8 +3485,7 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
                                qdio_kick_outbound_q(q);
                        } else {
                                QDIO_DBF_TEXT3(0,trace, "fast-req");
-                               if (qdio_performance_stats)
-                                       perf_stats.fast_reqs++;
+                               qdio_perf_stat_inc(&perf_stats.fast_reqs);
                        }
                }
                /* 
@@ -3516,10 +3496,7 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
                __qdio_outbound_processing(q);
        }
 
-       if (qdio_performance_stats) {
-               perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound;
-               perf_stats.outbound_cnt++;
-       }
+       qdio_perf_stat_inc(&perf_stats.outbound_cnt);
 }
 
 /* count must be 1 in iqdio */
@@ -3589,33 +3566,67 @@ qdio_perf_procfile_read(char *buffer, char **buffer_location, off_t offset,
                return 0;
 
 #define _OUTP_IT(x...) c+=sprintf(buffer+c,x)
-       _OUTP_IT("i_p_nc/c=%lu/%lu\n",i_p_nc,i_p_c);
-       _OUTP_IT("ii_p_nc/c=%lu/%lu\n",ii_p_nc,ii_p_c);
-       _OUTP_IT("o_p_nc/c=%lu/%lu\n",o_p_nc,o_p_c);
-       _OUTP_IT("Number of tasklet runs (total)                  : %lu\n",
-                perf_stats.tl_runs);
+#ifdef CONFIG_64BIT
+       _OUTP_IT("Number of tasklet runs (total)                  : %li\n",
+                (long)atomic64_read(&perf_stats.tl_runs));
+       _OUTP_IT("Inbound tasklet runs      tried/retried         : %li/%li\n",
+                (long)atomic64_read(&perf_stats.inbound_tl_runs),
+                (long)atomic64_read(&perf_stats.inbound_tl_runs_resched));
+       _OUTP_IT("Inbound-thin tasklet runs tried/retried         : %li/%li\n",
+                (long)atomic64_read(&perf_stats.inbound_thin_tl_runs),
+                (long)atomic64_read(&perf_stats.inbound_thin_tl_runs_resched));
+       _OUTP_IT("Outbound tasklet runs     tried/retried         : %li/%li\n",
+                (long)atomic64_read(&perf_stats.outbound_tl_runs),
+                (long)atomic64_read(&perf_stats.outbound_tl_runs_resched));
        _OUTP_IT("\n");
-       _OUTP_IT("Number of SIGA sync's issued                    : %lu\n",
-                perf_stats.siga_syncs);
-       _OUTP_IT("Number of SIGA in's issued                      : %lu\n",
-                perf_stats.siga_ins);
-       _OUTP_IT("Number of SIGA out's issued                     : %lu\n",
-                perf_stats.siga_outs);
-       _OUTP_IT("Number of PCIs caught                           : %lu\n",
-                perf_stats.pcis);
-       _OUTP_IT("Number of adapter interrupts caught             : %lu\n",
-                perf_stats.thinints);
-       _OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA)  : %lu\n",
-                perf_stats.fast_reqs);
+       _OUTP_IT("Number of SIGA sync's issued                    : %li\n",
+                (long)atomic64_read(&perf_stats.siga_syncs));
+       _OUTP_IT("Number of SIGA in's issued                      : %li\n",
+                (long)atomic64_read(&perf_stats.siga_ins));
+       _OUTP_IT("Number of SIGA out's issued                     : %li\n",
+                (long)atomic64_read(&perf_stats.siga_outs));
+       _OUTP_IT("Number of PCIs caught                           : %li\n",
+                (long)atomic64_read(&perf_stats.pcis));
+       _OUTP_IT("Number of adapter interrupts caught             : %li\n",
+                (long)atomic64_read(&perf_stats.thinints));
+       _OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA)  : %li\n",
+                (long)atomic64_read(&perf_stats.fast_reqs));
        _OUTP_IT("\n");
-       _OUTP_IT("Total time of all inbound actions (us) incl. UL : %lu\n",
-                perf_stats.inbound_time);
-       _OUTP_IT("Number of inbound transfers                     : %lu\n",
-                perf_stats.inbound_cnt);
-       _OUTP_IT("Total time of all outbound do_QDIOs (us)        : %lu\n",
-                perf_stats.outbound_time);
-       _OUTP_IT("Number of do_QDIOs outbound                     : %lu\n",
-                perf_stats.outbound_cnt);
+       _OUTP_IT("Number of inbound transfers                     : %li\n",
+                (long)atomic64_read(&perf_stats.inbound_cnt));
+       _OUTP_IT("Number of do_QDIOs outbound                     : %li\n",
+                (long)atomic64_read(&perf_stats.outbound_cnt));
+#else /* CONFIG_64BIT */
+       _OUTP_IT("Number of tasklet runs (total)                  : %i\n",
+                atomic_read(&perf_stats.tl_runs));
+       _OUTP_IT("Inbound tasklet runs      tried/retried         : %i/%i\n",
+                atomic_read(&perf_stats.inbound_tl_runs),
+                atomic_read(&perf_stats.inbound_tl_runs_resched));
+       _OUTP_IT("Inbound-thin tasklet runs tried/retried         : %i/%i\n",
+                atomic_read(&perf_stats.inbound_thin_tl_runs),
+                atomic_read(&perf_stats.inbound_thin_tl_runs_resched));
+       _OUTP_IT("Outbound tasklet runs     tried/retried         : %i/%i\n",
+                atomic_read(&perf_stats.outbound_tl_runs),
+                atomic_read(&perf_stats.outbound_tl_runs_resched));
+       _OUTP_IT("\n");
+       _OUTP_IT("Number of SIGA sync's issued                    : %i\n",
+                atomic_read(&perf_stats.siga_syncs));
+       _OUTP_IT("Number of SIGA in's issued                      : %i\n",
+                atomic_read(&perf_stats.siga_ins));
+       _OUTP_IT("Number of SIGA out's issued                     : %i\n",
+                atomic_read(&perf_stats.siga_outs));
+       _OUTP_IT("Number of PCIs caught                           : %i\n",
+                atomic_read(&perf_stats.pcis));
+       _OUTP_IT("Number of adapter interrupts caught             : %i\n",
+                atomic_read(&perf_stats.thinints));
+       _OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA)  : %i\n",
+                atomic_read(&perf_stats.fast_reqs));
+       _OUTP_IT("\n");
+       _OUTP_IT("Number of inbound transfers                     : %i\n",
+                atomic_read(&perf_stats.inbound_cnt));
+       _OUTP_IT("Number of do_QDIOs outbound                     : %i\n",
+                atomic_read(&perf_stats.outbound_cnt));
+#endif /* CONFIG_64BIT */
        _OUTP_IT("\n");
 
         return c;
@@ -3642,8 +3653,6 @@ qdio_add_procfs_entry(void)
 static void
 qdio_remove_procfs_entry(void)
 {
-       perf_stats.tl_runs=0;
-
         if (!proc_perf_file_registration) /* means if it went ok earlier */
                remove_proc_entry(QDIO_PERF,&proc_root);
 }
@@ -3671,13 +3680,38 @@ qdio_performance_stats_store(struct bus_type *bus, const char *buf, size_t count
                qdio_performance_stats = i;
                if (i==0) {
                        /* reset perf. stat. info */
-                       i_p_nc = 0;
-                       i_p_c = 0;
-                       ii_p_nc = 0;
-                       ii_p_c = 0;
-                       o_p_nc = 0;
-                       o_p_c = 0;
-                       memset(&perf_stats, 0, sizeof(struct qdio_perf_stats));
+#ifdef CONFIG_64BIT
+                       atomic64_set(&perf_stats.tl_runs, 0);
+                       atomic64_set(&perf_stats.outbound_tl_runs, 0);
+                       atomic64_set(&perf_stats.inbound_tl_runs, 0);
+                       atomic64_set(&perf_stats.inbound_tl_runs_resched, 0);
+                       atomic64_set(&perf_stats.inbound_thin_tl_runs, 0);
+                       atomic64_set(&perf_stats.inbound_thin_tl_runs_resched,
+                                    0);
+                       atomic64_set(&perf_stats.siga_outs, 0);
+                       atomic64_set(&perf_stats.siga_ins, 0);
+                       atomic64_set(&perf_stats.siga_syncs, 0);
+                       atomic64_set(&perf_stats.pcis, 0);
+                       atomic64_set(&perf_stats.thinints, 0);
+                       atomic64_set(&perf_stats.fast_reqs, 0);
+                       atomic64_set(&perf_stats.outbound_cnt, 0);
+                       atomic64_set(&perf_stats.inbound_cnt, 0);
+#else /* CONFIG_64BIT */
+                       atomic_set(&perf_stats.tl_runs, 0);
+                       atomic_set(&perf_stats.outbound_tl_runs, 0);
+                       atomic_set(&perf_stats.inbound_tl_runs, 0);
+                       atomic_set(&perf_stats.inbound_tl_runs_resched, 0);
+                       atomic_set(&perf_stats.inbound_thin_tl_runs, 0);
+                       atomic_set(&perf_stats.inbound_thin_tl_runs_resched, 0);
+                       atomic_set(&perf_stats.siga_outs, 0);
+                       atomic_set(&perf_stats.siga_ins, 0);
+                       atomic_set(&perf_stats.siga_syncs, 0);
+                       atomic_set(&perf_stats.pcis, 0);
+                       atomic_set(&perf_stats.thinints, 0);
+                       atomic_set(&perf_stats.fast_reqs, 0);
+                       atomic_set(&perf_stats.outbound_cnt, 0);
+                       atomic_set(&perf_stats.inbound_cnt, 0);
+#endif /* CONFIG_64BIT */
                }
        } else {
                QDIO_PRINT_WARN("QDIO performance_stats: write 0 or 1 to this file!\n");
index ec9af72..2895392 100644 (file)
@@ -406,21 +406,43 @@ do_clear_global_summary(void)
 #define CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS 0x04
 
 struct qdio_perf_stats {
-       unsigned long tl_runs;
-
-       unsigned long siga_outs;
-       unsigned long siga_ins;
-       unsigned long siga_syncs;
-       unsigned long pcis;
-       unsigned long thinints;
-       unsigned long fast_reqs;
-
-       __u64 start_time_outbound;
-       unsigned long outbound_cnt;
-       unsigned long outbound_time;
-       __u64 start_time_inbound;
-       unsigned long inbound_cnt;
-       unsigned long inbound_time;
+#ifdef CONFIG_64BIT
+       atomic64_t tl_runs;
+       atomic64_t outbound_tl_runs;
+       atomic64_t outbound_tl_runs_resched;
+       atomic64_t inbound_tl_runs;
+       atomic64_t inbound_tl_runs_resched;
+       atomic64_t inbound_thin_tl_runs;
+       atomic64_t inbound_thin_tl_runs_resched;
+
+       atomic64_t siga_outs;
+       atomic64_t siga_ins;
+       atomic64_t siga_syncs;
+       atomic64_t pcis;
+       atomic64_t thinints;
+       atomic64_t fast_reqs;
+
+       atomic64_t outbound_cnt;
+       atomic64_t inbound_cnt;
+#else /* CONFIG_64BIT */
+       atomic_t tl_runs;
+       atomic_t outbound_tl_runs;
+       atomic_t outbound_tl_runs_resched;
+       atomic_t inbound_tl_runs;
+       atomic_t inbound_tl_runs_resched;
+       atomic_t inbound_thin_tl_runs;
+       atomic_t inbound_thin_tl_runs_resched;
+
+       atomic_t siga_outs;
+       atomic_t siga_ins;
+       atomic_t siga_syncs;
+       atomic_t pcis;
+       atomic_t thinints;
+       atomic_t fast_reqs;
+
+       atomic_t outbound_cnt;
+       atomic_t inbound_cnt;
+#endif /* CONFIG_64BIT */
 };
 
 /* unlikely as the later the better */
index 84b108d..b34eb82 100644 (file)
@@ -288,6 +288,7 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
  */
 #define IF_NAME_LEN            16
 #define QETH_TX_TIMEOUT                100 * HZ
+#define QETH_RCD_TIMEOUT       60 * HZ
 #define QETH_HEADER_SIZE       32
 #define MAX_PORTNO             15
 #define QETH_FAKE_LL_LEN_ETH   ETH_HLEN
@@ -582,6 +583,8 @@ enum qeth_channel_states {
        CH_STATE_ACTIVATING,
        CH_STATE_HALTED,
        CH_STATE_STOPPED,
+       CH_STATE_RCD,
+       CH_STATE_RCD_DONE,
 };
 /**
  * card state machine
index ad7792d..6fd8870 100644 (file)
@@ -315,7 +315,8 @@ qeth_alloc_card(void)
 }
 
 static long
-__qeth_check_irb_error(struct ccw_device *cdev, struct irb *irb)
+__qeth_check_irb_error(struct ccw_device *cdev, unsigned long intparm,
+                      struct irb *irb)
 {
        if (!IS_ERR(irb))
                return 0;
@@ -330,6 +331,14 @@ __qeth_check_irb_error(struct ccw_device *cdev, struct irb *irb)
                PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id);
                QETH_DBF_TEXT(trace, 2, "ckirberr");
                QETH_DBF_TEXT_(trace, 2, "  rc%d", -ETIMEDOUT);
+               if (intparm == QETH_RCD_PARM) {
+                       struct qeth_card *card = CARD_FROM_CDEV(cdev);
+
+                       if (card && (card->data.ccwdev == cdev)) {
+                               card->data.state = CH_STATE_DOWN;
+                               wake_up(&card->wait_q);
+                       }
+               }
                break;
        default:
                PRINT_WARN("unknown error %ld on device %s\n", PTR_ERR(irb),
@@ -401,7 +410,7 @@ qeth_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
 
        QETH_DBF_TEXT(trace,5,"irq");
 
-       if (__qeth_check_irb_error(cdev, irb))
+       if (__qeth_check_irb_error(cdev, intparm, irb))
                return;
        cstat = irb->scsw.cstat;
        dstat = irb->scsw.dstat;
@@ -429,7 +438,8 @@ qeth_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
                channel->state = CH_STATE_HALTED;
 
        /*let's wake up immediately on data channel*/
-       if ((channel == &card->data) && (intparm != 0))
+       if ((channel == &card->data) && (intparm != 0) &&
+           (intparm != QETH_RCD_PARM))
                goto out;
 
        if (intparm == QETH_CLEAR_CHANNEL_PARM) {
@@ -453,6 +463,10 @@ qeth_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
                        HEXDUMP16(WARN,"irb: ",irb);
                        HEXDUMP16(WARN,"sense data: ",irb->ecw);
                }
+               if (intparm == QETH_RCD_PARM) {
+                       channel->state = CH_STATE_DOWN;
+                       goto out;
+               }
                rc = qeth_get_problem(cdev,irb);
                if (rc) {
                        qeth_schedule_recovery(card);
@@ -460,6 +474,10 @@ qeth_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
                }
        }
 
+       if (intparm == QETH_RCD_PARM) {
+               channel->state = CH_STATE_RCD_DONE;
+               goto out;
+       }
        if (intparm) {
                buffer = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
                buffer->state = BUF_STATE_PROCESSED;
@@ -1204,6 +1222,54 @@ qeth_probe_device(struct ccwgroup_device *gdev)
 }
 
 
+static int qeth_read_conf_data(struct qeth_card *card, void **buffer,
+                              int *length)
+{
+       struct ciw *ciw;
+       char *rcd_buf;
+       int ret;
+       struct qeth_channel *channel = &card->data;
+       unsigned long flags;
+
+       /*
+        * scan for RCD command in extended SenseID data
+        */
+       ciw = ccw_device_get_ciw(channel->ccwdev, CIW_TYPE_RCD);
+       if (!ciw || ciw->cmd == 0)
+               return -EOPNOTSUPP;
+       rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA);
+       if (!rcd_buf)
+               return -ENOMEM;
+
+       channel->ccw.cmd_code = ciw->cmd;
+       channel->ccw.cda = (__u32) __pa (rcd_buf);
+       channel->ccw.count = ciw->count;
+       channel->ccw.flags = CCW_FLAG_SLI;
+       channel->state = CH_STATE_RCD;
+       spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
+       ret = ccw_device_start_timeout(channel->ccwdev, &channel->ccw,
+                                      QETH_RCD_PARM, LPM_ANYPATH, 0,
+                                      QETH_RCD_TIMEOUT);
+       spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
+       if (!ret)
+               wait_event(card->wait_q,
+                          (channel->state == CH_STATE_RCD_DONE ||
+                           channel->state == CH_STATE_DOWN));
+       if (channel->state == CH_STATE_DOWN)
+               ret = -EIO;
+       else
+               channel->state = CH_STATE_DOWN;
+       if (ret) {
+               kfree(rcd_buf);
+               *buffer = NULL;
+               *length = 0;
+       } else {
+               *length = ciw->count;
+               *buffer = rcd_buf;
+       }
+       return ret;
+}
+
 static int
 qeth_get_unitaddr(struct qeth_card *card)
 {
@@ -1212,9 +1278,9 @@ qeth_get_unitaddr(struct qeth_card *card)
        int rc;
 
        QETH_DBF_TEXT(setup, 2, "getunit");
-       rc = read_conf_data(CARD_DDEV(card), (void **) &prcd, &length);
+       rc = qeth_read_conf_data(card, (void **) &prcd, &length);
        if (rc) {
-               PRINT_ERR("read_conf_data for device %s returned %i\n",
+               PRINT_ERR("qeth_read_conf_data for device %s returned %i\n",
                          CARD_DDEV_ID(card), rc);
                return rc;
        }
@@ -1223,6 +1289,7 @@ qeth_get_unitaddr(struct qeth_card *card)
        card->info.cula = prcd[63];
        card->info.guestlan = ((prcd[0x10] == _ascebc['V']) &&
                               (prcd[0x11] == _ascebc['M']));
+       kfree(prcd);
        return 0;
 }
 
index 0477c47..d74bc43 100644 (file)
@@ -37,6 +37,7 @@ extern unsigned char IPA_PDU_HEADER[];
 
 #define QETH_CLEAR_CHANNEL_PARM        -10
 #define QETH_HALT_CHANNEL_PARM -11
+#define QETH_RCD_PARM -12
 
 /*****************************************************************************/
 /* IP Assist related definitions                                             */
index 421da1e..c1f2d4b 100644 (file)
@@ -186,7 +186,7 @@ void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout)
 {
        fsf_req->timer.function = zfcp_fsf_request_timeout_handler;
        fsf_req->timer.data = (unsigned long) fsf_req->adapter;
-       fsf_req->timer.expires = timeout;
+       fsf_req->timer.expires = jiffies + timeout;
        add_timer(&fsf_req->timer);
 }
 
index ef16f7c..4c0a59a 100644 (file)
@@ -299,9 +299,10 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
        }
 
        /* log additional information provided by FSF (if any) */
-       if (unlikely(qtcb->header.log_length)) {
+       if (likely(qtcb->header.log_length)) {
                /* do not trust them ;-) */
-               if (qtcb->header.log_start > sizeof(struct fsf_qtcb)) {
+               if (unlikely(qtcb->header.log_start >
+                            sizeof(struct fsf_qtcb))) {
                        ZFCP_LOG_NORMAL
                            ("bug: ULP (FSF logging) log data starts "
                             "beyond end of packet header. Ignored. "
@@ -310,8 +311,9 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
                             sizeof(struct fsf_qtcb));
                        goto forget_log;
                }
-               if ((size_t) (qtcb->header.log_start + qtcb->header.log_length)
-                   > sizeof(struct fsf_qtcb)) {
+               if (unlikely((size_t) (qtcb->header.log_start +
+                                      qtcb->header.log_length) >
+                            sizeof(struct fsf_qtcb))) {
                        ZFCP_LOG_NORMAL("bug: ULP (FSF logging) log data ends "
                                        "beyond end of packet header. Ignored. "
                                        "(start=%i, length=%i, size=%li)\n",
index eee590a..0026433 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <linux/device.h>
 
 #include <asm/system.h>
index e874b89..96f4cab 100644 (file)
@@ -579,17 +579,17 @@ static void __init BusLogic_InitializeProbeInfoListISA(struct BusLogic_HostAdapt
        /*
           Append the list of standard BusLogic MultiMaster ISA I/O Addresses.
         */
-       if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe330 : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0)
+       if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe330)
                BusLogic_AppendProbeAddressISA(0x330);
-       if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe334 : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0)
+       if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe334)
                BusLogic_AppendProbeAddressISA(0x334);
-       if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe230 : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0)
+       if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe230)
                BusLogic_AppendProbeAddressISA(0x230);
-       if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe234 : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0)
+       if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe234)
                BusLogic_AppendProbeAddressISA(0x234);
-       if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe130 : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0)
+       if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe130)
                BusLogic_AppendProbeAddressISA(0x130);
-       if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe134 : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0)
+       if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe134)
                BusLogic_AppendProbeAddressISA(0x134);
 }
 
@@ -795,7 +795,9 @@ static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAd
           host adapters are probed.
         */
        if (!BusLogic_ProbeOptions.NoProbeISA)
-               if (PrimaryProbeInfo->IO_Address == 0 && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe330 : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0)) {
+               if (PrimaryProbeInfo->IO_Address == 0 &&
+                               (!BusLogic_ProbeOptions.LimitedProbeISA ||
+                                BusLogic_ProbeOptions.Probe330)) {
                        PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
                        PrimaryProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
                        PrimaryProbeInfo->IO_Address = 0x330;
@@ -805,15 +807,25 @@ static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAd
           omitting the Primary I/O Address which has already been handled.
         */
        if (!BusLogic_ProbeOptions.NoProbeISA) {
-               if (!StandardAddressSeen[1] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe334 : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0))
+               if (!StandardAddressSeen[1] &&
+                               (!BusLogic_ProbeOptions.LimitedProbeISA ||
+                                BusLogic_ProbeOptions.Probe334))
                        BusLogic_AppendProbeAddressISA(0x334);
-               if (!StandardAddressSeen[2] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe230 : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0))
+               if (!StandardAddressSeen[2] &&
+                               (!BusLogic_ProbeOptions.LimitedProbeISA ||
+                                BusLogic_ProbeOptions.Probe230))
                        BusLogic_AppendProbeAddressISA(0x230);
-               if (!StandardAddressSeen[3] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe234 : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0))
+               if (!StandardAddressSeen[3] &&
+                               (!BusLogic_ProbeOptions.LimitedProbeISA ||
+                                BusLogic_ProbeOptions.Probe234))
                        BusLogic_AppendProbeAddressISA(0x234);
-               if (!StandardAddressSeen[4] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe130 : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0))
+               if (!StandardAddressSeen[4] &&
+                               (!BusLogic_ProbeOptions.LimitedProbeISA ||
+                                BusLogic_ProbeOptions.Probe130))
                        BusLogic_AppendProbeAddressISA(0x130);
-               if (!StandardAddressSeen[5] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe134 : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0))
+               if (!StandardAddressSeen[5] &&
+                               (!BusLogic_ProbeOptions.LimitedProbeISA ||
+                                BusLogic_ProbeOptions.Probe134))
                        BusLogic_AppendProbeAddressISA(0x134);
        }
        /*
@@ -2220,22 +2232,35 @@ static int __init BusLogic_init(void)
                HostAdapter->PCI_Device = ProbeInfo->PCI_Device;
                HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel;
                HostAdapter->AddressCount = BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType];
+
+               /*
+                  Make sure region is free prior to probing.
+                */
+               if (!request_region(HostAdapter->IO_Address, HostAdapter->AddressCount,
+                                       "BusLogic"))
+                       continue;
                /*
                   Probe the Host Adapter.  If unsuccessful, abort further initialization.
                 */
-               if (!BusLogic_ProbeHostAdapter(HostAdapter))
+               if (!BusLogic_ProbeHostAdapter(HostAdapter)) {
+                       release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
                        continue;
+               }
                /*
                   Hard Reset the Host Adapter.  If unsuccessful, abort further
                   initialization.
                 */
-               if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true))
+               if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true)) {
+                       release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
                        continue;
+               }
                /*
                   Check the Host Adapter.  If unsuccessful, abort further initialization.
                 */
-               if (!BusLogic_CheckHostAdapter(HostAdapter))
+               if (!BusLogic_CheckHostAdapter(HostAdapter)) {
+                       release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
                        continue;
+               }
                /*
                   Initialize the Driver Options field if provided.
                 */
@@ -2247,16 +2272,6 @@ static int __init BusLogic_init(void)
                 */
                BusLogic_AnnounceDriver(HostAdapter);
                /*
-                  Register usage of the I/O Address range.  From this point onward, any
-                  failure will be assumed to be due to a problem with the Host Adapter,
-                  rather than due to having mistakenly identified this port as belonging
-                  to a BusLogic Host Adapter.  The I/O Address range will not be
-                  released, thereby preventing it from being incorrectly identified as
-                  any other type of Host Adapter.
-                */
-               if (!request_region(HostAdapter->IO_Address, HostAdapter->AddressCount, "BusLogic"))
-                       continue;
-               /*
                   Register the SCSI Host structure.
                 */
 
@@ -2280,6 +2295,12 @@ static int __init BusLogic_init(void)
                   Acquire the System Resources necessary to use the Host Adapter, then
                   Create the Initial CCBs, Initialize the Host Adapter, and finally
                   perform Target Device Inquiry.
+
+                  From this point onward, any failure will be assumed to be due to a
+                  problem with the Host Adapter, rather than due to having mistakenly
+                  identified this port as belonging to a BusLogic Host Adapter.  The
+                  I/O Address range will not be released, thereby preventing it from
+                  being incorrectly identified as any other type of Host Adapter.
                 */
                if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) &&
                    BusLogic_ReportHostAdapterConfiguration(HostAdapter) &&
@@ -3598,6 +3619,7 @@ static void __exit BusLogic_exit(void)
 
 __setup("BusLogic=", BusLogic_Setup);
 
+#ifdef MODULE
 static struct pci_device_id BusLogic_pci_tbl[] __devinitdata = {
        { PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
@@ -3607,6 +3629,7 @@ static struct pci_device_id BusLogic_pci_tbl[] __devinitdata = {
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        { }
 };
+#endif
 MODULE_DEVICE_TABLE(pci, BusLogic_pci_tbl);
 
 module_init(BusLogic_init);
index fcc4cb6..58c811d 100644 (file)
@@ -241,6 +241,12 @@ config SCSI_SCAN_ASYNC
          You can override this choice by specifying "scsi_mod.scan=sync"
          or async on the kernel's command line.
 
+config SCSI_WAIT_SCAN
+       tristate
+       default m
+       depends on SCSI
+       depends on MODULES
+
 menu "SCSI Transports"
        depends on SCSI
 
@@ -1194,17 +1200,6 @@ config SCSI_NCR53C8XX_SYNC
          There is no safe option other than using good cabling, right
          terminations and SCSI conformant devices.
 
-config SCSI_NCR53C8XX_PROFILE
-       bool "enable profiling"
-       depends on SCSI_ZALON || SCSI_NCR_Q720
-       help
-         This option allows you to enable profiling information gathering.
-         These statistics are not very accurate due to the low frequency
-         of the kernel clock (100 Hz on i386) and have performance impact
-         on systems that use very fast devices.
-
-         The normal answer therefore is N.
-
 config SCSI_NCR53C8XX_NO_DISCONNECT
        bool "not allow targets to disconnect"
        depends on (SCSI_ZALON || SCSI_NCR_Q720) && SCSI_NCR53C8XX_DEFAULT_TAGS=0
@@ -1334,11 +1329,6 @@ config SCSI_SIM710
 
          It currently supports Compaq EISA cards and NCR MCA cards
 
-config 53C700_IO_MAPPED
-       bool
-       depends on SCSI_SIM710
-       default y
-
 config SCSI_SYM53C416
        tristate "Symbios 53c416 SCSI support"
        depends on ISA && SCSI
@@ -1649,7 +1639,7 @@ config OKTAGON_SCSI
 
 config ATARI_SCSI
        tristate "Atari native SCSI support"
-       depends on ATARI && SCSI && BROKEN
+       depends on ATARI && SCSI
        select SCSI_SPI_ATTRS
        ---help---
          If you have an Atari with built-in NCR5380 SCSI controller (TT,
index 70cff4c..51e884f 100644 (file)
@@ -146,7 +146,7 @@ obj-$(CONFIG_CHR_DEV_SCH)   += ch.o
 # This goes last, so that "real" scsi devices probe earlier
 obj-$(CONFIG_SCSI_DEBUG)       += scsi_debug.o
 
-obj-$(CONFIG_SCSI)             += scsi_wait_scan.o
+obj-$(CONFIG_SCSI_WAIT_SCAN)   += scsi_wait_scan.o
 
 scsi_mod-y                     += scsi.o hosts.o scsi_ioctl.o constants.o \
                                   scsicam.o scsi_error.o scsi_lib.o \
index d789e61..1e82c69 100644 (file)
@@ -5,7 +5,7 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -172,6 +172,30 @@ MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size.
 int expose_physicals = -1;
 module_param(expose_physicals, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. -1=protect 0=off, 1=on");
+
+
+static inline int aac_valid_context(struct scsi_cmnd *scsicmd,
+               struct fib *fibptr) {
+       struct scsi_device *device;
+
+       if (unlikely(!scsicmd || !scsicmd->scsi_done )) {
+               dprintk((KERN_WARNING "aac_valid_context: scsi command corrupt\n"))
+;
+                aac_fib_complete(fibptr);
+                aac_fib_free(fibptr);
+                return 0;
+        }
+       scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
+       device = scsicmd->device;
+       if (unlikely(!device || !scsi_device_online(device))) {
+               dprintk((KERN_WARNING "aac_valid_context: scsi device corrupt\n"));
+               aac_fib_complete(fibptr);
+               aac_fib_free(fibptr);
+               return 0;
+       }
+       return 1;
+}
+
 /**
  *     aac_get_config_status   -       check the adapter configuration
  *     @common: adapter to query
@@ -258,13 +282,10 @@ int aac_get_containers(struct aac_dev *dev)
        u32 index; 
        int status = 0;
        struct fib * fibptr;
-       unsigned instance;
        struct aac_get_container_count *dinfo;
        struct aac_get_container_count_resp *dresp;
        int maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
 
-       instance = dev->scsi_host_ptr->unique_id;
-
        if (!(fibptr = aac_fib_alloc(dev)))
                return -ENOMEM;
 
@@ -284,88 +305,35 @@ int aac_get_containers(struct aac_dev *dev)
                maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries);
                aac_fib_complete(fibptr);
        }
+       aac_fib_free(fibptr);
 
        if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)
                maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
-       fsa_dev_ptr = kmalloc(
-         sizeof(*fsa_dev_ptr) * maximum_num_containers, GFP_KERNEL);
-       if (!fsa_dev_ptr) {
-               aac_fib_free(fibptr);
+       fsa_dev_ptr =  kmalloc(sizeof(*fsa_dev_ptr) * maximum_num_containers,
+                       GFP_KERNEL);
+       if (!fsa_dev_ptr)
                return -ENOMEM;
-       }
        memset(fsa_dev_ptr, 0, sizeof(*fsa_dev_ptr) * maximum_num_containers);
 
        dev->fsa_dev = fsa_dev_ptr;
        dev->maximum_num_containers = maximum_num_containers;
 
-       for (index = 0; index < dev->maximum_num_containers; index++) {
-               struct aac_query_mount *dinfo;
-               struct aac_mount *dresp;
-
+       for (index = 0; index < dev->maximum_num_containers; ) {
                fsa_dev_ptr[index].devname[0] = '\0';
 
-               aac_fib_init(fibptr);
-               dinfo = (struct aac_query_mount *) fib_data(fibptr);
-
-               dinfo->command = cpu_to_le32(VM_NameServe);
-               dinfo->count = cpu_to_le32(index);
-               dinfo->type = cpu_to_le32(FT_FILESYS);
+               status = aac_probe_container(dev, index);
 
-               status = aac_fib_send(ContainerCommand,
-                                   fibptr,
-                                   sizeof (struct aac_query_mount),
-                                   FsaNormal,
-                                   1, 1,
-                                   NULL, NULL);
-               if (status < 0 ) {
+               if (status < 0) {
                        printk(KERN_WARNING "aac_get_containers: SendFIB failed.\n");
                        break;
                }
-               dresp = (struct aac_mount *)fib_data(fibptr);
 
-               if ((le32_to_cpu(dresp->status) == ST_OK) &&
-                   (le32_to_cpu(dresp->mnt[0].vol) == CT_NONE)) {
-                       dinfo->command = cpu_to_le32(VM_NameServe64);
-                       dinfo->count = cpu_to_le32(index);
-                       dinfo->type = cpu_to_le32(FT_FILESYS);
-
-                       if (aac_fib_send(ContainerCommand,
-                                   fibptr,
-                                   sizeof(struct aac_query_mount),
-                                   FsaNormal,
-                                   1, 1,
-                                   NULL, NULL) < 0)
-                               continue;
-               } else
-                       dresp->mnt[0].capacityhigh = 0;
-
-               dprintk ((KERN_DEBUG
-                 "VM_NameServe cid=%d status=%d vol=%d state=%d cap=%llu\n",
-                 (int)index, (int)le32_to_cpu(dresp->status),
-                 (int)le32_to_cpu(dresp->mnt[0].vol),
-                 (int)le32_to_cpu(dresp->mnt[0].state),
-                 ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
-                   (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32)));
-               if ((le32_to_cpu(dresp->status) == ST_OK) &&
-                   (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&
-                   (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) {
-                       fsa_dev_ptr[index].valid = 1;
-                       fsa_dev_ptr[index].type = le32_to_cpu(dresp->mnt[0].vol);
-                       fsa_dev_ptr[index].size
-                         = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
-                           (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32);
-                       if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)
-                                   fsa_dev_ptr[index].ro = 1;
-               }
-               aac_fib_complete(fibptr);
                /*
                 *      If there are no more containers, then stop asking.
                 */
-               if ((index + 1) >= le32_to_cpu(dresp->count)){
+               if (++index >= status)
                        break;
-               }
        }
-       aac_fib_free(fibptr);
        return status;
 }
 
@@ -382,8 +350,9 @@ static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigne
                buf = scsicmd->request_buffer;
                transfer_len = min(scsicmd->request_bufflen, len + offset);
        }
-
-       memcpy(buf + offset, data, transfer_len - offset);
+       transfer_len -= offset;
+       if (buf && transfer_len)
+               memcpy(buf + offset, data, transfer_len);
 
        if (scsicmd->use_sg) 
                kunmap_atomic(buf - sg->offset, KM_IRQ0);
@@ -396,7 +365,9 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
        struct scsi_cmnd * scsicmd;
 
        scsicmd = (struct scsi_cmnd *) context;
-       scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
+
+       if (!aac_valid_context(scsicmd, fibptr))
+               return;
 
        dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies));
        BUG_ON(fibptr == NULL);
@@ -431,7 +402,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
 /**
  *     aac_get_container_name  -       get container name, none blocking.
  */
-static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
+static int aac_get_container_name(struct scsi_cmnd * scsicmd)
 {
        int status;
        struct aac_get_name *dinfo;
@@ -448,7 +419,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
 
        dinfo->command = cpu_to_le32(VM_ContainerConfig);
        dinfo->type = cpu_to_le32(CT_READ_NAME);
-       dinfo->cid = cpu_to_le32(cid);
+       dinfo->cid = cpu_to_le32(scmd_id(scsicmd));
        dinfo->count = cpu_to_le32(sizeof(((struct aac_get_name_resp *)NULL)->data));
 
        status = aac_fib_send(ContainerCommand,
@@ -473,85 +444,192 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
        return -1;
 }
 
-/**
- *     aac_probe_container             -       query a logical volume
- *     @dev: device to query
- *     @cid: container identifier
- *
- *     Queries the controller about the given volume. The volume information
- *     is updated in the struct fsa_dev_info structure rather than returned.
- */
-int aac_probe_container(struct aac_dev *dev, int cid)
+static int aac_probe_container_callback2(struct scsi_cmnd * scsicmd)
+{
+       struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
+
+       if (fsa_dev_ptr[scmd_id(scsicmd)].valid)
+               return aac_scsi_cmd(scsicmd);
+
+       scsicmd->result = DID_NO_CONNECT << 16;
+       scsicmd->scsi_done(scsicmd);
+       return 0;
+}
+
+static int _aac_probe_container2(void * context, struct fib * fibptr)
 {
        struct fsa_dev_info *fsa_dev_ptr;
-       int status;
+       int (*callback)(struct scsi_cmnd *);
+       struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context;
+
+       if (!aac_valid_context(scsicmd, fibptr))
+               return 0;
+
+       fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
+
+       scsicmd->SCp.Status = 0;
+       if (fsa_dev_ptr) {
+               struct aac_mount * dresp = (struct aac_mount *) fib_data(fibptr);
+               fsa_dev_ptr += scmd_id(scsicmd);
+
+               if ((le32_to_cpu(dresp->status) == ST_OK) &&
+                   (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&
+                   (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) {
+                       fsa_dev_ptr->valid = 1;
+                       fsa_dev_ptr->type = le32_to_cpu(dresp->mnt[0].vol);
+                       fsa_dev_ptr->size
+                         = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
+                           (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32);
+                       fsa_dev_ptr->ro = ((le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) != 0);
+               }
+               if ((fsa_dev_ptr->valid & 1) == 0)
+                       fsa_dev_ptr->valid = 0;
+               scsicmd->SCp.Status = le32_to_cpu(dresp->count);
+       }
+       aac_fib_complete(fibptr);
+       aac_fib_free(fibptr);
+       callback = (int (*)(struct scsi_cmnd *))(scsicmd->SCp.ptr);
+       scsicmd->SCp.ptr = NULL;
+       return (*callback)(scsicmd);
+}
+
+static int _aac_probe_container1(void * context, struct fib * fibptr)
+{
+       struct scsi_cmnd * scsicmd;
+       struct aac_mount * dresp;
        struct aac_query_mount *dinfo;
-       struct aac_mount *dresp;
-       struct fib * fibptr;
-       unsigned instance;
+       int status;
 
-       fsa_dev_ptr = dev->fsa_dev;
-       if (!fsa_dev_ptr)
-               return -ENOMEM;
-       instance = dev->scsi_host_ptr->unique_id;
+       dresp = (struct aac_mount *) fib_data(fibptr);
+       dresp->mnt[0].capacityhigh = 0;
+       if ((le32_to_cpu(dresp->status) != ST_OK) ||
+           (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE))
+               return _aac_probe_container2(context, fibptr);
+       scsicmd = (struct scsi_cmnd *) context;
+       scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
 
-       if (!(fibptr = aac_fib_alloc(dev)))
-               return -ENOMEM;
+       if (!aac_valid_context(scsicmd, fibptr))
+               return 0;
 
        aac_fib_init(fibptr);
 
        dinfo = (struct aac_query_mount *)fib_data(fibptr);
 
-       dinfo->command = cpu_to_le32(VM_NameServe);
-       dinfo->count = cpu_to_le32(cid);
+       dinfo->command = cpu_to_le32(VM_NameServe64);
+       dinfo->count = cpu_to_le32(scmd_id(scsicmd));
        dinfo->type = cpu_to_le32(FT_FILESYS);
 
        status = aac_fib_send(ContainerCommand,
-                           fibptr,
-                           sizeof(struct aac_query_mount),
-                           FsaNormal,
-                           1, 1,
-                           NULL, NULL);
+                         fibptr,
+                         sizeof(struct aac_query_mount),
+                         FsaNormal,
+                         0, 1,
+                         (fib_callback) _aac_probe_container2,
+                         (void *) scsicmd);
+       /*
+        *      Check that the command queued to the controller
+        */
+       if (status == -EINPROGRESS) {
+               scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
+               return 0;
+       }
        if (status < 0) {
-               printk(KERN_WARNING "aacraid: aac_probe_container query failed.\n");
-               goto error;
+               /* Inherit results from VM_NameServe, if any */
+               dresp->status = cpu_to_le32(ST_OK);
+               return _aac_probe_container2(context, fibptr);
        }
+       return 0;
+}
 
-       dresp = (struct aac_mount *) fib_data(fibptr);
+static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(struct scsi_cmnd *))
+{
+       struct fib * fibptr;
+       int status = -ENOMEM;
 
-       if ((le32_to_cpu(dresp->status) == ST_OK) &&
-           (le32_to_cpu(dresp->mnt[0].vol) == CT_NONE)) {
-               dinfo->command = cpu_to_le32(VM_NameServe64);
-               dinfo->count = cpu_to_le32(cid);
-               dinfo->type = cpu_to_le32(FT_FILESYS);
+       if ((fibptr = aac_fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) {
+               struct aac_query_mount *dinfo;
 
-               if (aac_fib_send(ContainerCommand,
-                           fibptr,
-                           sizeof(struct aac_query_mount),
-                           FsaNormal,
-                           1, 1,
-                           NULL, NULL) < 0)
-                       goto error;
-       } else
-               dresp->mnt[0].capacityhigh = 0;
+               aac_fib_init(fibptr);
+
+               dinfo = (struct aac_query_mount *)fib_data(fibptr);
+
+               dinfo->command = cpu_to_le32(VM_NameServe);
+               dinfo->count = cpu_to_le32(scmd_id(scsicmd));
+               dinfo->type = cpu_to_le32(FT_FILESYS);
+               scsicmd->SCp.ptr = (char *)callback;
 
-       if ((le32_to_cpu(dresp->status) == ST_OK) &&
-           (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&
-           (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) {
-               fsa_dev_ptr[cid].valid = 1;
-               fsa_dev_ptr[cid].type = le32_to_cpu(dresp->mnt[0].vol);
-               fsa_dev_ptr[cid].size
-                 = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
-                   (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32);
-               if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)
-                       fsa_dev_ptr[cid].ro = 1;
+               status = aac_fib_send(ContainerCommand,
+                         fibptr,
+                         sizeof(struct aac_query_mount),
+                         FsaNormal,
+                         0, 1,
+                         (fib_callback) _aac_probe_container1,
+                         (void *) scsicmd);
+               /*
+                *      Check that the command queued to the controller
+                */
+               if (status == -EINPROGRESS) {
+                       scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
+                       return 0;
+               }
+               if (status < 0) {
+                       scsicmd->SCp.ptr = NULL;
+                       aac_fib_complete(fibptr);
+                       aac_fib_free(fibptr);
+               }
        }
+       if (status < 0) {
+               struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
+               if (fsa_dev_ptr) {
+                       fsa_dev_ptr += scmd_id(scsicmd);
+                       if ((fsa_dev_ptr->valid & 1) == 0) {
+                               fsa_dev_ptr->valid = 0;
+                               return (*callback)(scsicmd);
+                       }
+               }
+       }
+       return status;
+}
 
-error:
-       aac_fib_complete(fibptr);
-       aac_fib_free(fibptr);
+/**
+ *     aac_probe_container             -       query a logical volume
+ *     @dev: device to query
+ *     @cid: container identifier
+ *
+ *     Queries the controller about the given volume. The volume information
+ *     is updated in the struct fsa_dev_info structure rather than returned.
+ */
+static int aac_probe_container_callback1(struct scsi_cmnd * scsicmd)
+{
+       scsicmd->device = NULL;
+       return 0;
+}
+
+int aac_probe_container(struct aac_dev *dev, int cid)
+{
+       struct scsi_cmnd *scsicmd = kmalloc(sizeof(*scsicmd), GFP_KERNEL);
+       struct scsi_device *scsidev = kmalloc(sizeof(*scsidev), GFP_KERNEL);
+       int status;
 
+       if (!scsicmd || !scsidev) {
+               kfree(scsicmd);
+               kfree(scsidev);
+               return -ENOMEM;
+       }
+       scsicmd->list.next = NULL;
+       scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))_aac_probe_container1;
+
+       scsicmd->device = scsidev;
+       scsidev->sdev_state = 0;
+       scsidev->id = cid;
+       scsidev->host = dev->scsi_host_ptr;
+
+       if (_aac_probe_container(scsicmd, aac_probe_container_callback1) == 0)
+               while (scsicmd->device == scsidev)
+                       schedule();
+       kfree(scsidev);
+       status = scsicmd->SCp.Status;
+       kfree(scsicmd);
        return status;
 }
 
@@ -1115,6 +1193,12 @@ int aac_get_adapter_info(struct aac_dev* dev)
                        printk(KERN_INFO "%s%d: serial %x\n",
                                dev->name, dev->id,
                                le32_to_cpu(dev->adapter_info.serial[0]));
+               if (dev->supplement_adapter_info.VpdInfo.Tsid[0]) {
+                       printk(KERN_INFO "%s%d: TSID %.*s\n",
+                         dev->name, dev->id,
+                         (int)sizeof(dev->supplement_adapter_info.VpdInfo.Tsid),
+                         dev->supplement_adapter_info.VpdInfo.Tsid);
+               }
        }
 
        dev->nondasd_support = 0;
@@ -1241,7 +1325,9 @@ static void io_callback(void *context, struct fib * fibptr)
        u32 cid;
 
        scsicmd = (struct scsi_cmnd *) context;
-       scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
+
+       if (!aac_valid_context(scsicmd, fibptr))
+               return;
 
        dev = (struct aac_dev *)scsicmd->device->host->hostdata;
        cid = scmd_id(scsicmd);
@@ -1317,7 +1403,7 @@ static void io_callback(void *context, struct fib * fibptr)
        scsicmd->scsi_done(scsicmd);
 }
 
-static int aac_read(struct scsi_cmnd * scsicmd, int cid)
+static int aac_read(struct scsi_cmnd * scsicmd)
 {
        u64 lba;
        u32 count;
@@ -1331,7 +1417,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
         */
        switch (scsicmd->cmnd[0]) {
        case READ_6:
-               dprintk((KERN_DEBUG "aachba: received a read(6) command on id %d.\n", cid));
+               dprintk((KERN_DEBUG "aachba: received a read(6) command on id %d.\n", scmd_id(scsicmd)));
 
                lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | 
                        (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
@@ -1341,7 +1427,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
                        count = 256;
                break;
        case READ_16:
-               dprintk((KERN_DEBUG "aachba: received a read(16) command on id %d.\n", cid));
+               dprintk((KERN_DEBUG "aachba: received a read(16) command on id %d.\n", scmd_id(scsicmd)));
 
                lba =   ((u64)scsicmd->cmnd[2] << 56) |
                        ((u64)scsicmd->cmnd[3] << 48) |
@@ -1355,7 +1441,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
                        (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13];
                break;
        case READ_12:
-               dprintk((KERN_DEBUG "aachba: received a read(12) command on id %d.\n", cid));
+               dprintk((KERN_DEBUG "aachba: received a read(12) command on id %d.\n", scmd_id(scsicmd)));
 
                lba = ((u64)scsicmd->cmnd[2] << 24) | 
                        (scsicmd->cmnd[3] << 16) |
@@ -1365,7 +1451,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
                        (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
                break;
        default:
-               dprintk((KERN_DEBUG "aachba: received a read(10) command on id %d.\n", cid));
+               dprintk((KERN_DEBUG "aachba: received a read(10) command on id %d.\n", scmd_id(scsicmd)));
 
                lba = ((u64)scsicmd->cmnd[2] << 24) | 
                        (scsicmd->cmnd[3] << 16) | 
@@ -1405,7 +1491,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
        return 0;
 }
 
-static int aac_write(struct scsi_cmnd * scsicmd, int cid)
+static int aac_write(struct scsi_cmnd * scsicmd)
 {
        u64 lba;
        u32 count;
@@ -1424,7 +1510,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
                if (count == 0)
                        count = 256;
        } else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */
-               dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", cid));
+               dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", scmd_id(scsicmd)));
 
                lba =   ((u64)scsicmd->cmnd[2] << 56) |
                        ((u64)scsicmd->cmnd[3] << 48) |
@@ -1436,14 +1522,14 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
                count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) |
                        (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13];
        } else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */
-               dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", cid));
+               dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", scmd_id(scsicmd)));
 
                lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16)
                    | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
                count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16)
                      | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
        } else {
-               dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", cid));
+               dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", scmd_id(scsicmd)));
                lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
                count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
        }
@@ -1488,7 +1574,9 @@ static void synchronize_callback(void *context, struct fib *fibptr)
        struct scsi_cmnd *cmd;
 
        cmd = context;
-       cmd->SCp.phase = AAC_OWNER_MIDLEVEL;
+
+       if (!aac_valid_context(cmd, fibptr))
+               return;
 
        dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n", 
                                smp_processor_id(), jiffies));
@@ -1523,7 +1611,7 @@ static void synchronize_callback(void *context, struct fib *fibptr)
        cmd->scsi_done(cmd);
 }
 
-static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
+static int aac_synchronize(struct scsi_cmnd *scsicmd)
 {
        int status;
        struct fib *cmd_fibcontext;
@@ -1568,7 +1656,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
        synchronizecmd = fib_data(cmd_fibcontext);
        synchronizecmd->command = cpu_to_le32(VM_ContainerConfig);
        synchronizecmd->type = cpu_to_le32(CT_FLUSH_CACHE);
-       synchronizecmd->cid = cpu_to_le32(cid);
+       synchronizecmd->cid = cpu_to_le32(scmd_id(scsicmd));
        synchronizecmd->count = 
             cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data));
 
@@ -1646,29 +1734,12 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                                case TEST_UNIT_READY:
                                        if (dev->in_reset)
                                                return -1;
-                                       spin_unlock_irq(host->host_lock);
-                                       aac_probe_container(dev, cid);
-                                       if ((fsa_dev_ptr[cid].valid & 1) == 0)
-                                               fsa_dev_ptr[cid].valid = 0;
-                                       spin_lock_irq(host->host_lock);
-                                       if (fsa_dev_ptr[cid].valid == 0) {
-                                               scsicmd->result = DID_NO_CONNECT << 16;
-                                               scsicmd->scsi_done(scsicmd);
-                                               return 0;
-                                       }
+                                       return _aac_probe_container(scsicmd,
+                                                       aac_probe_container_callback2);
                                default:
                                        break;
                                }
                        }
-                       /*
-                        *      If the target container still doesn't exist, 
-                        *      return failure
-                        */
-                       if (fsa_dev_ptr[cid].valid == 0) {
-                               scsicmd->result = DID_BAD_TARGET << 16;
-                               scsicmd->scsi_done(scsicmd);
-                               return 0;
-                       }
                } else {  /* check for physical non-dasd devices */
                        if ((dev->nondasd_support == 1) || expose_physicals) {
                                if (dev->in_reset)
@@ -1733,7 +1804,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type);
                inq_data.inqd_pdt = INQD_PDT_DA;        /* Direct/random access device */
                aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
-               return aac_get_container_name(scsicmd, cid);
+               return aac_get_container_name(scsicmd);
        }
        case SERVICE_ACTION_IN:
                if (!(dev->raw_io_interface) ||
@@ -1899,7 +1970,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                                min(sizeof(fsa_dev_ptr[cid].devname),
                                sizeof(scsicmd->request->rq_disk->disk_name) + 1));
 
-                       return aac_read(scsicmd, cid);
+                       return aac_read(scsicmd);
 
                case WRITE_6:
                case WRITE_10:
@@ -1907,11 +1978,11 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                case WRITE_16:
                        if (dev->in_reset)
                                return -1;
-                       return aac_write(scsicmd, cid);
+                       return aac_write(scsicmd);
 
                case SYNCHRONIZE_CACHE:
                        /* Issue FIB to tell Firmware to flush it's cache */
-                       return aac_synchronize(scsicmd, cid);
+                       return aac_synchronize(scsicmd);
                        
                default:
                        /*
@@ -2058,7 +2129,10 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
        struct scsi_cmnd *scsicmd;
 
        scsicmd = (struct scsi_cmnd *) context;
-       scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
+
+       if (!aac_valid_context(scsicmd, fibptr))
+               return;
+
        dev = (struct aac_dev *)scsicmd->device->host->hostdata;
 
        BUG_ON(fibptr == NULL);
index 39ecd0d..45ca3e8 100644 (file)
@@ -12,8 +12,8 @@
  *----------------------------------------------------------------------------*/
 
 #ifndef AAC_DRIVER_BUILD
-# define AAC_DRIVER_BUILD 2423
-# define AAC_DRIVER_BRANCH "-mh3"
+# define AAC_DRIVER_BUILD 2437
+# define AAC_DRIVER_BRANCH "-mh4"
 #endif
 #define MAXIMUM_NUM_CONTAINERS 32
 
@@ -48,49 +48,13 @@ struct diskparm
 
 
 /*
- *     DON'T CHANGE THE ORDER, this is set by the firmware
+ *     Firmware constants
  */
  
 #define                CT_NONE                 0
-#define                CT_VOLUME               1
-#define                CT_MIRROR               2
-#define                CT_STRIPE               3
-#define                CT_RAID5                4
-#define                CT_SSRW                 5
-#define                CT_SSRO                 6
-#define                CT_MORPH                7
-#define                CT_PASSTHRU             8
-#define                CT_RAID4                9
-#define                CT_RAID10               10      /* stripe of mirror */
-#define                CT_RAID00               11      /* stripe of stripe */
-#define                CT_VOLUME_OF_MIRRORS    12      /* volume of mirror */
-#define                CT_PSEUDO_RAID          13      /* really raid4 */
-#define                CT_LAST_VOLUME_TYPE     14
 #define        CT_OK                   218
-
-/*
- *     Types of objects addressable in some fashion by the client.
- *     This is a superset of those objects handled just by the filesystem
- *     and includes "raw" objects that an administrator would use to
- *     configure containers and filesystems.
- */
-
-#define                FT_REG          1       /* regular file */
-#define                FT_DIR          2       /* directory */
-#define                FT_BLK          3       /* "block" device - reserved */
-#define                FT_CHR          4       /* "character special" device - reserved */
-#define                FT_LNK          5       /* symbolic link */
-#define                FT_SOCK         6       /* socket */
-#define                FT_FIFO         7       /* fifo */
 #define                FT_FILESYS      8       /* ADAPTEC's "FSA"(tm) filesystem */
 #define                FT_DRIVE        9       /* physical disk - addressable in scsi by bus/id/lun */
-#define                FT_SLICE        10      /* virtual disk - raw volume - slice */
-#define                FT_PARTITION    11      /* FSA partition - carved out of a slice - building block for containers */
-#define                FT_VOLUME       12      /* Container - Volume Set */
-#define                FT_STRIPE       13      /* Container - Stripe Set */
-#define                FT_MIRROR       14      /* Container - Mirror Set */
-#define                FT_RAID5        15      /* Container - Raid 5 Set */
-#define                FT_DATABASE     16      /* Storage object with "foreign" content manager */
 
 /*
  *     Host side memory scatter gather list
@@ -497,6 +461,7 @@ struct adapter_ops
        void (*adapter_enable_int)(struct aac_dev *dev);
        int  (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
        int  (*adapter_check_health)(struct aac_dev *dev);
+       int  (*adapter_restart)(struct aac_dev *dev, int bled);
        /* Transport operations */
        int  (*adapter_ioremap)(struct aac_dev * dev, u32 size);
        irqreturn_t (*adapter_intr)(int irq, void *dev_id);
@@ -833,7 +798,7 @@ struct fib {
         */
        struct list_head        fiblink;
        void                    *data;
-       struct hw_fib           *hw_fib;                /* Actual shared object */
+       struct hw_fib           *hw_fib_va;             /* Actual shared object */
        dma_addr_t              hw_fib_pa;              /* physical address of hw_fib*/
 };
 
@@ -878,10 +843,25 @@ struct aac_supplement_adapter_info
        __le32  Version;
        __le32  FeatureBits;
        u8      SlotNumber;
-       u8      ReservedPad0[0];
+       u8      ReservedPad0[3];
        u8      BuildDate[12];
        __le32  CurrentNumberPorts;
-       __le32  ReservedGrowth[24];
+       struct {
+               u8      AssemblyPn[8];
+               u8      FruPn[8];
+               u8      BatteryFruPn[8];
+               u8      EcVersionString[8];
+               u8      Tsid[12];
+       }       VpdInfo;
+       __le32  FlashFirmwareRevision;
+       __le32  FlashFirmwareBuild;
+       __le32  RaidTypeMorphOptions;
+       __le32  FlashFirmwareBootRevision;
+       __le32  FlashFirmwareBootBuild;
+       u8      MfgPcbaSerialNo[12];
+       u8      MfgWWNName[8];
+       __le32  MoreFeatureBits;
+       __le32  ReservedGrowth[1];
 };
 #define AAC_FEATURE_FALCON     0x00000010
 #define AAC_SIS_VERSION_V3     3
@@ -970,7 +950,6 @@ struct aac_dev
        struct fib              *fibs;
 
        struct fib              *free_fib;
-       struct fib              *timeout_fib;
        spinlock_t              fib_lock;
        
        struct aac_queue_block *queues;
@@ -1060,6 +1039,9 @@ struct aac_dev
 #define aac_adapter_check_health(dev) \
        (dev)->a_ops.adapter_check_health(dev)
 
+#define aac_adapter_restart(dev,bled) \
+       (dev)->a_ops.adapter_restart(dev,bled)
+
 #define aac_adapter_ioremap(dev, size) \
        (dev)->a_ops.adapter_ioremap(dev, size)
 
@@ -1516,8 +1498,7 @@ struct aac_mntent {
        struct creation_info    create_info;    /* if applicable */
        __le32                  capacity;
        __le32                  vol;            /* substrate structure */
-       __le32                  obj;            /* FT_FILESYS, 
-                                                  FT_DATABASE, etc. */
+       __le32                  obj;            /* FT_FILESYS, etc. */
        __le32                  state;          /* unready for mounting, 
                                                   readonly, etc. */
        union aac_contentinfo   fileinfo;       /* Info specific to content 
@@ -1817,7 +1798,7 @@ int aac_fib_send(u16 command, struct fib * context, unsigned long size, int prio
 int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry);
 void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum);
 int aac_fib_complete(struct fib * context);
-#define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data)
+#define fib_data(fibctx) ((void *)(fibctx)->hw_fib_va->data)
 struct aac_dev *aac_init_adapter(struct aac_dev *dev);
 int aac_get_config_status(struct aac_dev *dev, int commit_flag);
 int aac_get_containers(struct aac_dev *dev);
@@ -1840,8 +1821,11 @@ struct aac_driver_ident* aac_get_driver_ident(int devtype);
 int aac_get_adapter_info(struct aac_dev* dev);
 int aac_send_shutdown(struct aac_dev *dev);
 int aac_probe_container(struct aac_dev *dev, int cid);
+int _aac_rx_init(struct aac_dev *dev);
+int aac_rx_select_comm(struct aac_dev *dev, int comm);
 extern int numacb;
 extern int acbsize;
 extern char aac_driver_version[];
 extern int startup_timeout;
 extern int aif_timeout;
+extern int expose_physicals;
index e21070f..72b0393 100644 (file)
@@ -5,7 +5,7 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -64,12 +64,15 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
        unsigned size;
        int retval;
 
+       if (dev->in_reset) {
+               return -EBUSY;
+       }
        fibptr = aac_fib_alloc(dev);
        if(fibptr == NULL) {
                return -ENOMEM;
        }
                
-       kfib = fibptr->hw_fib;
+       kfib = fibptr->hw_fib_va;
        /*
         *      First copy in the header so that we can check the size field.
         */
@@ -91,9 +94,9 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
                        goto cleanup;
                }
                /* Highjack the hw_fib */
-               hw_fib = fibptr->hw_fib;
+               hw_fib = fibptr->hw_fib_va;
                hw_fib_pa = fibptr->hw_fib_pa;
-               fibptr->hw_fib = kfib = pci_alloc_consistent(dev->pdev, size, &fibptr->hw_fib_pa);
+               fibptr->hw_fib_va = kfib = pci_alloc_consistent(dev->pdev, size, &fibptr->hw_fib_pa);
                memset(((char *)kfib) + dev->max_fib_size, 0, size - dev->max_fib_size);
                memcpy(kfib, hw_fib, dev->max_fib_size);
        }
@@ -137,7 +140,7 @@ cleanup:
        if (hw_fib) {
                pci_free_consistent(dev->pdev, size, kfib, fibptr->hw_fib_pa);
                fibptr->hw_fib_pa = hw_fib_pa;
-               fibptr->hw_fib = hw_fib;
+               fibptr->hw_fib_va = hw_fib;
        }
        if (retval != -EINTR)
                aac_fib_free(fibptr);
@@ -282,15 +285,15 @@ return_fib:
                fib = list_entry(entry, struct fib, fiblink);
                fibctx->count--;
                spin_unlock_irqrestore(&dev->fib_lock, flags);
-               if (copy_to_user(f.fib, fib->hw_fib, sizeof(struct hw_fib))) {
-                       kfree(fib->hw_fib);
+               if (copy_to_user(f.fib, fib->hw_fib_va, sizeof(struct hw_fib))) {
+                       kfree(fib->hw_fib_va);
                        kfree(fib);
                        return -EFAULT;
                }       
                /*
                 *      Free the space occupied by this copy of the fib.
                 */
-               kfree(fib->hw_fib);
+               kfree(fib->hw_fib_va);
                kfree(fib);
                status = 0;
        } else {
@@ -340,7 +343,7 @@ int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context * fibctx)
                /*
                 *      Free the space occupied by this copy of the fib.
                 */
-               kfree(fib->hw_fib);
+               kfree(fib->hw_fib_va);
                kfree(fib);
        }
        /*
@@ -388,10 +391,8 @@ static int close_getadapter_fib(struct aac_dev * dev, void __user *arg)
                /*
                 *      Extract the fibctx from the input parameters
                 */
-               if (fibctx->unique == (u32)(unsigned long)arg) {   
-                       /* We found a winner */
+               if (fibctx->unique == (u32)(ptrdiff_t)arg) /* We found a winner */
                        break;
-               }
                entry = entry->next;
                fibctx = NULL;
        }
@@ -465,16 +466,20 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
        void *sg_list[32];
        u32   sg_indx = 0;
        u32 byte_count = 0;
-       u32 actual_fibsize = 0;
+       u32 actual_fibsize64, actual_fibsize = 0;
        int i;
 
 
+       if (dev->in_reset) {
+               dprintk((KERN_DEBUG"aacraid: send raw srb -EBUSY\n"));
+               return -EBUSY;
+       }
        if (!capable(CAP_SYS_ADMIN)){
                dprintk((KERN_DEBUG"aacraid: No permission to send raw srb\n")); 
                return -EPERM;
        }
        /*
-        *      Allocate and initialize a Fib then setup a BlockWrite command
+        *      Allocate and initialize a Fib then setup a SRB command
         */
        if (!(srbfib = aac_fib_alloc(dev))) {
                return -ENOMEM;
@@ -541,129 +546,183 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
                rcode = -EINVAL;
                goto cleanup;
        }
-       if (dev->dac_support == 1) {
+       actual_fibsize = sizeof(struct aac_srb) - sizeof(struct sgentry) +
+               ((user_srbcmd->sg.count & 0xff) * sizeof(struct sgentry));
+       actual_fibsize64 = actual_fibsize + (user_srbcmd->sg.count & 0xff) *
+         (sizeof(struct sgentry64) - sizeof(struct sgentry));
+       /* User made a mistake - should not continue */
+       if ((actual_fibsize != fibsize) && (actual_fibsize64 != fibsize)) {
+               dprintk((KERN_DEBUG"aacraid: Bad Size specified in "
+                 "Raw SRB command calculated fibsize=%lu;%lu "
+                 "user_srbcmd->sg.count=%d aac_srb=%lu sgentry=%lu;%lu "
+                 "issued fibsize=%d\n",
+                 actual_fibsize, actual_fibsize64, user_srbcmd->sg.count,
+                 sizeof(struct aac_srb), sizeof(struct sgentry),
+                 sizeof(struct sgentry64), fibsize));
+               rcode = -EINVAL;
+               goto cleanup;
+       }
+       if ((data_dir == DMA_NONE) && user_srbcmd->sg.count) {
+               dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
+               rcode = -EINVAL;
+               goto cleanup;
+       }
+       byte_count = 0;
+       if (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64) {
                struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg;
                struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg;
-               struct user_sgmap* usg;
-               byte_count = 0;
 
                /*
                 * This should also catch if user used the 32 bit sgmap
                 */
-               actual_fibsize = sizeof(struct aac_srb) - 
-                       sizeof(struct sgentry) +
-                       ((upsg->count & 0xff) * 
-                       sizeof(struct sgentry));
-               if(actual_fibsize != fibsize){ // User made a mistake - should not continue
-                       dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"));
-                       rcode = -EINVAL;
-                       goto cleanup;
-               }
-               usg = kmalloc(actual_fibsize - sizeof(struct aac_srb)
-                 + sizeof(struct sgmap), GFP_KERNEL);
-               if (!usg) {
-                       dprintk((KERN_DEBUG"aacraid: Allocation error in Raw SRB command\n"));
-                       rcode = -ENOMEM;
-                       goto cleanup;
-               }
-               memcpy (usg, upsg, actual_fibsize - sizeof(struct aac_srb)
-                 + sizeof(struct sgmap));
-               actual_fibsize = sizeof(struct aac_srb) - 
-                       sizeof(struct sgentry) + ((usg->count & 0xff) * 
-                               sizeof(struct sgentry64));
-               if ((data_dir == DMA_NONE) && upsg->count) {
-                       kfree (usg);
-                       dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
-                       rcode = -EINVAL;
-                       goto cleanup;
-               }
+               if (actual_fibsize64 == fibsize) {
+                       actual_fibsize = actual_fibsize64;
+                       for (i = 0; i < upsg->count; i++) {
+                               u64 addr;
+                               void* p;
+                               /* Does this really need to be GFP_DMA? */
+                               p = kmalloc(upsg->sg[i].count,GFP_KERNEL|__GFP_DMA);
+                               if(p == 0) {
+                                       dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
+                                         upsg->sg[i].count,i,upsg->count));
+                                       rcode = -ENOMEM;
+                                       goto cleanup;
+                               }
+                               addr = (u64)upsg->sg[i].addr[0];
+                               addr += ((u64)upsg->sg[i].addr[1]) << 32;
+                               sg_user[i] = (void __user *)(ptrdiff_t)addr;
+                               sg_list[i] = p; // save so we can clean up later
+                               sg_indx = i;
+
+                               if( flags & SRB_DataOut ){
+                                       if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){
+                                               dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
+                                               rcode = -EFAULT;
+                                               goto cleanup;
+                                       }
+                               }
+                               addr = pci_map_single(dev->pdev, p, upsg->sg[i].count, data_dir);
 
-               for (i = 0; i < usg->count; i++) {
-                       u64 addr;
-                       void* p;
-                       /* Does this really need to be GFP_DMA? */
-                       p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
-                       if(p == 0) {
-                               kfree (usg);
-                               dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
-                                 usg->sg[i].count,i,usg->count));
+                               psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
+                               psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
+                               byte_count += upsg->sg[i].count;
+                               psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);
+                       }
+               } else {
+                       struct user_sgmap* usg;
+                       usg = kmalloc(actual_fibsize - sizeof(struct aac_srb)
+                         + sizeof(struct sgmap), GFP_KERNEL);
+                       if (!usg) {
+                               dprintk((KERN_DEBUG"aacraid: Allocation error in Raw SRB command\n"));
                                rcode = -ENOMEM;
                                goto cleanup;
                        }
-                       sg_user[i] = (void __user *)(long)usg->sg[i].addr;
-                       sg_list[i] = p; // save so we can clean up later
-                       sg_indx = i;
-
-                       if( flags & SRB_DataOut ){
-                               if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){
+                       memcpy (usg, upsg, actual_fibsize - sizeof(struct aac_srb)
+                         + sizeof(struct sgmap));
+                       actual_fibsize = actual_fibsize64;
+
+                       for (i = 0; i < usg->count; i++) {
+                               u64 addr;
+                               void* p;
+                               /* Does this really need to be GFP_DMA? */
+                               p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
+                               if(p == 0) {
                                        kfree (usg);
-                                       dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); 
-                                       rcode = -EFAULT;
+                                       dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
+                                         usg->sg[i].count,i,usg->count));
+                                       rcode = -ENOMEM;
                                        goto cleanup;
                                }
-                       }
-                       addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir);
+                               sg_user[i] = (void __user *)(ptrdiff_t)usg->sg[i].addr;
+                               sg_list[i] = p; // save so we can clean up later
+                               sg_indx = i;
+
+                               if( flags & SRB_DataOut ){
+                                       if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){
+                                               kfree (usg);
+                                               dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
+                                               rcode = -EFAULT;
+                                               goto cleanup;
+                                       }
+                               }
+                               addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir);
 
-                       psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
-                       psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
-                       psg->sg[i].count = cpu_to_le32(usg->sg[i].count);  
-                       byte_count += usg->sg[i].count;
+                               psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
+                               psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
+                               byte_count += usg->sg[i].count;
+                               psg->sg[i].count = cpu_to_le32(usg->sg[i].count);
+                       }
+                       kfree (usg);
                }
-               kfree (usg);
-
                srbcmd->count = cpu_to_le32(byte_count);
                psg->count = cpu_to_le32(sg_indx+1);
                status = aac_fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL);
        } else {
                struct user_sgmap* upsg = &user_srbcmd->sg;
                struct sgmap* psg = &srbcmd->sg;
-               byte_count = 0;
-
-               actual_fibsize = sizeof (struct aac_srb) + (((user_srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry));
-               if(actual_fibsize != fibsize){ // User made a mistake - should not continue
-                       dprintk((KERN_DEBUG"aacraid: Bad Size specified in "
-                         "Raw SRB command calculated fibsize=%d "
-                         "user_srbcmd->sg.count=%d aac_srb=%d sgentry=%d "
-                         "issued fibsize=%d\n",
-                         actual_fibsize, user_srbcmd->sg.count,
-                         sizeof(struct aac_srb), sizeof(struct sgentry),
-                         fibsize));
-                       rcode = -EINVAL;
-                       goto cleanup;
-               }
-               if ((data_dir == DMA_NONE) && upsg->count) {
-                       dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
-                       rcode = -EINVAL;
-                       goto cleanup;
-               }
-               for (i = 0; i < upsg->count; i++) {
-                       dma_addr_t addr; 
-                       void* p;
-                       p = kmalloc(upsg->sg[i].count, GFP_KERNEL);
-                       if(p == 0) {
-                               dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
-                                 upsg->sg[i].count, i, upsg->count));
-                               rcode = -ENOMEM;
-                               goto cleanup;
-                       }
-                       sg_user[i] = (void __user *)(long)upsg->sg[i].addr;
-                       sg_list[i] = p; // save so we can clean up later
-                       sg_indx = i;
-
-                       if( flags & SRB_DataOut ){
-                               if(copy_from_user(p, sg_user[i],
-                                               upsg->sg[i].count)) {
-                                       dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); 
-                                       rcode = -EFAULT;
+
+               if (actual_fibsize64 == fibsize) {
+                       struct user_sgmap64* usg = (struct user_sgmap64 *)upsg;
+                       for (i = 0; i < upsg->count; i++) {
+                               u64 addr;
+                               void* p;
+                               /* Does this really need to be GFP_DMA? */
+                               p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
+                               if(p == 0) {
+                                       dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
+                                         usg->sg[i].count,i,usg->count));
+                                       rcode = -ENOMEM;
                                        goto cleanup;
                                }
+                               addr = (u64)usg->sg[i].addr[0];
+                               addr += ((u64)usg->sg[i].addr[1]) << 32;
+                               sg_user[i] = (void __user *)(ptrdiff_t)addr;
+                               sg_list[i] = p; // save so we can clean up later
+                               sg_indx = i;
+
+                               if( flags & SRB_DataOut ){
+                                       if(copy_from_user(p,sg_user[i],usg->sg[i].count)){
+                                               dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
+                                               rcode = -EFAULT;
+                                               goto cleanup;
+                                       }
+                               }
+                               addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir);
+
+                               psg->sg[i].addr = cpu_to_le32(addr & 0xffffffff);
+                               byte_count += usg->sg[i].count;
+                               psg->sg[i].count = cpu_to_le32(usg->sg[i].count);
                        }
-                       addr = pci_map_single(dev->pdev, p,
-                               upsg->sg[i].count, data_dir);
+               } else {
+                       for (i = 0; i < upsg->count; i++) {
+                               dma_addr_t addr;
+                               void* p;
+                               p = kmalloc(upsg->sg[i].count, GFP_KERNEL);
+                               if(p == 0) {
+                                       dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
+                                         upsg->sg[i].count, i, upsg->count));
+                                       rcode = -ENOMEM;
+                                       goto cleanup;
+                               }
+                               sg_user[i] = (void __user *)(ptrdiff_t)upsg->sg[i].addr;
+                               sg_list[i] = p; // save so we can clean up later
+                               sg_indx = i;
+
+                               if( flags & SRB_DataOut ){
+                                       if(copy_from_user(p, sg_user[i],
+                                                       upsg->sg[i].count)) {
+                                               dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
+                                               rcode = -EFAULT;
+                                               goto cleanup;
+                                       }
+                               }
+                               addr = pci_map_single(dev->pdev, p,
+                                       upsg->sg[i].count, data_dir);
 
-                       psg->sg[i].addr = cpu_to_le32(addr);
-                       psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);  
-                       byte_count += upsg->sg[i].count;
+                               psg->sg[i].addr = cpu_to_le32(addr);
+                               byte_count += upsg->sg[i].count;
+                               psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);
+                       }
                }
                srbcmd->count = cpu_to_le32(byte_count);
                psg->count = cpu_to_le32(sg_indx+1);
@@ -682,7 +741,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
 
        if( flags & SRB_DataIn ) {
                for(i = 0 ; i <= sg_indx; i++){
-                       byte_count = le32_to_cpu((dev->dac_support == 1)
+                       byte_count = le32_to_cpu(
+                         (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)
                              ? ((struct sgmap64*)&srbcmd->sg)->sg[i].count
                              : srbcmd->sg.sg[i].count);
                        if(copy_to_user(sg_user[i], sg_list[i], byte_count)){
index ae34768..33682ce 100644 (file)
@@ -5,7 +5,7 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -110,7 +110,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
        /*
         *      Align the beginning of Headers to commalign
         */
-       align = (commalign - ((unsigned long)(base) & (commalign - 1)));
+       align = (commalign - ((ptrdiff_t)(base) & (commalign - 1)));
        base = base + align;
        phys = phys + align;
        /*
index 1b97f60..5824a75 100644 (file)
@@ -5,7 +5,7 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -94,7 +94,7 @@ void aac_fib_map_free(struct aac_dev *dev)
 int aac_fib_setup(struct aac_dev * dev)
 {
        struct fib *fibptr;
-       struct hw_fib *hw_fib_va;
+       struct hw_fib *hw_fib;
        dma_addr_t hw_fib_pa;
        int i;
 
@@ -106,24 +106,24 @@ int aac_fib_setup(struct aac_dev * dev)
        if (i<0)
                return -ENOMEM;
                
-       hw_fib_va = dev->hw_fib_va;
+       hw_fib = dev->hw_fib_va;
        hw_fib_pa = dev->hw_fib_pa;
-       memset(hw_fib_va, 0, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB));
+       memset(hw_fib, 0, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB));
        /*
         *      Initialise the fibs
         */
        for (i = 0, fibptr = &dev->fibs[i]; i < (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); i++, fibptr++) 
        {
                fibptr->dev = dev;
-               fibptr->hw_fib = hw_fib_va;
-               fibptr->data = (void *) fibptr->hw_fib->data;
+               fibptr->hw_fib_va = hw_fib;
+               fibptr->data = (void *) fibptr->hw_fib_va->data;
                fibptr->next = fibptr+1;        /* Forward chain the fibs */
                init_MUTEX_LOCKED(&fibptr->event_wait);
                spin_lock_init(&fibptr->event_lock);
-               hw_fib_va->header.XferState = cpu_to_le32(0xffffffff);
-               hw_fib_va->header.SenderSize = cpu_to_le16(dev->max_fib_size);
+               hw_fib->header.XferState = cpu_to_le32(0xffffffff);
+               hw_fib->header.SenderSize = cpu_to_le16(dev->max_fib_size);
                fibptr->hw_fib_pa = hw_fib_pa;
-               hw_fib_va = (struct hw_fib *)((unsigned char *)hw_fib_va + dev->max_fib_size);
+               hw_fib = (struct hw_fib *)((unsigned char *)hw_fib + dev->max_fib_size);
                hw_fib_pa = hw_fib_pa + dev->max_fib_size;
        }
        /*
@@ -166,7 +166,7 @@ struct fib *aac_fib_alloc(struct aac_dev *dev)
         *      Null out fields that depend on being zero at the start of
         *      each I/O
         */
-       fibptr->hw_fib->header.XferState = 0;
+       fibptr->hw_fib_va->header.XferState = 0;
        fibptr->callback = NULL;
        fibptr->callback_data = NULL;
 
@@ -178,7 +178,6 @@ struct fib *aac_fib_alloc(struct aac_dev *dev)
  *     @fibptr: fib to free up
  *
  *     Frees up a fib and places it on the appropriate queue
- *     (either free or timed out)
  */
  
 void aac_fib_free(struct fib *fibptr)
@@ -186,19 +185,15 @@ void aac_fib_free(struct fib *fibptr)
        unsigned long flags;
 
        spin_lock_irqsave(&fibptr->dev->fib_lock, flags);
-       if (fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT) {
+       if (unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT))
                aac_config.fib_timeouts++;
-               fibptr->next = fibptr->dev->timeout_fib;
-               fibptr->dev->timeout_fib = fibptr;
-       } else {
-               if (fibptr->hw_fib->header.XferState != 0) {
-                       printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n",
-                                (void*)fibptr, 
-                                le32_to_cpu(fibptr->hw_fib->header.XferState));
-               }
-               fibptr->next = fibptr->dev->free_fib;
-               fibptr->dev->free_fib = fibptr;
-       }       
+       if (fibptr->hw_fib_va->header.XferState != 0) {
+               printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n",
+                        (void*)fibptr,
+                        le32_to_cpu(fibptr->hw_fib_va->header.XferState));
+       }
+       fibptr->next = fibptr->dev->free_fib;
+       fibptr->dev->free_fib = fibptr;
        spin_unlock_irqrestore(&fibptr->dev->fib_lock, flags);
 }
 
@@ -211,7 +206,7 @@ void aac_fib_free(struct fib *fibptr)
  
 void aac_fib_init(struct fib *fibptr)
 {
-       struct hw_fib *hw_fib = fibptr->hw_fib;
+       struct hw_fib *hw_fib = fibptr->hw_fib_va;
 
        hw_fib->header.StructType = FIB_MAGIC;
        hw_fib->header.Size = cpu_to_le16(fibptr->dev->max_fib_size);
@@ -231,7 +226,7 @@ void aac_fib_init(struct fib *fibptr)
  
 static void fib_dealloc(struct fib * fibptr)
 {
-       struct hw_fib *hw_fib = fibptr->hw_fib;
+       struct hw_fib *hw_fib = fibptr->hw_fib_va;
        BUG_ON(hw_fib->header.StructType != FIB_MAGIC);
        hw_fib->header.XferState = 0;        
 }
@@ -386,7 +381,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
                void *callback_data)
 {
        struct aac_dev * dev = fibptr->dev;
-       struct hw_fib * hw_fib = fibptr->hw_fib;
+       struct hw_fib * hw_fib = fibptr->hw_fib_va;
        unsigned long flags = 0;
        unsigned long qflags;
 
@@ -430,7 +425,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
         */
        hw_fib->header.Command = cpu_to_le16(command);
        hw_fib->header.XferState |= cpu_to_le32(SentFromHost);
-       fibptr->hw_fib->header.Flags = 0;       /* 0 the flags field - internal only*/
+       fibptr->hw_fib_va->header.Flags = 0;    /* 0 the flags field - internal only*/
        /*
         *      Set the size of the Fib we want to send to the adapter
         */
@@ -462,7 +457,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
        dprintk((KERN_DEBUG "  Command =               %d.\n", le32_to_cpu(hw_fib->header.Command)));
        dprintk((KERN_DEBUG "  SubCommand =            %d.\n", le32_to_cpu(((struct aac_query_mount *)fib_data(fibptr))->command)));
        dprintk((KERN_DEBUG "  XferState  =            %x.\n", le32_to_cpu(hw_fib->header.XferState)));
-       dprintk((KERN_DEBUG "  hw_fib va being sent=%p\n",fibptr->hw_fib));
+       dprintk((KERN_DEBUG "  hw_fib va being sent=%p\n",fibptr->hw_fib_va));
        dprintk((KERN_DEBUG "  hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa));
        dprintk((KERN_DEBUG "  fib being sent=%p\n",fibptr));
 
@@ -513,22 +508,20 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
                                }
                                udelay(5);
                        }
-               } else if (down_interruptible(&fibptr->event_wait)) {
-                       spin_lock_irqsave(&fibptr->event_lock, flags);
-                       if (fibptr->done == 0) {
-                               fibptr->done = 2; /* Tell interrupt we aborted */
-                               spin_unlock_irqrestore(&fibptr->event_lock, flags);
-                               return -EINTR;
-                       }
+               } else
+                       (void)down_interruptible(&fibptr->event_wait);
+               spin_lock_irqsave(&fibptr->event_lock, flags);
+               if (fibptr->done == 0) {
+                       fibptr->done = 2; /* Tell interrupt we aborted */
                        spin_unlock_irqrestore(&fibptr->event_lock, flags);
+                       return -EINTR;
                }
+               spin_unlock_irqrestore(&fibptr->event_lock, flags);
                BUG_ON(fibptr->done == 0);
                        
-               if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)){
+               if(unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT))
                        return -ETIMEDOUT;
-               } else {
-                       return 0;
-               }
+               return 0;
        }
        /*
         *      If the user does not want a response than return success otherwise
@@ -624,7 +617,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid)
 
 int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size)
 {
-       struct hw_fib * hw_fib = fibptr->hw_fib;
+       struct hw_fib * hw_fib = fibptr->hw_fib_va;
        struct aac_dev * dev = fibptr->dev;
        struct aac_queue * q;
        unsigned long nointr = 0;
@@ -688,7 +681,7 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size)
  
 int aac_fib_complete(struct fib *fibptr)
 {
-       struct hw_fib * hw_fib = fibptr->hw_fib;
+       struct hw_fib * hw_fib = fibptr->hw_fib_va;
 
        /*
         *      Check for a fib which has already been completed
@@ -774,9 +767,8 @@ void aac_printf(struct aac_dev *dev, u32 val)
 #define AIF_SNIFF_TIMEOUT      (30*HZ)
 static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
 {
-       struct hw_fib * hw_fib = fibptr->hw_fib;
+       struct hw_fib * hw_fib = fibptr->hw_fib_va;
        struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data;
-       int busy;
        u32 container;
        struct scsi_device *device;
        enum {
@@ -988,9 +980,6 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
         * behind you.
         */
 
-       busy = 0;
-
-
        /*
         *      Find the scsi_device associated with the SCSI address,
         * and mark it as changed, invalidating the cache. This deals
@@ -1035,7 +1024,6 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
 static int _aac_reset_adapter(struct aac_dev *aac)
 {
        int index, quirks;
-       u32 ret;
        int retval;
        struct Scsi_Host *host;
        struct scsi_device *dev;
@@ -1059,35 +1047,29 @@ static int _aac_reset_adapter(struct aac_dev *aac)
         *      If a positive health, means in a known DEAD PANIC
         * state and the adapter could be reset to `try again'.
         */
-       retval = aac_adapter_check_health(aac);
-       if (retval == 0)
-               retval = aac_adapter_sync_cmd(aac, IOP_RESET_ALWAYS,
-                 0, 0, 0, 0, 0, 0, &ret, NULL, NULL, NULL, NULL);
-       if (retval)
-               retval = aac_adapter_sync_cmd(aac, IOP_RESET,
-                 0, 0, 0, 0, 0, 0, &ret, NULL, NULL, NULL, NULL);
+       retval = aac_adapter_restart(aac, aac_adapter_check_health(aac));
 
        if (retval)
                goto out;
-       if (ret != 0x00000001) {
-               retval = -ENODEV;
-               goto out;
-       }
 
        /*
         *      Loop through the fibs, close the synchronous FIBS
         */
-       for (index = 0; index < (aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); index++) {
+       for (retval = 1, index = 0; index < (aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); index++) {
                struct fib *fib = &aac->fibs[index];
-               if (!(fib->hw_fib->header.XferState & cpu_to_le32(NoResponseExpected | Async)) &&
-                 (fib->hw_fib->header.XferState & cpu_to_le32(ResponseExpected))) {
+               if (!(fib->hw_fib_va->header.XferState & cpu_to_le32(NoResponseExpected | Async)) &&
+                 (fib->hw_fib_va->header.XferState & cpu_to_le32(ResponseExpected))) {
                        unsigned long flagv;
                        spin_lock_irqsave(&fib->event_lock, flagv);
                        up(&fib->event_wait);
                        spin_unlock_irqrestore(&fib->event_lock, flagv);
                        schedule();
+                       retval = 0;
                }
        }
+       /* Give some extra time for ioctls to complete. */
+       if (retval == 0)
+               ssleep(2);
        index = aac->cardtype;
 
        /*
@@ -1248,7 +1230,7 @@ int aac_check_health(struct aac_dev * aac)
 
                        memset(hw_fib, 0, sizeof(struct hw_fib));
                        memset(fib, 0, sizeof(struct fib));
-                       fib->hw_fib = hw_fib;
+                       fib->hw_fib_va = hw_fib;
                        fib->dev = aac;
                        aac_fib_init(fib);
                        fib->type = FSAFS_NTC_FIB_CONTEXT;
@@ -1354,11 +1336,11 @@ int aac_command_thread(void *data)
                         *      do anything at this point since we don't have
                         *      anything defined for this thread to do.
                         */
-                       hw_fib = fib->hw_fib;
+                       hw_fib = fib->hw_fib_va;
                        memset(fib, 0, sizeof(struct fib));
                        fib->type = FSAFS_NTC_FIB_CONTEXT;
                        fib->size = sizeof( struct fib );
-                       fib->hw_fib = hw_fib;
+                       fib->hw_fib_va = hw_fib;
                        fib->data = hw_fib->data;
                        fib->dev = dev;
                        /*
@@ -1485,7 +1467,7 @@ int aac_command_thread(void *data)
                                                 */
                                                memcpy(hw_newfib, hw_fib, sizeof(struct hw_fib));
                                                memcpy(newfib, fib, sizeof(struct fib));
-                                               newfib->hw_fib = hw_newfib;
+                                               newfib->hw_fib_va = hw_newfib;
                                                /*
                                                 * Put the FIB onto the
                                                 * fibctx's fibs
index d38b628..42c7dcd 100644 (file)
@@ -5,7 +5,7 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -32,7 +32,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/completion.h>
@@ -73,7 +72,7 @@ unsigned int aac_response_normal(struct aac_queue * q)
                u32 index = le32_to_cpu(entry->addr);
                fast = index & 0x01;
                fib = &dev->fibs[index >> 2];
-               hwfib = fib->hw_fib;
+               hwfib = fib->hw_fib_va;
                
                aac_consumer_free(dev, q, HostNormRespQueue);
                /*
@@ -84,11 +83,13 @@ unsigned int aac_response_normal(struct aac_queue * q)
                 *      continue. The caller has already been notified that
                 *      the fib timed out.
                 */
-               if (!(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT))
-                       dev->queues->queue[AdapNormCmdQueue].numpending--;
-               else {
-                       printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags);
-                       printk(KERN_DEBUG"aacraid: hwfib=%p fib index=%i fib=%p\n",hwfib, hwfib->header.SenderData,fib);
+               dev->queues->queue[AdapNormCmdQueue].numpending--;
+
+               if (unlikely(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) {
+                       spin_unlock_irqrestore(q->lock, flags);
+                       aac_fib_complete(fib);
+                       aac_fib_free(fib);
+                       spin_lock_irqsave(q->lock, flags);
                        continue;
                }
                spin_unlock_irqrestore(q->lock, flags);
@@ -193,7 +194,7 @@ unsigned int aac_command_normal(struct aac_queue *q)
                INIT_LIST_HEAD(&fib->fiblink);
                fib->type = FSAFS_NTC_FIB_CONTEXT;
                fib->size = sizeof(struct fib);
-               fib->hw_fib = hw_fib;
+               fib->hw_fib_va = hw_fib;
                fib->data = hw_fib->data;
                fib->dev = dev;
                
@@ -254,12 +255,13 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index)
                        return 1;
                }
                memset(hw_fib, 0, sizeof(struct hw_fib));
-               memcpy(hw_fib, (struct hw_fib *)(((unsigned long)(dev->regs.sa)) + (index & ~0x00000002L)), sizeof(struct hw_fib));
+               memcpy(hw_fib, (struct hw_fib *)(((ptrdiff_t)(dev->regs.sa)) +
+                 (index & ~0x00000002L)), sizeof(struct hw_fib));
                memset(fib, 0, sizeof(struct fib));
                INIT_LIST_HEAD(&fib->fiblink);
                fib->type = FSAFS_NTC_FIB_CONTEXT;
                fib->size = sizeof(struct fib);
-               fib->hw_fib = hw_fib;
+               fib->hw_fib_va = hw_fib;
                fib->data = hw_fib->data;
                fib->dev = dev;
        
@@ -271,7 +273,7 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index)
        } else {
                int fast = index & 0x01;
                struct fib * fib = &dev->fibs[index >> 2];
-               struct hw_fib * hwfib = fib->hw_fib;
+               struct hw_fib * hwfib = fib->hw_fib_va;
 
                /*
                 *      Remove this fib from the Outstanding I/O queue.
@@ -281,14 +283,14 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index)
                 *      continue. The caller has already been notified that
                 *      the fib timed out.
                 */
-               if ((fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) {
-                       printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags);
-                       printk(KERN_DEBUG"aacraid: hwfib=%p index=%i fib=%p\n",hwfib, hwfib->header.SenderData,fib);
+               dev->queues->queue[AdapNormCmdQueue].numpending--;
+
+               if (unlikely(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) {
+                       aac_fib_complete(fib);
+                       aac_fib_free(fib);
                        return 0;
                }
 
-               dev->queues->queue[AdapNormCmdQueue].numpending--;
-
                if (fast) {
                        /*
                         *      Doctor the fib
index 0f948c2..350ea7f 100644 (file)
@@ -5,7 +5,7 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -82,8 +82,6 @@ static LIST_HEAD(aac_devices);
 static int aac_cfg_major = -1;
 char aac_driver_version[] = AAC_DRIVER_FULL_VERSION;
 
-extern int expose_physicals;
-
 /*
  * Because of the way Linux names scsi devices, the order in this table has
  * become important.  Check for on-board Raid first, add-in cards second.
@@ -247,7 +245,19 @@ static struct aac_driver_ident aac_drivers[] = {
 
 static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
+       struct Scsi_Host *host = cmd->device->host;
+       struct aac_dev *dev = (struct aac_dev *)host->hostdata;
+       u32 count = 0;
        cmd->scsi_done = done;
+       for (; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
+               struct fib * fib = &dev->fibs[count];
+               struct scsi_cmnd * command;
+               if (fib->hw_fib_va->header.XferState &&
+                   ((command = fib->callback_data)) &&
+                   (command == cmd) &&
+                   (cmd->SCp.phase == AAC_OWNER_FIRMWARE))
+                       return 0; /* Already owned by Adapter */
+       }
        cmd->SCp.phase = AAC_OWNER_LOWLEVEL;
        return (aac_scsi_cmd(cmd) ? FAILED : 0);
 } 
@@ -446,6 +456,40 @@ static int aac_ioctl(struct scsi_device *sdev, int cmd, void __user * arg)
        return aac_do_ioctl(dev, cmd, arg);
 }
 
+static int aac_eh_abort(struct scsi_cmnd* cmd)
+{
+       struct scsi_device * dev = cmd->device;
+       struct Scsi_Host * host = dev->host;
+       struct aac_dev * aac = (struct aac_dev *)host->hostdata;
+       int count;
+       int ret = FAILED;
+
+       printk(KERN_ERR "%s: Host adapter abort request (%d,%d,%d,%d)\n",
+               AAC_DRIVERNAME,
+               host->host_no, sdev_channel(dev), sdev_id(dev), dev->lun);
+       switch (cmd->cmnd[0]) {
+       case SERVICE_ACTION_IN:
+               if (!(aac->raw_io_interface) ||
+                   !(aac->raw_io_64) ||
+                   ((cmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))
+                       break;
+       case INQUIRY:
+       case READ_CAPACITY:
+       case TEST_UNIT_READY:
+               /* Mark associated FIB to not complete, eh handler does this */
+               for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
+                       struct fib * fib = &aac->fibs[count];
+                       if (fib->hw_fib_va->header.XferState &&
+                         (fib->callback_data == cmd)) {
+                               fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT;
+                               cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER;
+                               ret = SUCCESS;
+                       }
+               }
+       }
+       return ret;
+}
+
 /*
  *     aac_eh_reset    - Reset command handling
  *     @scsi_cmd:      SCSI command block causing the reset
@@ -457,12 +501,20 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
        struct Scsi_Host * host = dev->host;
        struct scsi_cmnd * command;
        int count;
-       struct aac_dev * aac;
+       struct aac_dev * aac = (struct aac_dev *)host->hostdata;
        unsigned long flags;
 
+       /* Mark the associated FIB to not complete, eh handler does this */
+       for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
+               struct fib * fib = &aac->fibs[count];
+               if (fib->hw_fib_va->header.XferState &&
+                 (fib->callback_data == cmd)) {
+                       fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT;
+                       cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER;
+               }
+       }
        printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", 
                                        AAC_DRIVERNAME);
-       aac = (struct aac_dev *)host->hostdata;
 
        if ((count = aac_check_health(aac)))
                return count;
@@ -496,7 +548,7 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
                ssleep(1);
        }
        printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME);
-       return -ETIMEDOUT;
+       return SUCCESS; /* Cause an immediate retry of the command with a ten second delay after successful tur */
 }
 
 /**
@@ -796,6 +848,7 @@ static struct scsi_host_template aac_driver_template = {
        .bios_param                     = aac_biosparm, 
        .shost_attrs                    = aac_attrs,
        .slave_configure                = aac_slave_configure,
+       .eh_abort_handler               = aac_eh_abort,
        .eh_host_reset_handler          = aac_eh_reset,
        .can_queue                      = AAC_NUM_IO_FIB,       
        .this_id                        = MAXIMUM_NUM_CONTAINERS,
index c76b611..a8ace56 100644 (file)
@@ -74,9 +74,6 @@ static int aac_nark_ioremap(struct aac_dev * dev, u32 size)
 
 int aac_nark_init(struct aac_dev * dev)
 {
-       extern int _aac_rx_init(struct aac_dev *dev);
-       extern int aac_rx_select_comm(struct aac_dev *dev, int comm);
-
        /*
         *      Fill in the function dispatch table.
         */
index d953c3f..9c5fcfb 100644 (file)
@@ -45,7 +45,6 @@
 static int aac_rkt_select_comm(struct aac_dev *dev, int comm)
 {
        int retval;
-       extern int aac_rx_select_comm(struct aac_dev *dev, int comm);
        retval = aac_rx_select_comm(dev, comm);
        if (comm == AAC_COMM_MESSAGE) {
                /*
@@ -97,8 +96,6 @@ static int aac_rkt_ioremap(struct aac_dev * dev, u32 size)
 
 int aac_rkt_init(struct aac_dev *dev)
 {
-       extern int _aac_rx_init(struct aac_dev *dev);
-
        /*
         *      Fill in the function dispatch table.
         */
index d242e26..0c71315 100644 (file)
@@ -5,7 +5,7 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -57,25 +57,25 @@ static irqreturn_t aac_rx_intr_producer(int irq, void *dev_id)
         *      been enabled.
         *      Check to see if this is our interrupt.  If it isn't just return
         */
-       if (intstat & ~(dev->OIMR)) {
+       if (likely(intstat & ~(dev->OIMR))) {
                bellbits = rx_readl(dev, OutboundDoorbellReg);
-               if (bellbits & DoorBellPrintfReady) {
+               if (unlikely(bellbits & DoorBellPrintfReady)) {
                        aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5]));
                        rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
                        rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
                }
-               else if (bellbits & DoorBellAdapterNormCmdReady) {
+               else if (unlikely(bellbits & DoorBellAdapterNormCmdReady)) {
                        rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
                        aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
                }
-               else if (bellbits & DoorBellAdapterNormRespReady) {
+               else if (likely(bellbits & DoorBellAdapterNormRespReady)) {
                        rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
                        aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
                }
-               else if (bellbits & DoorBellAdapterNormCmdNotFull) {
+               else if (unlikely(bellbits & DoorBellAdapterNormCmdNotFull)) {
                        rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
                }
-               else if (bellbits & DoorBellAdapterNormRespNotFull) {
+               else if (unlikely(bellbits & DoorBellAdapterNormRespNotFull)) {
                        rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
                        rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
                }
@@ -88,11 +88,11 @@ static irqreturn_t aac_rx_intr_message(int irq, void *dev_id)
 {
        struct aac_dev *dev = dev_id;
        u32 Index = rx_readl(dev, MUnit.OutboundQueue);
-       if (Index == 0xFFFFFFFFL)
+       if (unlikely(Index == 0xFFFFFFFFL))
                Index = rx_readl(dev, MUnit.OutboundQueue);
-       if (Index != 0xFFFFFFFFL) {
+       if (likely(Index != 0xFFFFFFFFL)) {
                do {
-                       if (aac_intr_normal(dev, Index)) {
+                       if (unlikely(aac_intr_normal(dev, Index))) {
                                rx_writel(dev, MUnit.OutboundQueue, Index);
                                rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady);
                        }
@@ -204,7 +204,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command,
                 */
                msleep(1);
        }
-       if (ok != 1) {
+       if (unlikely(ok != 1)) {
                /*
                 *      Restore interrupt mask even though we timed out
                 */
@@ -294,7 +294,7 @@ static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event)
  *     Start up processing on an i960 based AAC adapter
  */
 
-void aac_rx_start_adapter(struct aac_dev *dev)
+static void aac_rx_start_adapter(struct aac_dev *dev)
 {
        struct aac_init *init;
 
@@ -319,12 +319,12 @@ static int aac_rx_check_health(struct aac_dev *dev)
        /*
         *      Check to see if the board failed any self tests.
         */
-       if (status & SELF_TEST_FAILED)
+       if (unlikely(status & SELF_TEST_FAILED))
                return -1;
        /*
         *      Check to see if the board panic'd.
         */
-       if (status & KERNEL_PANIC) {
+       if (unlikely(status & KERNEL_PANIC)) {
                char * buffer;
                struct POSTSTATUS {
                        __le32 Post_Command;
@@ -333,15 +333,15 @@ static int aac_rx_check_health(struct aac_dev *dev)
                dma_addr_t paddr, baddr;
                int ret;
 
-               if ((status & 0xFF000000L) == 0xBC000000L)
+               if (likely((status & 0xFF000000L) == 0xBC000000L))
                        return (status >> 16) & 0xFF;
                buffer = pci_alloc_consistent(dev->pdev, 512, &baddr);
                ret = -2;
-               if (buffer == NULL)
+               if (unlikely(buffer == NULL))
                        return ret;
                post = pci_alloc_consistent(dev->pdev,
                  sizeof(struct POSTSTATUS), &paddr);
-               if (post == NULL) {
+               if (unlikely(post == NULL)) {
                        pci_free_consistent(dev->pdev, 512, buffer, baddr);
                        return ret;
                }
@@ -353,7 +353,7 @@ static int aac_rx_check_health(struct aac_dev *dev)
                  NULL, NULL, NULL, NULL, NULL);
                pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
                  post, paddr);
-               if ((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X'))) {
+               if (likely((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X')))) {
                        ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10);
                        ret <<= 4;
                        ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10);
@@ -364,7 +364,7 @@ static int aac_rx_check_health(struct aac_dev *dev)
        /*
         *      Wait for the adapter to be up and running.
         */
-       if (!(status & KERNEL_UP_AND_RUNNING))
+       if (unlikely(!(status & KERNEL_UP_AND_RUNNING)))
                return -3;
        /*
         *      Everything is OK
@@ -387,7 +387,7 @@ static int aac_rx_deliver_producer(struct fib * fib)
        unsigned long nointr = 0;
 
        spin_lock_irqsave(q->lock, qflags);
-       aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib, 1, fib, &nointr);
+       aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib_va, 1, fib, &nointr);
 
        q->numpending++;
        *(q->headers.producer) = cpu_to_le32(Index + 1);
@@ -419,9 +419,9 @@ static int aac_rx_deliver_message(struct fib * fib)
        spin_unlock_irqrestore(q->lock, qflags);
        for(;;) {
                Index = rx_readl(dev, MUnit.InboundQueue);
-               if (Index == 0xFFFFFFFFL)
+               if (unlikely(Index == 0xFFFFFFFFL))
                        Index = rx_readl(dev, MUnit.InboundQueue);
-               if (Index != 0xFFFFFFFFL)
+               if (likely(Index != 0xFFFFFFFFL))
                        break;
                if (--count == 0) {
                        spin_lock_irqsave(q->lock, qflags);
@@ -437,7 +437,7 @@ static int aac_rx_deliver_message(struct fib * fib)
        device += sizeof(u32);
        writel((u32)(addr >> 32), device);
        device += sizeof(u32);
-       writel(le16_to_cpu(fib->hw_fib->header.Size), device);
+       writel(le16_to_cpu(fib->hw_fib_va->header.Size), device);
        rx_writel(dev, MUnit.InboundQueue, Index);
        return 0;
 }
@@ -460,22 +460,34 @@ static int aac_rx_ioremap(struct aac_dev * dev, u32 size)
        return 0;
 }
 
-static int aac_rx_restart_adapter(struct aac_dev *dev)
+static int aac_rx_restart_adapter(struct aac_dev *dev, int bled)
 {
        u32 var;
 
-       printk(KERN_ERR "%s%d: adapter kernel panic'd.\n",
-                       dev->name, dev->id);
-
-       if (aac_rx_check_health(dev) <= 0)
-               return 1;
-       if (rx_sync_cmd(dev, IOP_RESET, 0, 0, 0, 0, 0, 0,
-                       &var, NULL, NULL, NULL, NULL))
-               return 1;
+       if (bled)
+               printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n",
+                       dev->name, dev->id, bled);
+       else {
+               bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS,
+                 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL);
+               if (!bled && (var != 0x00000001))
+                       bled = -EINVAL;
+       }
+       if (bled && (bled != -ETIMEDOUT))
+               bled = aac_adapter_sync_cmd(dev, IOP_RESET,
+                 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL);
+
+       if (bled && (bled != -ETIMEDOUT))
+               return -EINVAL;
+       if (bled || (var == 0x3803000F)) { /* USE_OTHER_METHOD */
+               rx_writel(dev, MUnit.reserved2, 3);
+               msleep(5000); /* Delay 5 seconds */
+               var = 0x00000001;
+       }
        if (var != 0x00000001)
-                return 1;
+               return -EINVAL;
        if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC)
-               return 1;
+               return -ENODEV;
        return 0;
 }
 
@@ -517,24 +529,29 @@ int _aac_rx_init(struct aac_dev *dev)
 {
        unsigned long start;
        unsigned long status;
-       int instance;
-       const char * name;
-
-       instance = dev->id;
-       name     = dev->name;
+       int restart = 0;
+       int instance = dev->id;
+       const char * name = dev->name;
 
        if (aac_adapter_ioremap(dev, dev->base_size)) {
                printk(KERN_WARNING "%s: unable to map adapter.\n", name);
                goto error_iounmap;
        }
 
+       /* Failure to reset here is an option ... */
+       dev->OIMR = status = rx_readb (dev, MUnit.OIMR);
+       if ((((status & 0xff) != 0xff) || reset_devices) &&
+         !aac_rx_restart_adapter(dev, 0))
+               ++restart;
        /*
         *      Check to see if the board panic'd while booting.
         */
        status = rx_readl(dev, MUnit.OMRx[0]);
-       if (status & KERNEL_PANIC)
-               if (aac_rx_restart_adapter(dev))
+       if (status & KERNEL_PANIC) {
+               if (aac_rx_restart_adapter(dev, aac_rx_check_health(dev)))
                        goto error_iounmap;
+               ++restart;
+       }
        /*
         *      Check to see if the board failed any self tests.
         */
@@ -556,12 +573,23 @@ int _aac_rx_init(struct aac_dev *dev)
         */
        while (!((status = rx_readl(dev, MUnit.OMRx[0])) & KERNEL_UP_AND_RUNNING))
        {
-               if(time_after(jiffies, start+startup_timeout*HZ))
-               {
+               if ((restart &&
+                 (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
+                 time_after(jiffies, start+HZ*startup_timeout)) {
                        printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", 
                                        dev->name, instance, status);
                        goto error_iounmap;
                }
+               if (!restart &&
+                 ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) ||
+                 time_after(jiffies, start + HZ *
+                 ((startup_timeout > 60)
+                   ? (startup_timeout - 60)
+                   : (startup_timeout / 2))))) {
+                       if (likely(!aac_rx_restart_adapter(dev, aac_rx_check_health(dev))))
+                               start = jiffies;
+                       ++restart;
+               }
                msleep(1);
        }
        /*
@@ -572,6 +600,7 @@ int _aac_rx_init(struct aac_dev *dev)
        dev->a_ops.adapter_notify = aac_rx_notify_adapter;
        dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
        dev->a_ops.adapter_check_health = aac_rx_check_health;
+       dev->a_ops.adapter_restart = aac_rx_restart_adapter;
 
        /*
         *      First clear out all interrupts.  Then enable the one's that we
index 6f1a178..f4b5e97 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/blkdev.h>
index 1d239f6..cbbfbc9 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
-#include <linux/pci.h>
 #include <linux/isapnp.h>
 #include <linux/blkdev.h>
 #include <linux/mca.h>
index 911ea17..5e6620f 100644 (file)
@@ -57,18 +57,6 @@ config AIC79XX_BUILD_FIRMWARE
        or modify the assembler Makefile or the files it includes if your
        build environment is different than that of the author.
 
-config AIC79XX_ENABLE_RD_STRM
-       bool "Enable Read Streaming for All Targets"
-       depends on SCSI_AIC79XX
-       default n
-       help
-       Read Streaming is a U320 protocol option that should enhance
-       performance.  Early U320 drive firmware actually performs slower
-       with read streaming enabled so it is disabled by default.  Read
-       Streaming can be configured in much the same way as tagged queueing
-       using the "rd_strm" command line option.  See
-       drivers/scsi/aic7xxx/README.aic79xx for details.
-
 config AIC79XX_DEBUG_ENABLE
        bool "Compile in Debugging Code"
        depends on SCSI_AIC79XX
index cd93f9a..88da670 100644 (file)
@@ -50,16 +50,6 @@ config AIC7XXX_RESET_DELAY_MS
 
        Default: 5000 (5 seconds)
 
-config AIC7XXX_PROBE_EISA_VL
-       bool "Probe for EISA and VL AIC7XXX Adapters"
-       depends on SCSI_AIC7XXX && EISA
-       help
-       Probe for EISA and VLB Aic7xxx controllers.  In many newer systems,
-       the invasive probes necessary to detect these controllers can cause
-       other devices to fail.  For this reason, the non-PCI probe code is
-       disabled by default.  The current value of this option can be "toggled"
-       via the no_probe kernel command line option.
-
 config AIC7XXX_BUILD_FIRMWARE
        bool "Build Adapter Firmware with Kernel Build"
        depends on SCSI_AIC7XXX && !PREVENT_FIRMWARE_BUILD
index 2be03e9..6054881 100644 (file)
@@ -363,6 +363,8 @@ static int ahd_linux_run_command(struct ahd_softc*,
                                 struct scsi_cmnd *);
 static void ahd_linux_setup_tag_info_global(char *p);
 static int  aic79xx_setup(char *c);
+static void ahd_freeze_simq(struct ahd_softc *ahd);
+static void ahd_release_simq(struct ahd_softc *ahd);
 
 static int ahd_linux_unit;
 
@@ -2016,13 +2018,13 @@ ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd)
        cmd->scsi_done(cmd);
 }
 
-void
+static void
 ahd_freeze_simq(struct ahd_softc *ahd)
 {
        scsi_block_requests(ahd->platform_data->host);
 }
 
-void
+static void
 ahd_release_simq(struct ahd_softc *ahd)
 {
        scsi_unblock_requests(ahd->platform_data->host);
index 147c83c..9218f29 100644 (file)
@@ -837,8 +837,6 @@ int ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg);
 void   ahd_platform_free(struct ahd_softc *ahd);
 void   ahd_platform_init(struct ahd_softc *ahd);
 void   ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb);
-void   ahd_freeze_simq(struct ahd_softc *ahd);
-void   ahd_release_simq(struct ahd_softc *ahd);
 
 static __inline void
 ahd_freeze_scb(struct scb *scb)
index 954c7c2..e1bd57b 100644 (file)
@@ -1278,11 +1278,6 @@ typedef enum {
        AHC_QUEUE_TAGGED
 } ahc_queue_alg;
 
-void                   ahc_set_tags(struct ahc_softc *ahc,
-                                    struct scsi_cmnd *cmd,
-                                    struct ahc_devinfo *devinfo,
-                                    ahc_queue_alg alg);
-
 /**************************** Target Mode *************************************/
 #ifdef AHC_TARGET_MODE
 void           ahc_send_lstate_events(struct ahc_softc *,
index 50ef785..75733b0 100644 (file)
@@ -2073,7 +2073,7 @@ ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
 /*
  * Update the current state of tagged queuing for a given target.
  */
-void
+static void
 ahc_set_tags(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
             struct ahc_devinfo *devinfo, ahc_queue_alg alg)
 {
index 8f43ff7..db6ab1a 100644 (file)
@@ -24,7 +24,6 @@
  *
  */
 
-#include <linux/pci.h>
 #include <scsi/scsi_host.h>
 
 #include "aic94xx.h"
index 12497da..03bfed6 100644 (file)
@@ -49,7 +49,6 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
 
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
index 0f920c8..eff846a 100644 (file)
@@ -1,19 +1,19 @@
-/* 
+/*
  * NCR 5380 generic driver routines.  These should make it *trivial*
- *     to implement 5380 SCSI drivers under Linux with a non-trantor
+ *     to implement 5380 SCSI drivers under Linux with a non-trantor
  *     architecture.
  *
  *     Note that these routines also work with NR53c400 family chips.
  *
  * Copyright 1993, Drew Eckhardt
- *     Visionary Computing 
+ *     Visionary Computing
  *     (Unix and Linux consulting and custom programming)
- *     drew@colorado.edu
+ *     drew@colorado.edu
  *     +1 (303) 666-5836
  *
- * DISTRIBUTION RELEASE 6. 
+ * DISTRIBUTION RELEASE 6.
  *
- * For more information, please consult 
+ * For more information, please consult
  *
  * NCR 5380 Family
  * SCSI Protocol Controller
@@ -57,7 +57,7 @@
  * - I've deleted all the stuff for AUTOPROBE_IRQ, REAL_DMA_POLL, PSEUDO_DMA
  *    and USLEEP, because these were messing up readability and will never be
  *    needed for Atari SCSI.
- * 
+ *
  * - I've revised the NCR5380_main() calling scheme (relax the 'main_running'
  *   stuff), and 'main' is executed in a bottom half if awoken by an
  *   interrupt.
  */
 
 /*
- * Further development / testing that should be done : 
- * 1.  Test linked command handling code after Eric is ready with 
+ * Further development / testing that should be done :
+ * 1.  Test linked command handling code after Eric is ready with
  *     the high level code.
  */
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_transport_spi.h>
 
 #if (NDEBUG & NDEBUG_LISTS)
-#define LIST(x,y) \
-  { printk("LINE:%d   Adding %p to %p\n", __LINE__, (void*)(x), (void*)(y)); \
-    if ((x)==(y)) udelay(5); }
-#define REMOVE(w,x,y,z) \
-  { printk("LINE:%d   Removing: %p->%p  %p->%p \n", __LINE__, \
-          (void*)(w), (void*)(x), (void*)(y), (void*)(z)); \
-    if ((x)==(y)) udelay(5); }
+#define LIST(x, y)                                             \
+       do {                                                    \
+               printk("LINE:%d   Adding %p to %p\n",           \
+                      __LINE__, (void*)(x), (void*)(y));       \
+               if ((x) == (y))                                 \
+                       udelay(5);                              \
+       } while (0)
+#define REMOVE(w, x, y, z)                                     \
+       do {                                                    \
+               printk("LINE:%d   Removing: %p->%p  %p->%p \n", \
+                      __LINE__, (void*)(w), (void*)(x),        \
+                      (void*)(y), (void*)(z));                 \
+               if ((x) == (y))                                 \
+                       udelay(5);                              \
+       } while (0)
 #else
 #define LIST(x,y)
 #define REMOVE(w,x,y,z)
  * more difficult than it has to be.
  *
  * Also, many of the SCSI drivers were written before the command queuing
- * routines were implemented, meaning their implementations of queued 
+ * routines were implemented, meaning their implementations of queued
  * commands were hacked on rather than designed in from the start.
  *
- * When I designed the Linux SCSI drivers I figured that 
+ * When I designed the Linux SCSI drivers I figured that
  * while having two different SCSI boards in a system might be useful
  * for debugging things, two of the same type wouldn't be used.
  * Well, I was wrong and a number of users have mailed me about running
  * multiple high-performance SCSI boards in a server.
  *
- * Finally, when I get questions from users, I have no idea what 
+ * Finally, when I get questions from users, I have no idea what
  * revision of my driver they are running.
  *
  * This driver attempts to address these problems :
- * This is a generic 5380 driver.  To use it on a different platform, 
+ * This is a generic 5380 driver.  To use it on a different platform,
  * one simply writes appropriate system specific macros (ie, data
- * transfer - some PC's will use the I/O bus, 68K's must use 
+ * transfer - some PC's will use the I/O bus, 68K's must use
  * memory mapped) and drops this file in their 'C' wrapper.
  *
- * As far as command queueing, two queues are maintained for 
+ * As far as command queueing, two queues are maintained for
  * each 5380 in the system - commands that haven't been issued yet,
- * and commands that are currently executing.  This means that an 
- * unlimited number of commands may be queued, letting 
- * more commands propagate from the higher driver levels giving higher 
- * throughput.  Note that both I_T_L and I_T_L_Q nexuses are supported, 
- * allowing multiple commands to propagate all the way to a SCSI-II device 
+ * and commands that are currently executing.  This means that an
+ * unlimited number of commands may be queued, letting
+ * more commands propagate from the higher driver levels giving higher
+ * throughput.  Note that both I_T_L and I_T_L_Q nexuses are supported,
+ * allowing multiple commands to propagate all the way to a SCSI-II device
  * while a command is already executing.
  *
- * To solve the multiple-boards-in-the-same-system problem, 
+ * To solve the multiple-boards-in-the-same-system problem,
  * there is a separate instance structure for each instance
  * of a 5380 in the system.  So, multiple NCR5380 drivers will
  * be able to coexist with appropriate changes to the high level
- * SCSI code.  
+ * SCSI code.
  *
  * A NCR5380_PUBLIC_REVISION macro is provided, with the release
- * number (updated for each public release) printed by the 
- * NCR5380_print_options command, which should be called from the 
+ * number (updated for each public release) printed by the
+ * NCR5380_print_options command, which should be called from the
  * wrapper detect function, so that I know what release of the driver
  * users are using.
  *
- * Issues specific to the NCR5380 : 
+ * Issues specific to the NCR5380 :
  *
- * When used in a PIO or pseudo-dma mode, the NCR5380 is a braindead 
- * piece of hardware that requires you to sit in a loop polling for 
- * the REQ signal as long as you are connected.  Some devices are 
- * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect 
+ * When used in a PIO or pseudo-dma mode, the NCR5380 is a braindead
+ * piece of hardware that requires you to sit in a loop polling for
+ * the REQ signal as long as you are connected.  Some devices are
+ * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect
  * while doing long seek operations.
- * 
+ *
  * The workaround for this is to keep track of devices that have
  * disconnected.  If the device hasn't disconnected, for commands that
- * should disconnect, we do something like 
+ * should disconnect, we do something like
  *
  * while (!REQ is asserted) { sleep for N usecs; poll for M usecs }
- * 
- * Some tweaking of N and M needs to be done.  An algorithm based 
+ *
+ * Some tweaking of N and M needs to be done.  An algorithm based
  * on "time to data" would give the best results as long as short time
- * to datas (ie, on the same track) were considered, however these 
+ * to datas (ie, on the same track) were considered, however these
  * broken devices are the exception rather than the rule and I'd rather
  * spend my time optimizing for the normal case.
  *
  * At the heart of the design is a coroutine, NCR5380_main,
  * which is started when not running by the interrupt handler,
  * timer, and queue command function.  It attempts to establish
- * I_T_L or I_T_L_Q nexuses by removing the commands from the 
- * issue queue and calling NCR5380_select() if a nexus 
- * is not established. 
+ * I_T_L or I_T_L_Q nexuses by removing the commands from the
+ * issue queue and calling NCR5380_select() if a nexus
+ * is not established.
  *
  * Once a nexus is established, the NCR5380_information_transfer()
  * phase goes through the various phases as instructed by the target.
  * calling NCR5380_intr()  which will in turn call NCR5380_reselect
  * to reestablish a nexus.  This will run main if necessary.
  *
- * On command termination, the done function will be called as 
+ * On command termination, the done function will be called as
  * appropriate.
  *
- * SCSI pointers are maintained in the SCp field of SCSI command 
+ * SCSI pointers are maintained in the SCp field of SCSI command
  * structures, being initialized after the command is connected
  * in NCR5380_select, and set as appropriate in NCR5380_information_transfer.
  * Note that in violation of the standard, an implicit SAVE POINTERS operation
 /*
  * Using this file :
  * This file a skeleton Linux SCSI driver for the NCR 5380 series
- * of chips.  To use it, you write an architecture specific functions 
+ * of chips.  To use it, you write an architecture specific functions
  * and macros and include this file in your driver.
  *
- * These macros control options : 
+ * These macros control options :
  * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
- *     for commands that return with a CHECK CONDITION status. 
+ *     for commands that return with a CHECK CONDITION status.
  *
  * LINKED - if defined, linked commands are supported.
  *
  * SUPPORT_TAGS - if defined, SCSI-2 tagged queuing is used where possible
  *
  * These macros MUST be defined :
- * 
+ *
  * NCR5380_read(register)  - read from the specified register
  *
- * NCR5380_write(register, value) - write to the specific register 
+ * NCR5380_write(register, value) - write to the specific register
  *
  * Either real DMA *or* pseudo DMA may be implemented
- * REAL functions : 
+ * REAL functions :
  * NCR5380_REAL_DMA should be defined if real DMA is to be used.
- * Note that the DMA setup functions should return the number of bytes 
+ * Note that the DMA setup functions should return the number of bytes
  *     that they were able to program the controller for.
  *
- * Also note that generic i386/PC versions of these macros are 
+ * Also note that generic i386/PC versions of these macros are
  *     available as NCR5380_i386_dma_write_setup,
  *     NCR5380_i386_dma_read_setup, and NCR5380_i386_dma_residual.
  *
  * NCR5380_pread(instance, dst, count);
  *
  * If nothing specific to this implementation needs doing (ie, with external
- * hardware), you must also define 
- *  
+ * hardware), you must also define
+ *
  * NCR5380_queue_command
  * NCR5380_reset
  * NCR5380_abort
  * NCR5380_proc_info
  *
- * to be the global entry points into the specific driver, ie 
+ * to be the global entry points into the specific driver, ie
  * #define NCR5380_queue_command t128_queue_command.
  *
  * If this is not done, the routines will be defined as static functions
  * accessible wrapper function.
  *
  * The generic driver is initialized by calling NCR5380_init(instance),
- * after setting the appropriate host specific fields and ID.  If the 
+ * after setting the appropriate host specific fields and ID.  If the
  * driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance,
  * possible) function may be used.  Before the specific driver initialization
  * code finishes, NCR5380_print_options should be called.
@@ -264,8 +272,9 @@ static struct scsi_host_template *the_template = NULL;
        (struct NCR5380_hostdata *)(in)->hostdata
 #define        HOSTDATA(in) ((struct NCR5380_hostdata *)(in)->hostdata)
 
-#define        NEXT(cmd)       ((Scsi_Cmnd *)((cmd)->host_scribble))
-#define        NEXTADDR(cmd)   ((Scsi_Cmnd **)&((cmd)->host_scribble))
+#define        NEXT(cmd)               ((Scsi_Cmnd *)(cmd)->host_scribble)
+#define        SET_NEXT(cmd,next)      ((cmd)->host_scribble = (void *)(next))
+#define        NEXTADDR(cmd)           ((Scsi_Cmnd **)&(cmd)->host_scribble)
 
 #define        HOSTNO          instance->host_no
 #define        H_NO(cmd)       (cmd)->device->host->host_no
@@ -312,34 +321,34 @@ static struct scsi_host_template *the_template = NULL;
 #define TAG_NONE 0xff
 
 typedef struct {
-    DECLARE_BITMAP(allocated, MAX_TAGS);
-    int                nr_allocated;
-    int                queue_size;
+       DECLARE_BITMAP(allocated, MAX_TAGS);
+       int nr_allocated;
+       int queue_size;
 } TAG_ALLOC;
 
-static TAG_ALLOC TagAlloc[8][8]; /* 8 targets and 8 LUNs */
+static TAG_ALLOC TagAlloc[8][8];       /* 8 targets and 8 LUNs */
 
 
-static void __init init_tags( void )
+static void __init init_tags(void)
 {
-    int target, lun;
-    TAG_ALLOC *ta;
-    
-    if (!setup_use_tagged_queuing)
-       return;
-    
-    for( target = 0; target < 8; ++target ) {
-       for( lun = 0; lun < 8; ++lun ) {
-           ta = &TagAlloc[target][lun];
-           bitmap_zero(ta->allocated, MAX_TAGS);
-           ta->nr_allocated = 0;
-           /* At the beginning, assume the maximum queue size we could
-            * support (MAX_TAGS). This value will be decreased if the target
-            * returns QUEUE_FULL status.
-            */
-           ta->queue_size = MAX_TAGS;
+       int target, lun;
+       TAG_ALLOC *ta;
+
+       if (!setup_use_tagged_queuing)
+               return;
+
+       for (target = 0; target < 8; ++target) {
+               for (lun = 0; lun < 8; ++lun) {
+                       ta = &TagAlloc[target][lun];
+                       bitmap_zero(ta->allocated, MAX_TAGS);
+                       ta->nr_allocated = 0;
+                       /* At the beginning, assume the maximum queue size we could
+                        * support (MAX_TAGS). This value will be decreased if the target
+                        * returns QUEUE_FULL status.
+                        */
+                       ta->queue_size = MAX_TAGS;
+               }
        }
-    }
 }
 
 
@@ -348,24 +357,24 @@ static void __init init_tags( void )
  * check that there is a free tag and the target's queue won't overflow. This
  * function should be called with interrupts disabled to avoid race
  * conditions.
- */ 
+ */
 
-static int is_lun_busy( Scsi_Cmnd *cmd, int should_be_tagged )
+static int is_lun_busy(Scsi_Cmnd *cmd, int should_be_tagged)
 {
-    SETUP_HOSTDATA(cmd->device->host);
-
-    if (hostdata->busy[cmd->device->id] & (1 << cmd->device->lun))
-       return( 1 );
-    if (!should_be_tagged ||
-       !setup_use_tagged_queuing || !cmd->device->tagged_supported)
-       return( 0 );
-    if (TagAlloc[cmd->device->id][cmd->device->lun].nr_allocated >=
-       TagAlloc[cmd->device->id][cmd->device->lun].queue_size ) {
-       TAG_PRINTK( "scsi%d: target %d lun %d: no free tags\n",
-                   H_NO(cmd), cmd->device->id, cmd->device->lun );
-       return( 1 );
-    }
-    return( 0 );
+       SETUP_HOSTDATA(cmd->device->host);
+
+       if (hostdata->busy[cmd->device->id] & (1 << cmd->device->lun))
+               return 1;
+       if (!should_be_tagged ||
+           !setup_use_tagged_queuing || !cmd->device->tagged_supported)
+               return 0;
+       if (TagAlloc[cmd->device->id][cmd->device->lun].nr_allocated >=
+           TagAlloc[cmd->device->id][cmd->device->lun].queue_size) {
+               TAG_PRINTK("scsi%d: target %d lun %d: no free tags\n",
+                          H_NO(cmd), cmd->device->id, cmd->device->lun);
+               return 1;
+       }
+       return 0;
 }
 
 
@@ -374,31 +383,30 @@ static int is_lun_busy( Scsi_Cmnd *cmd, int should_be_tagged )
  * untagged.
  */
 
-static void cmd_get_tag( Scsi_Cmnd *cmd, int should_be_tagged )
+static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged)
 {
-    SETUP_HOSTDATA(cmd->device->host);
-
-    /* If we or the target don't support tagged queuing, allocate the LUN for
-     * an untagged command.
-     */
-    if (!should_be_tagged ||
-       !setup_use_tagged_queuing || !cmd->device->tagged_supported) {
-       cmd->tag = TAG_NONE;
-       hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
-       TAG_PRINTK( "scsi%d: target %d lun %d now allocated by untagged "
-                   "command\n", H_NO(cmd), cmd->device->id, cmd->device->lun );
-    }
-    else {
-       TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
-
-       cmd->tag = find_first_zero_bit( ta->allocated, MAX_TAGS );
-       set_bit( cmd->tag, ta->allocated );
-       ta->nr_allocated++;
-       TAG_PRINTK( "scsi%d: using tag %d for target %d lun %d "
-                   "(now %d tags in use)\n",
-                   H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun,
-                   ta->nr_allocated );
-    }
+       SETUP_HOSTDATA(cmd->device->host);
+
+       /* If we or the target don't support tagged queuing, allocate the LUN for
+        * an untagged command.
+        */
+       if (!should_be_tagged ||
+           !setup_use_tagged_queuing || !cmd->device->tagged_supported) {
+               cmd->tag = TAG_NONE;
+               hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
+               TAG_PRINTK("scsi%d: target %d lun %d now allocated by untagged "
+                          "command\n", H_NO(cmd), cmd->device->id, cmd->device->lun);
+       } else {
+               TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+
+               cmd->tag = find_first_zero_bit(ta->allocated, MAX_TAGS);
+               set_bit(cmd->tag, ta->allocated);
+               ta->nr_allocated++;
+               TAG_PRINTK("scsi%d: using tag %d for target %d lun %d "
+                          "(now %d tags in use)\n",
+                          H_NO(cmd), cmd->tag, cmd->device->id,
+                          cmd->device->lun, ta->nr_allocated);
+       }
 }
 
 
@@ -406,44 +414,42 @@ static void cmd_get_tag( Scsi_Cmnd *cmd, int should_be_tagged )
  * unlock the LUN.
  */
 
-static void cmd_free_tag( Scsi_Cmnd *cmd )
+static void cmd_free_tag(Scsi_Cmnd *cmd)
 {
-    SETUP_HOSTDATA(cmd->device->host);
-
-    if (cmd->tag == TAG_NONE) {
-       hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
-       TAG_PRINTK( "scsi%d: target %d lun %d untagged cmd finished\n",
-                   H_NO(cmd), cmd->device->id, cmd->device->lun );
-    }
-    else if (cmd->tag >= MAX_TAGS) {
-       printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n",
-               H_NO(cmd), cmd->tag );
-    }
-    else {
-       TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
-       clear_bit( cmd->tag, ta->allocated );
-       ta->nr_allocated--;
-       TAG_PRINTK( "scsi%d: freed tag %d for target %d lun %d\n",
-                   H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun );
-    }
+       SETUP_HOSTDATA(cmd->device->host);
+
+       if (cmd->tag == TAG_NONE) {
+               hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+               TAG_PRINTK("scsi%d: target %d lun %d untagged cmd finished\n",
+                          H_NO(cmd), cmd->device->id, cmd->device->lun);
+       } else if (cmd->tag >= MAX_TAGS) {
+               printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n",
+                      H_NO(cmd), cmd->tag);
+       } else {
+               TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+               clear_bit(cmd->tag, ta->allocated);
+               ta->nr_allocated--;
+               TAG_PRINTK("scsi%d: freed tag %d for target %d lun %d\n",
+                          H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun);
+       }
 }
 
 
-static void free_all_tags( void )
+static void free_all_tags(void)
 {
-    int target, lun;
-    TAG_ALLOC *ta;
-
-    if (!setup_use_tagged_queuing)
-       return;
-    
-    for( target = 0; target < 8; ++target ) {
-       for( lun = 0; lun < 8; ++lun ) {
-           ta = &TagAlloc[target][lun];
-           bitmap_zero(ta->allocated, MAX_TAGS);
-           ta->nr_allocated = 0;
+       int target, lun;
+       TAG_ALLOC *ta;
+
+       if (!setup_use_tagged_queuing)
+               return;
+
+       for (target = 0; target < 8; ++target) {
+               for (lun = 0; lun < 8; ++lun) {
+                       ta = &TagAlloc[target][lun];
+                       bitmap_zero(ta->allocated, MAX_TAGS);
+                       ta->nr_allocated = 0;
+               }
        }
-    }
 }
 
 #endif /* SUPPORT_TAGS */
@@ -461,89 +467,94 @@ static void free_all_tags( void )
  *    assumed to be already transfered into ptr/this_residual.
  */
 
-static void merge_contiguous_buffers( Scsi_Cmnd *cmd )
+static void merge_contiguous_buffers(Scsi_Cmnd *cmd)
 {
-    unsigned long endaddr;
+       unsigned long endaddr;
 #if (NDEBUG & NDEBUG_MERGING)
-    unsigned long oldlen = cmd->SCp.this_residual;
-    int                  cnt = 1;
+       unsigned long oldlen = cmd->SCp.this_residual;
+       int cnt = 1;
 #endif
 
-    for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1;
-        cmd->SCp.buffers_residual &&
-        virt_to_phys(page_address(cmd->SCp.buffer[1].page)+
-                     cmd->SCp.buffer[1].offset) == endaddr; ) {
-       MER_PRINTK("VTOP(%p) == %08lx -> merging\n",
-                  cmd->SCp.buffer[1].address, endaddr);
+       for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1;
+            cmd->SCp.buffers_residual &&
+            virt_to_phys(page_address(cmd->SCp.buffer[1].page) +
+                         cmd->SCp.buffer[1].offset) == endaddr;) {
+               MER_PRINTK("VTOP(%p) == %08lx -> merging\n",
+                          page_address(cmd->SCp.buffer[1].page), endaddr);
 #if (NDEBUG & NDEBUG_MERGING)
-       ++cnt;
+               ++cnt;
 #endif
-       ++cmd->SCp.buffer;
-       --cmd->SCp.buffers_residual;
-       cmd->SCp.this_residual += cmd->SCp.buffer->length;
-       endaddr += cmd->SCp.buffer->length;
-    }
+               ++cmd->SCp.buffer;
+               --cmd->SCp.buffers_residual;
+               cmd->SCp.this_residual += cmd->SCp.buffer->length;
+               endaddr += cmd->SCp.buffer->length;
+       }
 #if (NDEBUG & NDEBUG_MERGING)
-    if (oldlen != cmd->SCp.this_residual)
-       MER_PRINTK("merged %d buffers from %p, new length %08x\n",
-                  cnt, cmd->SCp.ptr, cmd->SCp.this_residual);
+       if (oldlen != cmd->SCp.this_residual)
+               MER_PRINTK("merged %d buffers from %p, new length %08x\n",
+                          cnt, cmd->SCp.ptr, cmd->SCp.this_residual);
 #endif
 }
 
 /*
  * Function : void initialize_SCp(Scsi_Cmnd *cmd)
  *
- * Purpose : initialize the saved data pointers for cmd to point to the 
+ * Purpose : initialize the saved data pointers for cmd to point to the
  *     start of the buffer.
  *
  * Inputs : cmd - Scsi_Cmnd structure to have pointers reset.
  */
 
-static __inline__ void initialize_SCp(Scsi_Cmnd *cmd)
+static inline void initialize_SCp(Scsi_Cmnd *cmd)
 {
-    /* 
-     * Initialize the Scsi Pointer field so that all of the commands in the 
-     * various queues are valid.
-     */
-
-    if (cmd->use_sg) {
-       cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
-       cmd->SCp.buffers_residual = cmd->use_sg - 1;
-       cmd->SCp.ptr = (char *)page_address(cmd->SCp.buffer->page)+
-                      cmd->SCp.buffer->offset;
-       cmd->SCp.this_residual = cmd->SCp.buffer->length;
-       /* ++roman: Try to merge some scatter-buffers if they are at
-        * contiguous physical addresses.
+       /*
+        * Initialize the Scsi Pointer field so that all of the commands in the
+        * various queues are valid.
         */
-       merge_contiguous_buffers( cmd );
-    } else {
-       cmd->SCp.buffer = NULL;
-       cmd->SCp.buffers_residual = 0;
-       cmd->SCp.ptr = (char *) cmd->request_buffer;
-       cmd->SCp.this_residual = cmd->request_bufflen;
-    }
+
+       if (cmd->use_sg) {
+               cmd->SCp.buffer = (struct scatterlist *)cmd->request_buffer;
+               cmd->SCp.buffers_residual = cmd->use_sg - 1;
+               cmd->SCp.ptr = (char *)page_address(cmd->SCp.buffer->page) +
+                              cmd->SCp.buffer->offset;
+               cmd->SCp.this_residual = cmd->SCp.buffer->length;
+               /* ++roman: Try to merge some scatter-buffers if they are at
+                * contiguous physical addresses.
+                */
+               merge_contiguous_buffers(cmd);
+       } else {
+               cmd->SCp.buffer = NULL;
+               cmd->SCp.buffers_residual = 0;
+               cmd->SCp.ptr = (char *)cmd->request_buffer;
+               cmd->SCp.this_residual = cmd->request_bufflen;
+       }
 }
 
 #include <linux/delay.h>
 
 #if NDEBUG
 static struct {
-    unsigned char mask;
-    const char * name;} 
-signals[] = {{ SR_DBP, "PARITY"}, { SR_RST, "RST" }, { SR_BSY, "BSY" }, 
-    { SR_REQ, "REQ" }, { SR_MSG, "MSG" }, { SR_CD,  "CD" }, { SR_IO, "IO" }, 
-    { SR_SEL, "SEL" }, {0, NULL}}, 
-basrs[] = {{BASR_ATN, "ATN"}, {BASR_ACK, "ACK"}, {0, NULL}},
-icrs[] = {{ICR_ASSERT_RST, "ASSERT RST"},{ICR_ASSERT_ACK, "ASSERT ACK"},
-    {ICR_ASSERT_BSY, "ASSERT BSY"}, {ICR_ASSERT_SEL, "ASSERT SEL"}, 
-    {ICR_ASSERT_ATN, "ASSERT ATN"}, {ICR_ASSERT_DATA, "ASSERT DATA"}, 
-    {0, NULL}},
-mrs[] = {{MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, {MR_TARGET, "MODE TARGET"}, 
-    {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, {MR_ENABLE_PAR_INTR, 
-    "MODE PARITY INTR"}, {MR_ENABLE_EOP_INTR,"MODE EOP INTR"},
-    {MR_MONITOR_BSY, "MODE MONITOR BSY"},
-    {MR_DMA_MODE, "MODE DMA"}, {MR_ARBITRATE, "MODE ARBITRATION"}, 
-    {0, NULL}};
+       unsigned char mask;
+       const char *name;
+} signals[] = {
+       { SR_DBP, "PARITY"}, { SR_RST, "RST" }, { SR_BSY, "BSY" },
+       { SR_REQ, "REQ" }, { SR_MSG, "MSG" }, { SR_CD,  "CD" }, { SR_IO, "IO" },
+       { SR_SEL, "SEL" }, {0, NULL}
+}, basrs[] = {
+       {BASR_ATN, "ATN"}, {BASR_ACK, "ACK"}, {0, NULL}
+}, icrs[] = {
+       {ICR_ASSERT_RST, "ASSERT RST"},{ICR_ASSERT_ACK, "ASSERT ACK"},
+       {ICR_ASSERT_BSY, "ASSERT BSY"}, {ICR_ASSERT_SEL, "ASSERT SEL"},
+       {ICR_ASSERT_ATN, "ASSERT ATN"}, {ICR_ASSERT_DATA, "ASSERT DATA"},
+       {0, NULL}
+}, mrs[] = {
+       {MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, {MR_TARGET, "MODE TARGET"},
+       {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, {MR_ENABLE_PAR_INTR,
+       "MODE PARITY INTR"}, {MR_ENABLE_EOP_INTR,"MODE EOP INTR"},
+       {MR_MONITOR_BSY, "MODE MONITOR BSY"},
+       {MR_DMA_MODE, "MODE DMA"}, {MR_ARBITRATE, "MODE ARBITRATION"},
+       {0, NULL}
+};
 
 /*
  * Function : void NCR5380_print(struct Scsi_Host *instance)
@@ -553,45 +564,47 @@ mrs[] = {{MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, {MR_TARGET, "MODE TARGET"},
  * Input : instance - which NCR5380
  */
 
-static void NCR5380_print(struct Scsi_Host *instance) {
-    unsigned char status, data, basr, mr, icr, i;
-    unsigned long flags;
-
-    local_irq_save(flags);
-    data = NCR5380_read(CURRENT_SCSI_DATA_REG);
-    status = NCR5380_read(STATUS_REG);
-    mr = NCR5380_read(MODE_REG);
-    icr = NCR5380_read(INITIATOR_COMMAND_REG);
-    basr = NCR5380_read(BUS_AND_STATUS_REG);
-    local_irq_restore(flags);
-    printk("STATUS_REG: %02x ", status);
-    for (i = 0; signals[i].mask ; ++i) 
-       if (status & signals[i].mask)
-           printk(",%s", signals[i].name);
-    printk("\nBASR: %02x ", basr);
-    for (i = 0; basrs[i].mask ; ++i) 
-       if (basr & basrs[i].mask)
-           printk(",%s", basrs[i].name);
-    printk("\nICR: %02x ", icr);
-    for (i = 0; icrs[i].mask; ++i) 
-       if (icr & icrs[i].mask)
-           printk(",%s", icrs[i].name);
-    printk("\nMODE: %02x ", mr);
-    for (i = 0; mrs[i].mask; ++i) 
-       if (mr & mrs[i].mask)
-           printk(",%s", mrs[i].name);
-    printk("\n");
+static void NCR5380_print(struct Scsi_Host *instance)
+{
+       unsigned char status, data, basr, mr, icr, i;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       data = NCR5380_read(CURRENT_SCSI_DATA_REG);
+       status = NCR5380_read(STATUS_REG);
+       mr = NCR5380_read(MODE_REG);
+       icr = NCR5380_read(INITIATOR_COMMAND_REG);
+       basr = NCR5380_read(BUS_AND_STATUS_REG);
+       local_irq_restore(flags);
+       printk("STATUS_REG: %02x ", status);
+       for (i = 0; signals[i].mask; ++i)
+               if (status & signals[i].mask)
+                       printk(",%s", signals[i].name);
+       printk("\nBASR: %02x ", basr);
+       for (i = 0; basrs[i].mask; ++i)
+               if (basr & basrs[i].mask)
+                       printk(",%s", basrs[i].name);
+       printk("\nICR: %02x ", icr);
+       for (i = 0; icrs[i].mask; ++i)
+               if (icr & icrs[i].mask)
+                       printk(",%s", icrs[i].name);
+       printk("\nMODE: %02x ", mr);
+       for (i = 0; mrs[i].mask; ++i)
+               if (mr & mrs[i].mask)
+                       printk(",%s", mrs[i].name);
+       printk("\n");
 }
 
 static struct {
-    unsigned char value;
-    const char *name;
+       unsigned char value;
+       const char *name;
 } phases[] = {
-    {PHASE_DATAOUT, "DATAOUT"}, {PHASE_DATAIN, "DATAIN"}, {PHASE_CMDOUT, "CMDOUT"},
-    {PHASE_STATIN, "STATIN"}, {PHASE_MSGOUT, "MSGOUT"}, {PHASE_MSGIN, "MSGIN"},
-    {PHASE_UNKNOWN, "UNKNOWN"}};
+       {PHASE_DATAOUT, "DATAOUT"}, {PHASE_DATAIN, "DATAIN"}, {PHASE_CMDOUT, "CMDOUT"},
+       {PHASE_STATIN, "STATIN"}, {PHASE_MSGOUT, "MSGOUT"}, {PHASE_MSGIN, "MSGIN"},
+       {PHASE_UNKNOWN, "UNKNOWN"}
+};
 
-/* 
+/*
  * Function : void NCR5380_print_phase(struct Scsi_Host *instance)
  *
  * Purpose : print the current SCSI phase for debugging purposes
@@ -601,30 +614,35 @@ static struct {
 
 static void NCR5380_print_phase(struct Scsi_Host *instance)
 {
-    unsigned char status;
-    int i;
-
-    status = NCR5380_read(STATUS_REG);
-    if (!(status & SR_REQ)) 
-       printk(KERN_DEBUG "scsi%d: REQ not asserted, phase unknown.\n", HOSTNO);
-    else {
-       for (i = 0; (phases[i].value != PHASE_UNKNOWN) && 
-           (phases[i].value != (status & PHASE_MASK)); ++i); 
-       printk(KERN_DEBUG "scsi%d: phase %s\n", HOSTNO, phases[i].name);
-    }
+       unsigned char status;
+       int i;
+
+       status = NCR5380_read(STATUS_REG);
+       if (!(status & SR_REQ))
+               printk(KERN_DEBUG "scsi%d: REQ not asserted, phase unknown.\n", HOSTNO);
+       else {
+               for (i = 0; (phases[i].value != PHASE_UNKNOWN) &&
+                    (phases[i].value != (status & PHASE_MASK)); ++i)
+                       ;
+               printk(KERN_DEBUG "scsi%d: phase %s\n", HOSTNO, phases[i].name);
+       }
 }
 
 #else /* !NDEBUG */
 
 /* dummies... */
-__inline__ void NCR5380_print(struct Scsi_Host *instance) { };
-__inline__ void NCR5380_print_phase(struct Scsi_Host *instance) { };
+static inline void NCR5380_print(struct Scsi_Host *instance)
+{
+};
+static inline void NCR5380_print_phase(struct Scsi_Host *instance)
+{
+};
 
 #endif
 
 /*
  * ++roman: New scheme of calling NCR5380_main()
- * 
+ *
  * If we're not in an interrupt, we can call our main directly, it cannot be
  * already running. Else, we queue it on a task queue, if not 'main_running'
  * tells us that a lower level is already executing it. This way,
@@ -638,33 +656,33 @@ __inline__ void NCR5380_print_phase(struct Scsi_Host *instance) { };
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
 
-static volatile int main_running = 0;
-static DECLARE_WORK(NCR5380_tqueue, (void (*)(void*))NCR5380_main, NULL);
+static volatile int main_running;
+static DECLARE_WORK(NCR5380_tqueue, NCR5380_main);
 
-static __inline__ void queue_main(void)
+static inline void queue_main(void)
 {
-    if (!main_running) {
-       /* If in interrupt and NCR5380_main() not already running,
-          queue it on the 'immediate' task queue, to be processed
-          immediately after the current interrupt processing has
-          finished. */
-       schedule_work(&NCR5380_tqueue);
-    }
-    /* else: nothing to do: the running NCR5380_main() will pick up
-       any newly queued command. */
+       if (!main_running) {
+               /* If in interrupt and NCR5380_main() not already running,
+                  queue it on the 'immediate' task queue, to be processed
+                  immediately after the current interrupt processing has
+                  finished. */
+               schedule_work(&NCR5380_tqueue);
+       }
+       /* else: nothing to do: the running NCR5380_main() will pick up
+          any newly queued command. */
 }
 
 
-static inline void NCR5380_all_init (void)
+static inline void NCR5380_all_init(void)
 {
-    static int done = 0;
-    if (!done) {
-       INI_PRINTK("scsi : NCR5380_all_init()\n");
-       done = 1;
-    }
+       static int done = 0;
+       if (!done) {
+               INI_PRINTK("scsi : NCR5380_all_init()\n");
+               done = 1;
+       }
 }
 
+
 /*
  * Function : void NCR58380_print_options (struct Scsi_Host *instance)
  *
@@ -674,23 +692,23 @@ static inline void NCR5380_all_init (void)
  * Inputs : instance, pointer to this instance.  Unused.
  */
 
-static void __init NCR5380_print_options (struct Scsi_Host *instance)
+static void __init NCR5380_print_options(struct Scsi_Host *instance)
 {
-    printk(" generic options"
-#ifdef AUTOSENSE 
-    " AUTOSENSE"
+       printk(" generic options"
+#ifdef AUTOSENSE
+              " AUTOSENSE"
 #endif
 #ifdef REAL_DMA
-    " REAL DMA"
+              " REAL DMA"
 #endif
 #ifdef PARITY
-    " PARITY"
+              " PARITY"
 #endif
 #ifdef SUPPORT_TAGS
-    " SCSI-2 TAGGED QUEUING"
+              " SCSI-2 TAGGED QUEUING"
 #endif
-    );
-    printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);
+              );
+       printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);
 }
 
 /*
@@ -699,27 +717,27 @@ static void __init NCR5380_print_options (struct Scsi_Host *instance)
  * Purpose : print commands in the various queues, called from
  *     NCR5380_abort and NCR5380_debug to aid debugging.
  *
- * Inputs : instance, pointer to this instance.  
+ * Inputs : instance, pointer to this instance.
  */
 
-static void NCR5380_print_status (struct Scsi_Host *instance)
+static void NCR5380_print_status(struct Scsi_Host *instance)
 {
-    char *pr_bfr;
-    char *start;
-    int len;
-
-    NCR_PRINT(NDEBUG_ANY);
-    NCR_PRINT_PHASE(NDEBUG_ANY);
-
-    pr_bfr = (char *) __get_free_page(GFP_ATOMIC);
-    if (!pr_bfr) {
-       printk("NCR5380_print_status: no memory for print buffer\n");
-       return;
-    }
-    len = NCR5380_proc_info(pr_bfr, &start, 0, PAGE_SIZE, HOSTNO, 0);
-    pr_bfr[len] = 0;
-    printk("\n%s\n", pr_bfr);
-    free_page((unsigned long) pr_bfr);
+       char *pr_bfr;
+       char *start;
+       int len;
+
+       NCR_PRINT(NDEBUG_ANY);
+       NCR_PRINT_PHASE(NDEBUG_ANY);
+
+       pr_bfr = (char *)__get_free_page(GFP_ATOMIC);
+       if (!pr_bfr) {
+               printk("NCR5380_print_status: no memory for print buffer\n");
+               return;
+       }
+       len = NCR5380_proc_info(instance, pr_bfr, &start, 0, PAGE_SIZE, 0);
+       pr_bfr[len] = 0;
+       printk("\n%s\n", pr_bfr);
+       free_page((unsigned long)pr_bfr);
 }
 
 
@@ -738,443 +756,478 @@ static void NCR5380_print_status (struct Scsi_Host *instance)
 */
 
 #undef SPRINTF
-#define SPRINTF(fmt,args...) \
-  do { if (pos + strlen(fmt) + 20 /* slop */ < buffer + length) \
-        pos += sprintf(pos, fmt , ## args); } while(0)
-static
-char *lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length);
-
-static
-int NCR5380_proc_info (struct Scsi_Host *instance, char *buffer, char **start, off_t offset,
-                      int length, int inout)
+#define SPRINTF(fmt,args...)                                                   \
+       do {                                                                    \
+               if (pos + strlen(fmt) + 20 /* slop */ < buffer + length)        \
+                       pos += sprintf(pos, fmt , ## args);                     \
+       } while(0)
+static char *lprint_Scsi_Cmnd(Scsi_Cmnd *cmd, char *pos, char *buffer, int length);
+
+static int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer,
+                            char **start, off_t offset, int length, int inout)
 {
-    char *pos = buffer;
-    struct NCR5380_hostdata *hostdata;
-    Scsi_Cmnd *ptr;
-    unsigned long flags;
-    off_t begin = 0;
-#define check_offset()                         \
-    do {                                       \
-       if (pos - buffer < offset - begin) {    \
-           begin += pos - buffer;              \
-           pos = buffer;                       \
-       }                                       \
-    } while (0)
-
-    hostdata = (struct NCR5380_hostdata *)instance->hostdata;
-
-    if (inout) { /* Has data been written to the file ? */
-       return(-ENOSYS);  /* Currently this is a no-op */
-    }
-    SPRINTF("NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
-    check_offset();
-    local_irq_save(flags);
-    SPRINTF("NCR5380: coroutine is%s running.\n", main_running ? "" : "n't");
-    check_offset();
-    if (!hostdata->connected)
-       SPRINTF("scsi%d: no currently connected command\n", HOSTNO);
-    else
-       pos = lprint_Scsi_Cmnd ((Scsi_Cmnd *) hostdata->connected,
-                               pos, buffer, length);
-    SPRINTF("scsi%d: issue_queue\n", HOSTNO);
-    check_offset();
-    for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = NEXT(ptr)) {
-       pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length);
+       char *pos = buffer;
+       struct NCR5380_hostdata *hostdata;
+       Scsi_Cmnd *ptr;
+       unsigned long flags;
+       off_t begin = 0;
+#define check_offset()                                 \
+       do {                                            \
+               if (pos - buffer < offset - begin) {    \
+                       begin += pos - buffer;          \
+                       pos = buffer;                   \
+               }                                       \
+       } while (0)
+
+       hostdata = (struct NCR5380_hostdata *)instance->hostdata;
+
+       if (inout)                      /* Has data been written to the file ? */
+               return -ENOSYS;         /* Currently this is a no-op */
+       SPRINTF("NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
        check_offset();
-    }
+       local_irq_save(flags);
+       SPRINTF("NCR5380: coroutine is%s running.\n",
+               main_running ? "" : "n't");
+       check_offset();
+       if (!hostdata->connected)
+               SPRINTF("scsi%d: no currently connected command\n", HOSTNO);
+       else
+               pos = lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected,
+                                      pos, buffer, length);
+       SPRINTF("scsi%d: issue_queue\n", HOSTNO);
+       check_offset();
+       for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr)) {
+               pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
+               check_offset();
+       }
 
-    SPRINTF("scsi%d: disconnected_queue\n", HOSTNO);
-    check_offset();
-    for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
-        ptr = NEXT(ptr)) {
-       pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length);
+       SPRINTF("scsi%d: disconnected_queue\n", HOSTNO);
        check_offset();
-    }
+       for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
+            ptr = NEXT(ptr)) {
+               pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
+               check_offset();
+       }
 
-    local_irq_restore(flags);
-    *start = buffer + (offset - begin);
-    if (pos - buffer < offset - begin)
-       return 0;
-    else if (pos - buffer - (offset - begin) < length)
-       return pos - buffer - (offset - begin);
-    return length;
+       local_irq_restore(flags);
+       *start = buffer + (offset - begin);
+       if (pos - buffer < offset - begin)
+               return 0;
+       else if (pos - buffer - (offset - begin) < length)
+               return pos - buffer - (offset - begin);
+       return length;
 }
 
-static char *
-lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length)
+static char *lprint_Scsi_Cmnd(Scsi_Cmnd *cmd, char *pos, char *buffer, int length)
 {
-    int i, s;
-    unsigned char *command;
-    SPRINTF("scsi%d: destination target %d, lun %d\n",
-           H_NO(cmd), cmd->device->id, cmd->device->lun);
-    SPRINTF("        command = ");
-    command = cmd->cmnd;
-    SPRINTF("%2d (0x%02x)", command[0], command[0]);
-    for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
-       SPRINTF(" %02x", command[i]);
-    SPRINTF("\n");
-    return pos;
+       int i, s;
+       unsigned char *command;
+       SPRINTF("scsi%d: destination target %d, lun %d\n",
+               H_NO(cmd), cmd->device->id, cmd->device->lun);
+       SPRINTF("        command = ");
+       command = cmd->cmnd;
+       SPRINTF("%2d (0x%02x)", command[0], command[0]);
+       for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
+               SPRINTF(" %02x", command[i]);
+       SPRINTF("\n");
+       return pos;
 }
 
 
-/* 
+/*
  * Function : void NCR5380_init (struct Scsi_Host *instance)
  *
  * Purpose : initializes *instance and corresponding 5380 chip.
  *
- * Inputs : instance - instantiation of the 5380 driver.  
+ * Inputs : instance - instantiation of the 5380 driver.
  *
  * Notes : I assume that the host, hostno, and id bits have been
- *     set correctly.  I don't care about the irq and other fields. 
- * 
+ *     set correctly.  I don't care about the irq and other fields.
+ *
  */
 
-static int NCR5380_init (struct Scsi_Host *instance, int flags)
+static int NCR5380_init(struct Scsi_Host *instance, int flags)
 {
-    int i;
-    SETUP_HOSTDATA(instance);
-
-    NCR5380_all_init();
-
-    hostdata->aborted = 0;
-    hostdata->id_mask = 1 << instance->this_id;
-    hostdata->id_higher_mask = 0;
-    for (i = hostdata->id_mask; i <= 0x80; i <<= 1)
-       if (i > hostdata->id_mask)
-           hostdata->id_higher_mask |= i;
-    for (i = 0; i < 8; ++i)
-       hostdata->busy[i] = 0;
+       int i;
+       SETUP_HOSTDATA(instance);
+
+       NCR5380_all_init();
+
+       hostdata->aborted = 0;
+       hostdata->id_mask = 1 << instance->this_id;
+       hostdata->id_higher_mask = 0;
+       for (i = hostdata->id_mask; i <= 0x80; i <<= 1)
+               if (i > hostdata->id_mask)
+                       hostdata->id_higher_mask |= i;
+       for (i = 0; i < 8; ++i)
+               hostdata->busy[i] = 0;
 #ifdef SUPPORT_TAGS
-    init_tags();
+       init_tags();
 #endif
 #if defined (REAL_DMA)
-    hostdata->dma_len = 0;
+       hostdata->dma_len = 0;
 #endif
-    hostdata->targets_present = 0;
-    hostdata->connected = NULL;
-    hostdata->issue_queue = NULL;
-    hostdata->disconnected_queue = NULL;
-    hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT;
-
-    if (!the_template) {
-       the_template = instance->hostt;
-       first_instance = instance;
-    }
-       
+       hostdata->targets_present = 0;
+       hostdata->connected = NULL;
+       hostdata->issue_queue = NULL;
+       hostdata->disconnected_queue = NULL;
+       hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT;
+
+       if (!the_template) {
+               the_template = instance->hostt;
+               first_instance = instance;
+       }
 
 #ifndef AUTOSENSE
-    if ((instance->cmd_per_lun > 1) || (instance->can_queue > 1))
-        printk("scsi%d: WARNING : support for multiple outstanding commands enabled\n"
-               "        without AUTOSENSE option, contingent allegiance conditions may\n"
-               "        be incorrectly cleared.\n", HOSTNO);
+       if ((instance->cmd_per_lun > 1) || (instance->can_queue > 1))
+               printk("scsi%d: WARNING : support for multiple outstanding commands enabled\n"
+                      "        without AUTOSENSE option, contingent allegiance conditions may\n"
+                      "        be incorrectly cleared.\n", HOSTNO);
 #endif /* def AUTOSENSE */
 
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-    NCR5380_write(MODE_REG, MR_BASE);
-    NCR5380_write(TARGET_COMMAND_REG, 0);
-    NCR5380_write(SELECT_ENABLE_REG, 0);
+       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+       NCR5380_write(MODE_REG, MR_BASE);
+       NCR5380_write(TARGET_COMMAND_REG, 0);
+       NCR5380_write(SELECT_ENABLE_REG, 0);
 
-    return 0;
+       return 0;
 }
 
-/* 
- * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd, 
- *     void (*done)(Scsi_Cmnd *)) 
+/*
+ * our own old-style timeout update
+ */
+/*
+ * The strategy is to cause the timer code to call scsi_times_out()
+ * when the soonest timeout is pending.
+ * The arguments are used when we are queueing a new command, because
+ * we do not want to subtract the time used from this time, but when we
+ * set the timer, we want to take this value into account.
+ */
+
+int atari_scsi_update_timeout(Scsi_Cmnd * SCset, int timeout)
+{
+       int rtn;
+
+       /*
+        * We are using the new error handling code to actually register/deregister
+        * timers for timeout.
+        */
+
+       if (!timer_pending(&SCset->eh_timeout))
+               rtn = 0;
+       else
+               rtn = SCset->eh_timeout.expires - jiffies;
+
+       if (timeout == 0) {
+               del_timer(&SCset->eh_timeout);
+               SCset->eh_timeout.data = (unsigned long)NULL;
+               SCset->eh_timeout.expires = 0;
+       } else {
+               if (SCset->eh_timeout.data != (unsigned long)NULL)
+                       del_timer(&SCset->eh_timeout);
+               SCset->eh_timeout.data = (unsigned long)SCset;
+               SCset->eh_timeout.expires = jiffies + timeout;
+               add_timer(&SCset->eh_timeout);
+       }
+       return rtn;
+}
+
+/*
+ * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd,
+ *     void (*done)(Scsi_Cmnd *))
  *
  * Purpose :  enqueues a SCSI command
  *
  * Inputs : cmd - SCSI command, done - function called on completion, with
  *     a pointer to the command descriptor.
- * 
+ *
  * Returns : 0
  *
- * Side effects : 
- *      cmd is added to the per instance issue_queue, with minor 
- *     twiddling done to the host specific fields of cmd.  If the 
+ * Side effects :
+ *      cmd is added to the per instance issue_queue, with minor
+ *     twiddling done to the host specific fields of cmd.  If the
  *     main coroutine is not running, it is restarted.
  *
  */
 
-static
-int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
+static int NCR5380_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
 {
-    SETUP_HOSTDATA(cmd->device->host);
-    Scsi_Cmnd *tmp;
-    int oldto;
-    unsigned long flags;
-    extern int update_timeout(Scsi_Cmnd * SCset, int timeout);
+       SETUP_HOSTDATA(cmd->device->host);
+       Scsi_Cmnd *tmp;
+       int oldto;
+       unsigned long flags;
+       // extern int update_timeout(Scsi_Cmnd * SCset, int timeout);
 
 #if (NDEBUG & NDEBUG_NO_WRITE)
-    switch (cmd->cmnd[0]) {
-    case WRITE_6:
-    case WRITE_10:
-       printk(KERN_NOTICE "scsi%d: WRITE attempted with NO_WRITE debugging flag set\n",
-              H_NO(cmd));
-       cmd->result = (DID_ERROR << 16);
-       done(cmd);
-       return 0;
-    }
+       switch (cmd->cmnd[0]) {
+       case WRITE_6:
+       case WRITE_10:
+               printk(KERN_NOTICE "scsi%d: WRITE attempted with NO_WRITE debugging flag set\n",
+                      H_NO(cmd));
+               cmd->result = (DID_ERROR << 16);
+               done(cmd);
+               return 0;
+       }
 #endif /* (NDEBUG & NDEBUG_NO_WRITE) */
 
-
 #ifdef NCR5380_STATS
 # if 0
-    if (!hostdata->connected && !hostdata->issue_queue &&
-       !hostdata->disconnected_queue) {
-       hostdata->timebase = jiffies;
-    }
+       if (!hostdata->connected && !hostdata->issue_queue &&
+           !hostdata->disconnected_queue) {
+               hostdata->timebase = jiffies;
+       }
 # endif
 # ifdef NCR5380_STAT_LIMIT
-    if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
+       if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
 # endif
-       switch (cmd->cmnd[0])
-       {
-           case WRITE:
-           case WRITE_6:
-           case WRITE_10:
-               hostdata->time_write[cmd->device->id] -= (jiffies - hostdata->timebase);
-               hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen;
-               hostdata->pendingw++;
-               break;
-           case READ:
-           case READ_6:
-           case READ_10:
-               hostdata->time_read[cmd->device->id] -= (jiffies - hostdata->timebase);
-               hostdata->bytes_read[cmd->device->id] += cmd->request_bufflen;
-               hostdata->pendingr++;
-               break;
-       }
+               switch (cmd->cmnd[0]) {
+               case WRITE:
+               case WRITE_6:
+               case WRITE_10:
+                       hostdata->time_write[cmd->device->id] -= (jiffies - hostdata->timebase);
+                       hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen;
+                       hostdata->pendingw++;
+                       break;
+               case READ:
+               case READ_6:
+               case READ_10:
+                       hostdata->time_read[cmd->device->id] -= (jiffies - hostdata->timebase);
+                       hostdata->bytes_read[cmd->device->id] += cmd->request_bufflen;
+                       hostdata->pendingr++;
+                       break;
+               }
 #endif
 
-    /* 
-     * We use the host_scribble field as a pointer to the next command  
-     * in a queue 
-     */
-
-    NEXT(cmd) = NULL;
-    cmd->scsi_done = done;
-
-    cmd->result = 0;
-
-
-    /* 
-     * Insert the cmd into the issue queue. Note that REQUEST SENSE 
-     * commands are added to the head of the queue since any command will
-     * clear the contingent allegiance condition that exists and the 
-     * sense data is only guaranteed to be valid while the condition exists.
-     */
-
-    local_irq_save(flags);
-    /* ++guenther: now that the issue queue is being set up, we can lock ST-DMA.
-     * Otherwise a running NCR5380_main may steal the lock.
-     * Lock before actually inserting due to fairness reasons explained in
-     * atari_scsi.c. If we insert first, then it's impossible for this driver
-     * to release the lock.
-     * Stop timer for this command while waiting for the lock, or timeouts
-     * may happen (and they really do), and it's no good if the command doesn't
-     * appear in any of the queues.
-     * ++roman: Just disabling the NCR interrupt isn't sufficient here,
-     * because also a timer int can trigger an abort or reset, which would
-     * alter queues and touch the lock.
-     */
-    if (!IS_A_TT()) {
-       oldto = update_timeout(cmd, 0);
-       falcon_get_lock();
-       update_timeout(cmd, oldto);
-    }
-    if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
-       LIST(cmd, hostdata->issue_queue);
-       NEXT(cmd) = hostdata->issue_queue;
-       hostdata->issue_queue = cmd;
-    } else {
-       for (tmp = (Scsi_Cmnd *)hostdata->issue_queue;
-            NEXT(tmp); tmp = NEXT(tmp))
-           ;
-       LIST(cmd, tmp);
-       NEXT(tmp) = cmd;
-    }
-    local_irq_restore(flags);
-
-    QU_PRINTK("scsi%d: command added to %s of queue\n", H_NO(cmd),
-             (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
-
-    /* If queue_command() is called from an interrupt (real one or bottom
-     * half), we let queue_main() do the job of taking care about main. If it
-     * is already running, this is a no-op, else main will be queued.
-     *
-     * If we're not in an interrupt, we can call NCR5380_main()
-     * unconditionally, because it cannot be already running.
-     */
-    if (in_interrupt() || ((flags >> 8) & 7) >= 6)
-       queue_main();
-    else
-       NCR5380_main(NULL);
-    return 0;
+       /*
+        * We use the host_scribble field as a pointer to the next command
+        * in a queue
+        */
+
+       SET_NEXT(cmd, NULL);
+       cmd->scsi_done = done;
+
+       cmd->result = 0;
+
+       /*
+        * Insert the cmd into the issue queue. Note that REQUEST SENSE
+        * commands are added to the head of the queue since any command will
+        * clear the contingent allegiance condition that exists and the
+        * sense data is only guaranteed to be valid while the condition exists.
+        */
+
+       local_irq_save(flags);
+       /* ++guenther: now that the issue queue is being set up, we can lock ST-DMA.
+        * Otherwise a running NCR5380_main may steal the lock.
+        * Lock before actually inserting due to fairness reasons explained in
+        * atari_scsi.c. If we insert first, then it's impossible for this driver
+        * to release the lock.
+        * Stop timer for this command while waiting for the lock, or timeouts
+        * may happen (and they really do), and it's no good if the command doesn't
+        * appear in any of the queues.
+        * ++roman: Just disabling the NCR interrupt isn't sufficient here,
+        * because also a timer int can trigger an abort or reset, which would
+        * alter queues and touch the lock.
+        */
+       if (!IS_A_TT()) {
+               oldto = atari_scsi_update_timeout(cmd, 0);
+               falcon_get_lock();
+               atari_scsi_update_timeout(cmd, oldto);
+       }
+       if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
+               LIST(cmd, hostdata->issue_queue);
+               SET_NEXT(cmd, hostdata->issue_queue);
+               hostdata->issue_queue = cmd;
+       } else {
+               for (tmp = (Scsi_Cmnd *)hostdata->issue_queue;
+                    NEXT(tmp); tmp = NEXT(tmp))
+                       ;
+               LIST(cmd, tmp);
+               SET_NEXT(tmp, cmd);
+       }
+       local_irq_restore(flags);
+
+       QU_PRINTK("scsi%d: command added to %s of queue\n", H_NO(cmd),
+                 (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
+
+       /* If queue_command() is called from an interrupt (real one or bottom
+        * half), we let queue_main() do the job of taking care about main. If it
+        * is already running, this is a no-op, else main will be queued.
+        *
+        * If we're not in an interrupt, we can call NCR5380_main()
+        * unconditionally, because it cannot be already running.
+        */
+       if (in_interrupt() || ((flags >> 8) & 7) >= 6)
+               queue_main();
+       else
+               NCR5380_main(NULL);
+       return 0;
 }
 
 /*
- * Function : NCR5380_main (void) 
+ * Function : NCR5380_main (void)
  *
- * Purpose : NCR5380_main is a coroutine that runs as long as more work can 
- *     be done on the NCR5380 host adapters in a system.  Both 
- *     NCR5380_queue_command() and NCR5380_intr() will try to start it 
+ * Purpose : NCR5380_main is a coroutine that runs as long as more work can
+ *     be done on the NCR5380 host adapters in a system.  Both
+ *     NCR5380_queue_command() and NCR5380_intr() will try to start it
  *     in case it is not running.
- * 
- * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should 
+ *
+ * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should
  *  reenable them.  This prevents reentrancy and kernel stack overflow.
- */    
-    
-static void NCR5380_main (void *bl)
+ */
+
+static void NCR5380_main(struct work_struct *work)
 {
-    Scsi_Cmnd *tmp, *prev;
-    struct Scsi_Host *instance = first_instance;
-    struct NCR5380_hostdata *hostdata = HOSTDATA(instance);
-    int done;
-    unsigned long flags;
-    
-    /*
-     * We run (with interrupts disabled) until we're sure that none of 
-     * the host adapters have anything that can be done, at which point 
-     * we set main_running to 0 and exit.
-     *
-     * Interrupts are enabled before doing various other internal 
-     * instructions, after we've decided that we need to run through
-     * the loop again.
-     *
-     * this should prevent any race conditions.
-     * 
-     * ++roman: Just disabling the NCR interrupt isn't sufficient here,
-     * because also a timer int can trigger an abort or reset, which can
-     * alter queues and touch the Falcon lock.
-     */
-
-    /* Tell int handlers main() is now already executing.  Note that
-       no races are possible here. If an int comes in before
-       'main_running' is set here, and queues/executes main via the
-       task queue, it doesn't do any harm, just this instance of main
-       won't find any work left to do. */
-    if (main_running)
-       return;
-    main_running = 1;
-
-    local_save_flags(flags);
-    do {
-       local_irq_disable(); /* Freeze request queues */
-       done = 1;
-       
-       if (!hostdata->connected) {
-           MAIN_PRINTK( "scsi%d: not connected\n", HOSTNO );
-           /*
-            * Search through the issue_queue for a command destined
-            * for a target that's not busy.
-            */
+       Scsi_Cmnd *tmp, *prev;
+       struct Scsi_Host *instance = first_instance;
+       struct NCR5380_hostdata *hostdata = HOSTDATA(instance);
+       int done;
+       unsigned long flags;
+
+       /*
+        * We run (with interrupts disabled) until we're sure that none of
+        * the host adapters have anything that can be done, at which point
+        * we set main_running to 0 and exit.
+        *
+        * Interrupts are enabled before doing various other internal
+        * instructions, after we've decided that we need to run through
+        * the loop again.
+        *
+        * this should prevent any race conditions.
+        *
+        * ++roman: Just disabling the NCR interrupt isn't sufficient here,
+        * because also a timer int can trigger an abort or reset, which can
+        * alter queues and touch the Falcon lock.
+        */
+
+       /* Tell int handlers main() is now already executing.  Note that
+          no races are possible here. If an int comes in before
+          'main_running' is set here, and queues/executes main via the
+          task queue, it doesn't do any harm, just this instance of main
+          won't find any work left to do. */
+       if (main_running)
+               return;
+       main_running = 1;
+
+       local_save_flags(flags);
+       do {
+               local_irq_disable();    /* Freeze request queues */
+               done = 1;
+
+               if (!hostdata->connected) {
+                       MAIN_PRINTK("scsi%d: not connected\n", HOSTNO);
+                       /*
+                        * Search through the issue_queue for a command destined
+                        * for a target that's not busy.
+                        */
 #if (NDEBUG & NDEBUG_LISTS)
-           for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL;
-                tmp && (tmp != prev); prev = tmp, tmp = NEXT(tmp))
-               ;
-               /*printk("%p  ", tmp);*/
-           if ((tmp == prev) && tmp) printk(" LOOP\n");/* else printk("\n");*/
+                       for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL;
+                            tmp && (tmp != prev); prev = tmp, tmp = NEXT(tmp))
+                               ;
+                       /*printk("%p  ", tmp);*/
+                       if ((tmp == prev) && tmp)
+                               printk(" LOOP\n");
+                       /* else printk("\n"); */
 #endif
-           for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, 
-                prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp) ) {
+                       for (tmp = (Scsi_Cmnd *) hostdata->issue_queue,
+                            prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp)) {
 
 #if (NDEBUG & NDEBUG_LISTS)
-               if (prev != tmp)
-                   printk("MAIN tmp=%p   target=%d   busy=%d lun=%d\n",
-                          tmp, tmp->device->id, hostdata->busy[tmp->device->id],
-                          tmp->device->lun);
+                               if (prev != tmp)
+                                       printk("MAIN tmp=%p   target=%d   busy=%d lun=%d\n",
+                                              tmp, tmp->device->id, hostdata->busy[tmp->device->id],
+                                              tmp->device->lun);
 #endif
-               /*  When we find one, remove it from the issue queue. */
-               /* ++guenther: possible race with Falcon locking */
-               if (
+                               /*  When we find one, remove it from the issue queue. */
+                               /* ++guenther: possible race with Falcon locking */
+                               if (
 #ifdef SUPPORT_TAGS
-                   !is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE)
+                                   !is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE)
 #else
-                   !(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun))
+                                   !(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun))
 #endif
-                   ) {
-                   /* ++guenther: just to be sure, this must be atomic */
-                   local_irq_disable();
-                   if (prev) {
-                       REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
-                       NEXT(prev) = NEXT(tmp);
-                   } else {
-                       REMOVE(-1, hostdata->issue_queue, tmp, NEXT(tmp));
-                       hostdata->issue_queue = NEXT(tmp);
-                   }
-                   NEXT(tmp) = NULL;
-                   falcon_dont_release++;
-                   
-                   /* reenable interrupts after finding one */
-                   local_irq_restore(flags);
-                   
-                   /* 
-                    * Attempt to establish an I_T_L nexus here. 
-                    * On success, instance->hostdata->connected is set.
-                    * On failure, we must add the command back to the
-                    *   issue queue so we can keep trying.     
-                    */
-                   MAIN_PRINTK("scsi%d: main(): command for target %d "
-                               "lun %d removed from issue_queue\n",
-                               HOSTNO, tmp->device->id, tmp->device->lun);
-                   /* 
-                    * REQUEST SENSE commands are issued without tagged
-                    * queueing, even on SCSI-II devices because the 
-                    * contingent allegiance condition exists for the 
-                    * entire unit.
-                    */
-                   /* ++roman: ...and the standard also requires that
-                    * REQUEST SENSE command are untagged.
-                    */
-                   
+                                   ) {
+                                       /* ++guenther: just to be sure, this must be atomic */
+                                       local_irq_disable();
+                                       if (prev) {
+                                               REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
+                                               SET_NEXT(prev, NEXT(tmp));
+                                       } else {
+                                               REMOVE(-1, hostdata->issue_queue, tmp, NEXT(tmp));
+                                               hostdata->issue_queue = NEXT(tmp);
+                                       }
+                                       SET_NEXT(tmp, NULL);
+                                       falcon_dont_release++;
+
+                                       /* reenable interrupts after finding one */
+                                       local_irq_restore(flags);
+
+                                       /*
+                                        * Attempt to establish an I_T_L nexus here.
+                                        * On success, instance->hostdata->connected is set.
+                                        * On failure, we must add the command back to the
+                                        *   issue queue so we can keep trying.
+                                        */
+                                       MAIN_PRINTK("scsi%d: main(): command for target %d "
+                                                   "lun %d removed from issue_queue\n",
+                                                   HOSTNO, tmp->device->id, tmp->device->lun);
+                                       /*
+                                        * REQUEST SENSE commands are issued without tagged
+                                        * queueing, even on SCSI-II devices because the
+                                        * contingent allegiance condition exists for the
+                                        * entire unit.
+                                        */
+                                       /* ++roman: ...and the standard also requires that
+                                        * REQUEST SENSE command are untagged.
+                                        */
+
 #ifdef SUPPORT_TAGS
-                   cmd_get_tag( tmp, tmp->cmnd[0] != REQUEST_SENSE );
+                                       cmd_get_tag(tmp, tmp->cmnd[0] != REQUEST_SENSE);
 #endif
-                   if (!NCR5380_select(instance, tmp, 
-                           (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : 
-                           TAG_NEXT)) {
-                       falcon_dont_release--;
-                       /* release if target did not response! */
-                       falcon_release_lock_if_possible( hostdata );
-                       break;
-                   } else {
-                       local_irq_disable();
-                       LIST(tmp, hostdata->issue_queue);
-                       NEXT(tmp) = hostdata->issue_queue;
-                       hostdata->issue_queue = tmp;
+                                       if (!NCR5380_select(instance, tmp,
+                                           (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE :
+                                           TAG_NEXT)) {
+                                               falcon_dont_release--;
+                                               /* release if target did not response! */
+                                               falcon_release_lock_if_possible(hostdata);
+                                               break;
+                                       } else {
+                                               local_irq_disable();
+                                               LIST(tmp, hostdata->issue_queue);
+                                               SET_NEXT(tmp, hostdata->issue_queue);
+                                               hostdata->issue_queue = tmp;
 #ifdef SUPPORT_TAGS
-                       cmd_free_tag( tmp );
+                                               cmd_free_tag(tmp);
 #endif
-                       falcon_dont_release--;
-                       local_irq_restore(flags);
-                       MAIN_PRINTK("scsi%d: main(): select() failed, "
-                                   "returned to issue_queue\n", HOSTNO);
-                       if (hostdata->connected)
-                           break;
-                   }
-               } /* if target/lun/target queue is not busy */
-           } /* for issue_queue */
-       } /* if (!hostdata->connected) */
-               
-       if (hostdata->connected 
+                                               falcon_dont_release--;
+                                               local_irq_restore(flags);
+                                               MAIN_PRINTK("scsi%d: main(): select() failed, "
+                                                           "returned to issue_queue\n", HOSTNO);
+                                               if (hostdata->connected)
+                                                       break;
+                                       }
+                               } /* if target/lun/target queue is not busy */
+                       } /* for issue_queue */
+               } /* if (!hostdata->connected) */
+
+               if (hostdata->connected
 #ifdef REAL_DMA
-           && !hostdata->dma_len
+                   && !hostdata->dma_len
 #endif
-           ) {
-           local_irq_restore(flags);
-           MAIN_PRINTK("scsi%d: main: performing information transfer\n",
-                       HOSTNO);
-           NCR5380_information_transfer(instance);
-           MAIN_PRINTK("scsi%d: main: done set false\n", HOSTNO);
-           done = 0;
-       }
-    } while (!done);
+                   ) {
+                       local_irq_restore(flags);
+                       MAIN_PRINTK("scsi%d: main: performing information transfer\n",
+                                   HOSTNO);
+                       NCR5380_information_transfer(instance);
+                       MAIN_PRINTK("scsi%d: main: done set false\n", HOSTNO);
+                       done = 0;
+               }
+       } while (!done);
 
-    /* Better allow ints _after_ 'main_running' has been cleared, else
-       an interrupt could believe we'll pick up the work it left for
-       us, but we won't see it anymore here... */
-    main_running = 0;
-    local_irq_restore(flags);
+       /* Better allow ints _after_ 'main_running' has been cleared, else
+          an interrupt could believe we'll pick up the work it left for
+          us, but we won't see it anymore here... */
+       main_running = 0;
+       local_irq_restore(flags);
 }
 
 
@@ -1183,1441 +1236,1439 @@ static void NCR5380_main (void *bl)
  * Function : void NCR5380_dma_complete (struct Scsi_Host *instance)
  *
  * Purpose : Called by interrupt handler when DMA finishes or a phase
- *     mismatch occurs (which would finish the DMA transfer).  
+ *     mismatch occurs (which would finish the DMA transfer).
  *
  * Inputs : instance - this instance of the NCR5380.
  *
  */
 
-static void NCR5380_dma_complete( struct Scsi_Host *instance )
+static void NCR5380_dma_complete(struct Scsi_Host *instance)
 {
-    SETUP_HOSTDATA(instance);
-    int           transfered, saved_data = 0, overrun = 0, cnt, toPIO;
-    unsigned char **data, p;
-    volatile int  *count;
-
-    if (!hostdata->connected) {
-       printk(KERN_WARNING "scsi%d: received end of DMA interrupt with "
-              "no connected cmd\n", HOSTNO);
-       return;
-    }
-    
-    if (atari_read_overruns) {
-       p = hostdata->connected->SCp.phase;
-       if (p & SR_IO) {
-           udelay(10);
-           if ((((NCR5380_read(BUS_AND_STATUS_REG)) &
-                 (BASR_PHASE_MATCH|BASR_ACK)) ==
-                (BASR_PHASE_MATCH|BASR_ACK))) {
-               saved_data = NCR5380_read(INPUT_DATA_REG);
-               overrun = 1;
-               DMA_PRINTK("scsi%d: read overrun handled\n", HOSTNO);
-           }
+       SETUP_HOSTDATA(instance);
+       int transfered, saved_data = 0, overrun = 0, cnt, toPIO;
+       unsigned char **data, p;
+       volatile int *count;
+
+       if (!hostdata->connected) {
+               printk(KERN_WARNING "scsi%d: received end of DMA interrupt with "
+                      "no connected cmd\n", HOSTNO);
+               return;
        }
-    }
-
-    DMA_PRINTK("scsi%d: real DMA transfer complete, basr 0x%X, sr 0x%X\n",
-              HOSTNO, NCR5380_read(BUS_AND_STATUS_REG),
-              NCR5380_read(STATUS_REG));
-
-    (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-    NCR5380_write(MODE_REG, MR_BASE);
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
-    transfered = hostdata->dma_len - NCR5380_dma_residual(instance);
-    hostdata->dma_len = 0;
-
-    data = (unsigned char **) &(hostdata->connected->SCp.ptr);
-    count = &(hostdata->connected->SCp.this_residual);
-    *data += transfered;
-    *count -= transfered;
-
-    if (atari_read_overruns) {
-       if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) {
-           cnt = toPIO = atari_read_overruns;
-           if (overrun) {
-               DMA_PRINTK("Got an input overrun, using saved byte\n");
-               *(*data)++ = saved_data;
-               (*count)--;
-               cnt--;
-               toPIO--;
-           }
-           DMA_PRINTK("Doing %d-byte PIO to 0x%08lx\n", cnt, (long)*data);
-           NCR5380_transfer_pio(instance, &p, &cnt, data);
-           *count -= toPIO - cnt;
+
+       if (atari_read_overruns) {
+               p = hostdata->connected->SCp.phase;
+               if (p & SR_IO) {
+                       udelay(10);
+                       if ((NCR5380_read(BUS_AND_STATUS_REG) &
+                            (BASR_PHASE_MATCH|BASR_ACK)) ==
+                           (BASR_PHASE_MATCH|BASR_ACK)) {
+                               saved_data = NCR5380_read(INPUT_DATA_REG);
+                               overrun = 1;
+                               DMA_PRINTK("scsi%d: read overrun handled\n", HOSTNO);
+                       }
+               }
+       }
+
+       DMA_PRINTK("scsi%d: real DMA transfer complete, basr 0x%X, sr 0x%X\n",
+                  HOSTNO, NCR5380_read(BUS_AND_STATUS_REG),
+                  NCR5380_read(STATUS_REG));
+
+       (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+       NCR5380_write(MODE_REG, MR_BASE);
+       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+
+       transfered = hostdata->dma_len - NCR5380_dma_residual(instance);
+       hostdata->dma_len = 0;
+
+       data = (unsigned char **)&hostdata->connected->SCp.ptr;
+       count = &hostdata->connected->SCp.this_residual;
+       *data += transfered;
+       *count -= transfered;
+
+       if (atari_read_overruns) {
+               if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) {
+                       cnt = toPIO = atari_read_overruns;
+                       if (overrun) {
+                               DMA_PRINTK("Got an input overrun, using saved byte\n");
+                               *(*data)++ = saved_data;
+                               (*count)--;
+                               cnt--;
+                               toPIO--;
+                       }
+                       DMA_PRINTK("Doing %d-byte PIO to 0x%08lx\n", cnt, (long)*data);
+                       NCR5380_transfer_pio(instance, &p, &cnt, data);
+                       *count -= toPIO - cnt;
+               }
        }
-    }
 }
 #endif /* REAL_DMA */
 
 
 /*
  * Function : void NCR5380_intr (int irq)
- * 
+ *
  * Purpose : handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
- *     from the disconnected queue, and restarting NCR5380_main() 
+ *     from the disconnected queue, and restarting NCR5380_main()
  *     as required.
  *
  * Inputs : int irq, irq that caused this interrupt.
  *
  */
 
-static irqreturn_t NCR5380_intr (int irq, void *dev_id)
+static irqreturn_t NCR5380_intr(int irq, void *dev_id)
 {
-    struct Scsi_Host *instance = first_instance;
-    int done = 1, handled = 0;
-    unsigned char basr;
-
-    INT_PRINTK("scsi%d: NCR5380 irq triggered\n", HOSTNO);
-
-    /* Look for pending interrupts */
-    basr = NCR5380_read(BUS_AND_STATUS_REG);
-    INT_PRINTK("scsi%d: BASR=%02x\n", HOSTNO, basr);
-    /* dispatch to appropriate routine if found and done=0 */
-    if (basr & BASR_IRQ) {
-       NCR_PRINT(NDEBUG_INTR);
-       if ((NCR5380_read(STATUS_REG) & (SR_SEL|SR_IO)) == (SR_SEL|SR_IO)) {
-           done = 0;
-           ENABLE_IRQ();
-           INT_PRINTK("scsi%d: SEL interrupt\n", HOSTNO);
-           NCR5380_reselect(instance);
-           (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-       }
-       else if (basr & BASR_PARITY_ERROR) {
-           INT_PRINTK("scsi%d: PARITY interrupt\n", HOSTNO);
-           (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-       }
-       else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) {
-           INT_PRINTK("scsi%d: RESET interrupt\n", HOSTNO);
-           (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-       }
-       else {
-           /*  
-            * The rest of the interrupt conditions can occur only during a
-            * DMA transfer
-            */
+       struct Scsi_Host *instance = first_instance;
+       int done = 1, handled = 0;
+       unsigned char basr;
+
+       INT_PRINTK("scsi%d: NCR5380 irq triggered\n", HOSTNO);
+
+       /* Look for pending interrupts */
+       basr = NCR5380_read(BUS_AND_STATUS_REG);
+       INT_PRINTK("scsi%d: BASR=%02x\n", HOSTNO, basr);
+       /* dispatch to appropriate routine if found and done=0 */
+       if (basr & BASR_IRQ) {
+               NCR_PRINT(NDEBUG_INTR);
+               if ((NCR5380_read(STATUS_REG) & (SR_SEL|SR_IO)) == (SR_SEL|SR_IO)) {
+                       done = 0;
+                       ENABLE_IRQ();
+                       INT_PRINTK("scsi%d: SEL interrupt\n", HOSTNO);
+                       NCR5380_reselect(instance);
+                       (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+               } else if (basr & BASR_PARITY_ERROR) {
+                       INT_PRINTK("scsi%d: PARITY interrupt\n", HOSTNO);
+                       (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+               } else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) {
+                       INT_PRINTK("scsi%d: RESET interrupt\n", HOSTNO);
+                       (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+               } else {
+                       /*
+                        * The rest of the interrupt conditions can occur only during a
+                        * DMA transfer
+                        */
 
 #if defined(REAL_DMA)
-           /*
-            * We should only get PHASE MISMATCH and EOP interrupts if we have
-            * DMA enabled, so do a sanity check based on the current setting
-            * of the MODE register.
-            */
-
-           if ((NCR5380_read(MODE_REG) & MR_DMA_MODE) &&
-               ((basr & BASR_END_DMA_TRANSFER) || 
-                !(basr & BASR_PHASE_MATCH))) {
-                   
-               INT_PRINTK("scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO);
-               NCR5380_dma_complete( instance );
-               done = 0;
-               ENABLE_IRQ();
-           } else
+                       /*
+                        * We should only get PHASE MISMATCH and EOP interrupts if we have
+                        * DMA enabled, so do a sanity check based on the current setting
+                        * of the MODE register.
+                        */
+
+                       if ((NCR5380_read(MODE_REG) & MR_DMA_MODE) &&
+                           ((basr & BASR_END_DMA_TRANSFER) ||
+                            !(basr & BASR_PHASE_MATCH))) {
+
+                               INT_PRINTK("scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO);
+                               NCR5380_dma_complete( instance );
+                               done = 0;
+                               ENABLE_IRQ();
+                       } else
 #endif /* REAL_DMA */
-           {
+                       {
 /* MS: Ignore unknown phase mismatch interrupts (caused by EOP interrupt) */
-               if (basr & BASR_PHASE_MATCH)
-                   printk(KERN_NOTICE "scsi%d: unknown interrupt, "
-                          "BASR 0x%x, MR 0x%x, SR 0x%x\n",
-                          HOSTNO, basr, NCR5380_read(MODE_REG),
-                          NCR5380_read(STATUS_REG));
-               (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-           }
-       } /* if !(SELECTION || PARITY) */
-       handled = 1;
-    } /* BASR & IRQ */
-    else {
-       printk(KERN_NOTICE "scsi%d: interrupt without IRQ bit set in BASR, "
-              "BASR 0x%X, MR 0x%X, SR 0x%x\n", HOSTNO, basr,
-              NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG));
-       (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-    }
-    
-    if (!done) {
-       INT_PRINTK("scsi%d: in int routine, calling main\n", HOSTNO);
-       /* Put a call to NCR5380_main() on the queue... */
-       queue_main();
-    }
-    return IRQ_RETVAL(handled);
+                               if (basr & BASR_PHASE_MATCH)
+                                       printk(KERN_NOTICE "scsi%d: unknown interrupt, "
+                                              "BASR 0x%x, MR 0x%x, SR 0x%x\n",
+                                              HOSTNO, basr, NCR5380_read(MODE_REG),
+                                              NCR5380_read(STATUS_REG));
+                               (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+                       }
+               } /* if !(SELECTION || PARITY) */
+               handled = 1;
+       } /* BASR & IRQ */ else {
+               printk(KERN_NOTICE "scsi%d: interrupt without IRQ bit set in BASR, "
+                      "BASR 0x%X, MR 0x%X, SR 0x%x\n", HOSTNO, basr,
+                      NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG));
+               (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+       }
+
+       if (!done) {
+               INT_PRINTK("scsi%d: in int routine, calling main\n", HOSTNO);
+               /* Put a call to NCR5380_main() on the queue... */
+               queue_main();
+       }
+       return IRQ_RETVAL(handled);
 }
 
 #ifdef NCR5380_STATS
-static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmndcmd)
+static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd *cmd)
 {
 # ifdef NCR5380_STAT_LIMIT
-    if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
+       if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
 # endif
-       switch (cmd->cmnd[0])
-       {
-           case WRITE:
-           case WRITE_6:
-           case WRITE_10:
-               hostdata->time_write[cmd->device->id] += (jiffies - hostdata->timebase);
-               /*hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen;*/
-               hostdata->pendingw--;
-               break;
-           case READ:
-           case READ_6:
-           case READ_10:
-               hostdata->time_read[cmd->device->id] += (jiffies - hostdata->timebase);
-               /*hostdata->bytes_read[cmd->device->id] += cmd->request_bufflen;*/
-               hostdata->pendingr--;
-               break;
-       }
+               switch (cmd->cmnd[0]) {
+               case WRITE:
+               case WRITE_6:
+               case WRITE_10:
+                       hostdata->time_write[cmd->device->id] += (jiffies - hostdata->timebase);
+                       /*hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen;*/
+                       hostdata->pendingw--;
+                       break;
+               case READ:
+               case READ_6:
+               case READ_10:
+                       hostdata->time_read[cmd->device->id] += (jiffies - hostdata->timebase);
+                       /*hostdata->bytes_read[cmd->device->id] += cmd->request_bufflen;*/
+                       hostdata->pendingr--;
+                       break;
+               }
 }
 #endif
 
-/* 
- * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, 
+/*
+ * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd,
  *     int tag);
  *
  * Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command,
- *     including ARBITRATION, SELECTION, and initial message out for 
- *     IDENTIFY and queue messages. 
+ *     including ARBITRATION, SELECTION, and initial message out for
+ *     IDENTIFY and queue messages.
  *
- * Inputs : instance - instantiation of the 5380 driver on which this 
- *     target lives, cmd - SCSI command to execute, tag - set to TAG_NEXT for 
- *     new tag, TAG_NONE for untagged queueing, otherwise set to the tag for 
+ * Inputs : instance - instantiation of the 5380 driver on which this
+ *     target lives, cmd - SCSI command to execute, tag - set to TAG_NEXT for
+ *     new tag, TAG_NONE for untagged queueing, otherwise set to the tag for
  *     the command that is presently connected.
- * 
+ *
  * Returns : -1 if selection could not execute for some reason,
- *     0 if selection succeeded or failed because the target 
- *     did not respond.
+ *     0 if selection succeeded or failed because the target
+ *     did not respond.
  *
- * Side effects : 
- *     If bus busy, arbitration failed, etc, NCR5380_select() will exit 
+ * Side effects :
+ *     If bus busy, arbitration failed, etc, NCR5380_select() will exit
  *             with registers as they should have been on entry - ie
  *             SELECT_ENABLE will be set appropriately, the NCR5380
  *             will cease to drive any SCSI bus signals.
  *
- *     If successful : I_T_L or I_T_L_Q nexus will be established, 
- *             instance->connected will be set to cmd.  
- *             SELECT interrupt will be disabled.
+ *     If successful : I_T_L or I_T_L_Q nexus will be established,
+ *             instance->connected will be set to cmd.
+ *             SELECT interrupt will be disabled.
  *
- *     If failed (no target) : cmd->scsi_done() will be called, and the 
+ *     If failed (no target) : cmd->scsi_done() will be called, and the
  *             cmd->result host byte set to DID_BAD_TARGET.
  */
 
-static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
+static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
 {
-    SETUP_HOSTDATA(instance);
-    unsigned char tmp[3], phase;
-    unsigned char *data;
-    int len;
-    unsigned long timeout;
-    unsigned long flags;
-
-    hostdata->restart_select = 0;
-    NCR_PRINT(NDEBUG_ARBITRATION);
-    ARB_PRINTK("scsi%d: starting arbitration, id = %d\n", HOSTNO,
-              instance->this_id);
-
-    /* 
-     * Set the phase bits to 0, otherwise the NCR5380 won't drive the 
-     * data bus during SELECTION.
-     */
-
-    local_irq_save(flags);
-    if (hostdata->connected) {
+       SETUP_HOSTDATA(instance);
+       unsigned char tmp[3], phase;
+       unsigned char *data;
+       int len;
+       unsigned long timeout;
+       unsigned long flags;
+
+       hostdata->restart_select = 0;
+       NCR_PRINT(NDEBUG_ARBITRATION);
+       ARB_PRINTK("scsi%d: starting arbitration, id = %d\n", HOSTNO,
+                  instance->this_id);
+
+       /*
+        * Set the phase bits to 0, otherwise the NCR5380 won't drive the
+        * data bus during SELECTION.
+        */
+
+       local_irq_save(flags);
+       if (hostdata->connected) {
+               local_irq_restore(flags);
+               return -1;
+       }
+       NCR5380_write(TARGET_COMMAND_REG, 0);
+
+       /*
+        * Start arbitration.
+        */
+
+       NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
+       NCR5380_write(MODE_REG, MR_ARBITRATE);
+
        local_irq_restore(flags);
-       return -1;
-    }
-    NCR5380_write(TARGET_COMMAND_REG, 0);
-
-
-    /* 
-     * Start arbitration.
-     */
-    
-    NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
-    NCR5380_write(MODE_REG, MR_ARBITRATE);
-
-    local_irq_restore(flags);
-
-    /* Wait for arbitration logic to complete */
-#if NCR_TIMEOUT
-    {
-      unsigned long timeout = jiffies + 2*NCR_TIMEOUT;
-
-      while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)
-          && time_before(jiffies, timeout) && !hostdata->connected)
-       ;
-      if (time_after_eq(jiffies, timeout))
-      {
-       printk("scsi : arbitration timeout at %d\n", __LINE__);
-       NCR5380_write(MODE_REG, MR_BASE);
-       NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-       return -1;
-      }
-    }
+
+       /* Wait for arbitration logic to complete */
+#if defined(NCR_TIMEOUT)
+       {
+               unsigned long timeout = jiffies + 2*NCR_TIMEOUT;
+
+               while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) &&
+                      time_before(jiffies, timeout) && !hostdata->connected)
+                       ;
+               if (time_after_eq(jiffies, timeout)) {
+                       printk("scsi : arbitration timeout at %d\n", __LINE__);
+                       NCR5380_write(MODE_REG, MR_BASE);
+                       NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+                       return -1;
+               }
+       }
 #else /* NCR_TIMEOUT */
-    while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)
-        && !hostdata->connected);
+       while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) &&
+              !hostdata->connected)
+               ;
 #endif
 
-    ARB_PRINTK("scsi%d: arbitration complete\n", HOSTNO);
-
-    if (hostdata->connected) {
-       NCR5380_write(MODE_REG, MR_BASE); 
-       return -1;
-    }
-    /* 
-     * The arbitration delay is 2.2us, but this is a minimum and there is 
-     * no maximum so we can safely sleep for ceil(2.2) usecs to accommodate
-     * the integral nature of udelay().
-     *
-     */
-
-    udelay(3);
-
-    /* Check for lost arbitration */
-    if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
-       (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) ||
-       (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
-       hostdata->connected) {
-       NCR5380_write(MODE_REG, MR_BASE); 
-       ARB_PRINTK("scsi%d: lost arbitration, deasserting MR_ARBITRATE\n",
-                  HOSTNO);
-       return -1;
-    }
-
-     /* after/during arbitration, BSY should be asserted.
-       IBM DPES-31080 Version S31Q works now */
-     /* Tnx to Thomas_Roesch@m2.maus.de for finding this! (Roman) */
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL |
-                                        ICR_ASSERT_BSY ) ;
-    
-    if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
-       hostdata->connected) {
-       NCR5380_write(MODE_REG, MR_BASE);
-       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-       ARB_PRINTK("scsi%d: lost arbitration, deasserting ICR_ASSERT_SEL\n",
-                  HOSTNO);
-       return -1;
-    }
+       ARB_PRINTK("scsi%d: arbitration complete\n", HOSTNO);
 
-    /* 
-     * Again, bus clear + bus settle time is 1.2us, however, this is 
-     * a minimum so we'll udelay ceil(1.2)
-     */
+       if (hostdata->connected) {
+               NCR5380_write(MODE_REG, MR_BASE);
+               return -1;
+       }
+       /*
+        * The arbitration delay is 2.2us, but this is a minimum and there is
+        * no maximum so we can safely sleep for ceil(2.2) usecs to accommodate
+        * the integral nature of udelay().
+        *
+        */
+
+       udelay(3);
+
+       /* Check for lost arbitration */
+       if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
+           (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) ||
+           (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
+           hostdata->connected) {
+               NCR5380_write(MODE_REG, MR_BASE);
+               ARB_PRINTK("scsi%d: lost arbitration, deasserting MR_ARBITRATE\n",
+                          HOSTNO);
+               return -1;
+       }
+
+       /* after/during arbitration, BSY should be asserted.
+          IBM DPES-31080 Version S31Q works now */
+       /* Tnx to Thomas_Roesch@m2.maus.de for finding this! (Roman) */
+       NCR5380_write(INITIATOR_COMMAND_REG,
+                     ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY);
+
+       if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
+           hostdata->connected) {
+               NCR5380_write(MODE_REG, MR_BASE);
+               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+               ARB_PRINTK("scsi%d: lost arbitration, deasserting ICR_ASSERT_SEL\n",
+                          HOSTNO);
+               return -1;
+       }
+
+       /*
+        * Again, bus clear + bus settle time is 1.2us, however, this is
+        * a minimum so we'll udelay ceil(1.2)
+        */
 
 #ifdef CONFIG_ATARI_SCSI_TOSHIBA_DELAY
-    /* ++roman: But some targets (see above :-) seem to need a bit more... */
-    udelay(15);
+       /* ++roman: But some targets (see above :-) seem to need a bit more... */
+       udelay(15);
 #else
-    udelay(2);
+       udelay(2);
 #endif
-    
-    if (hostdata->connected) {
+
+       if (hostdata->connected) {
+               NCR5380_write(MODE_REG, MR_BASE);
+               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+               return -1;
+       }
+
+       ARB_PRINTK("scsi%d: won arbitration\n", HOSTNO);
+
+       /*
+        * Now that we have won arbitration, start Selection process, asserting
+        * the host and target ID's on the SCSI bus.
+        */
+
+       NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << cmd->device->id)));
+
+       /*
+        * Raise ATN while SEL is true before BSY goes false from arbitration,
+        * since this is the only way to guarantee that we'll get a MESSAGE OUT
+        * phase immediately after selection.
+        */
+
+       NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY |
+                     ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL ));
        NCR5380_write(MODE_REG, MR_BASE);
-       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-       return -1;
-    }
 
-    ARB_PRINTK("scsi%d: won arbitration\n", HOSTNO);
+       /*
+        * Reselect interrupts must be turned off prior to the dropping of BSY,
+        * otherwise we will trigger an interrupt.
+        */
+
+       if (hostdata->connected) {
+               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+               return -1;
+       }
 
-    /* 
-     * Now that we have won arbitration, start Selection process, asserting 
-     * the host and target ID's on the SCSI bus.
-     */
+       NCR5380_write(SELECT_ENABLE_REG, 0);
+
+       /*
+        * The initiator shall then wait at least two deskew delays and release
+        * the BSY signal.
+        */
+       udelay(1);        /* wingel -- wait two bus deskew delay >2*45ns */
+
+       /* Reset BSY */
+       NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA |
+                     ICR_ASSERT_ATN | ICR_ASSERT_SEL));
+
+       /*
+        * Something weird happens when we cease to drive BSY - looks
+        * like the board/chip is letting us do another read before the
+        * appropriate propagation delay has expired, and we're confusing
+        * a BSY signal from ourselves as the target's response to SELECTION.
+        *
+        * A small delay (the 'C++' frontend breaks the pipeline with an
+        * unnecessary jump, making it work on my 386-33/Trantor T128, the
+        * tighter 'C' code breaks and requires this) solves the problem -
+        * the 1 us delay is arbitrary, and only used because this delay will
+        * be the same on other platforms and since it works here, it should
+        * work there.
+        *
+        * wingel suggests that this could be due to failing to wait
+        * one deskew delay.
+        */
 
-    NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << cmd->device->id)));
+       udelay(1);
 
-    /* 
-     * Raise ATN while SEL is true before BSY goes false from arbitration,
-     * since this is the only way to guarantee that we'll get a MESSAGE OUT
-     * phase immediately after selection.
-     */
+       SEL_PRINTK("scsi%d: selecting target %d\n", HOSTNO, cmd->device->id);
 
-    NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY | 
-       ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL ));
-    NCR5380_write(MODE_REG, MR_BASE);
+       /*
+        * The SCSI specification calls for a 250 ms timeout for the actual
+        * selection.
+        */
 
-    /* 
-     * Reselect interrupts must be turned off prior to the dropping of BSY,
-     * otherwise we will trigger an interrupt.
-     */
+       timeout = jiffies + 25;
 
-    if (hostdata->connected) {
-       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-       return -1;
-    }
-
-    NCR5380_write(SELECT_ENABLE_REG, 0);
-
-    /*
-     * The initiator shall then wait at least two deskew delays and release 
-     * the BSY signal.
-     */
-    udelay(1);        /* wingel -- wait two bus deskew delay >2*45ns */
-
-    /* Reset BSY */
-    NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA | 
-       ICR_ASSERT_ATN | ICR_ASSERT_SEL));
-
-    /* 
-     * Something weird happens when we cease to drive BSY - looks
-     * like the board/chip is letting us do another read before the 
-     * appropriate propagation delay has expired, and we're confusing
-     * a BSY signal from ourselves as the target's response to SELECTION.
-     *
-     * A small delay (the 'C++' frontend breaks the pipeline with an
-     * unnecessary jump, making it work on my 386-33/Trantor T128, the
-     * tighter 'C' code breaks and requires this) solves the problem - 
-     * the 1 us delay is arbitrary, and only used because this delay will 
-     * be the same on other platforms and since it works here, it should 
-     * work there.
-     *
-     * wingel suggests that this could be due to failing to wait
-     * one deskew delay.
-     */
-
-    udelay(1);
-
-    SEL_PRINTK("scsi%d: selecting target %d\n", HOSTNO, cmd->device->id);
-
-    /* 
-     * The SCSI specification calls for a 250 ms timeout for the actual 
-     * selection.
-     */
-
-    timeout = jiffies + 25; 
-
-    /* 
-     * XXX very interesting - we're seeing a bounce where the BSY we 
-     * asserted is being reflected / still asserted (propagation delay?)
-     * and it's detecting as true.  Sigh.
-     */
+       /*
+        * XXX very interesting - we're seeing a bounce where the BSY we
+        * asserted is being reflected / still asserted (propagation delay?)
+        * and it's detecting as true.  Sigh.
+        */
 
 #if 0
-    /* ++roman: If a target conformed to the SCSI standard, it wouldn't assert
-     * IO while SEL is true. But again, there are some disks out the in the
-     * world that do that nevertheless. (Somebody claimed that this announces
-     * reselection capability of the target.) So we better skip that test and
-     * only wait for BSY... (Famous german words: Der Klügere gibt nach :-)
-     */
-
-    while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & 
-       (SR_BSY | SR_IO)));
-
-    if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == 
-           (SR_SEL | SR_IO)) {
-           NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-           NCR5380_reselect(instance);
-           printk (KERN_ERR "scsi%d: reselection after won arbitration?\n",
-                   HOSTNO);
-           NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-           return -1;
-    }
+       /* ++roman: If a target conformed to the SCSI standard, it wouldn't assert
+        * IO while SEL is true. But again, there are some disks out the in the
+        * world that do that nevertheless. (Somebody claimed that this announces
+        * reselection capability of the target.) So we better skip that test and
+        * only wait for BSY... (Famous german words: Der Klügere gibt nach :-)
+        */
+
+       while (time_before(jiffies, timeout) &&
+              !(NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO)))
+               ;
+
+       if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
+               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+               NCR5380_reselect(instance);
+               printk(KERN_ERR "scsi%d: reselection after won arbitration?\n",
+                      HOSTNO);
+               NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+               return -1;
+       }
 #else
-    while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY));
+       while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY))
+               ;
 #endif
 
-    /* 
-     * No less than two deskew delays after the initiator detects the 
-     * BSY signal is true, it shall release the SEL signal and may 
-     * change the DATA BUS.                                     -wingel
-     */
+       /*
+        * No less than two deskew delays after the initiator detects the
+        * BSY signal is true, it shall release the SEL signal and may
+        * change the DATA BUS.                                     -wingel
+        */
 
-    udelay(1);
+       udelay(1);
 
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
+       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
 
-    if (!(NCR5380_read(STATUS_REG) & SR_BSY)) {
-       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-       if (hostdata->targets_present & (1 << cmd->device->id)) {
-           printk(KERN_ERR "scsi%d: weirdness\n", HOSTNO);
-           if (hostdata->restart_select)
-               printk(KERN_NOTICE "\trestart select\n");
-           NCR_PRINT(NDEBUG_ANY);
-           NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-           return -1;
-       }
-       cmd->result = DID_BAD_TARGET << 16;
+       if (!(NCR5380_read(STATUS_REG) & SR_BSY)) {
+               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+               if (hostdata->targets_present & (1 << cmd->device->id)) {
+                       printk(KERN_ERR "scsi%d: weirdness\n", HOSTNO);
+                       if (hostdata->restart_select)
+                               printk(KERN_NOTICE "\trestart select\n");
+                       NCR_PRINT(NDEBUG_ANY);
+                       NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+                       return -1;
+               }
+               cmd->result = DID_BAD_TARGET << 16;
 #ifdef NCR5380_STATS
-       collect_stats(hostdata, cmd);
+               collect_stats(hostdata, cmd);
 #endif
 #ifdef SUPPORT_TAGS
-       cmd_free_tag( cmd );
+               cmd_free_tag(cmd);
 #endif
-       cmd->scsi_done(cmd);
-       NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-       SEL_PRINTK("scsi%d: target did not respond within 250ms\n", HOSTNO);
-       NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-       return 0;
-    } 
-
-    hostdata->targets_present |= (1 << cmd->device->id);
-
-    /*
-     * Since we followed the SCSI spec, and raised ATN while SEL 
-     * was true but before BSY was false during selection, the information
-     * transfer phase should be a MESSAGE OUT phase so that we can send the
-     * IDENTIFY message.
-     * 
-     * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG
-     * message (2 bytes) with a tag ID that we increment with every command
-     * until it wraps back to 0.
-     *
-     * XXX - it turns out that there are some broken SCSI-II devices,
-     *      which claim to support tagged queuing but fail when more than
-     *      some number of commands are issued at once.
-     */
-
-    /* Wait for start of REQ/ACK handshake */
-    while (!(NCR5380_read(STATUS_REG) & SR_REQ));
-
-    SEL_PRINTK("scsi%d: target %d selected, going into MESSAGE OUT phase.\n",
-              HOSTNO, cmd->device->id);
-    tmp[0] = IDENTIFY(1, cmd->device->lun);
+               cmd->scsi_done(cmd);
+               NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+               SEL_PRINTK("scsi%d: target did not respond within 250ms\n", HOSTNO);
+               NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+               return 0;
+       }
+
+       hostdata->targets_present |= (1 << cmd->device->id);
+
+       /*
+        * Since we followed the SCSI spec, and raised ATN while SEL
+        * was true but before BSY was false during selection, the information
+        * transfer phase should be a MESSAGE OUT phase so that we can send the
+        * IDENTIFY message.
+        *
+        * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG
+        * message (2 bytes) with a tag ID that we increment with every command
+        * until it wraps back to 0.
+        *
+        * XXX - it turns out that there are some broken SCSI-II devices,
+        *           which claim to support tagged queuing but fail when more than
+        *           some number of commands are issued at once.
+        */
+
+       /* Wait for start of REQ/ACK handshake */
+       while (!(NCR5380_read(STATUS_REG) & SR_REQ))
+               ;
+
+       SEL_PRINTK("scsi%d: target %d selected, going into MESSAGE OUT phase.\n",
+                  HOSTNO, cmd->device->id);
+       tmp[0] = IDENTIFY(1, cmd->device->lun);
 
 #ifdef SUPPORT_TAGS
-    if (cmd->tag != TAG_NONE) {
-       tmp[1] = hostdata->last_message = SIMPLE_QUEUE_TAG;
-       tmp[2] = cmd->tag;
-       len = 3;
-    } else 
-       len = 1;
+       if (cmd->tag != TAG_NONE) {
+               tmp[1] = hostdata->last_message = SIMPLE_QUEUE_TAG;
+               tmp[2] = cmd->tag;
+               len = 3;
+       } else
+               len = 1;
 #else
-    len = 1;
-    cmd->tag=0;
+       len = 1;
+       cmd->tag = 0;
 #endif /* SUPPORT_TAGS */
 
-    /* Send message(s) */
-    data = tmp;
-    phase = PHASE_MSGOUT;
-    NCR5380_transfer_pio(instance, &phase, &len, &data);
-    SEL_PRINTK("scsi%d: nexus established.\n", HOSTNO);
-    /* XXX need to handle errors here */
-    hostdata->connected = cmd;
+       /* Send message(s) */
+       data = tmp;
+       phase = PHASE_MSGOUT;
+       NCR5380_transfer_pio(instance, &phase, &len, &data);
+       SEL_PRINTK("scsi%d: nexus established.\n", HOSTNO);
+       /* XXX need to handle errors here */
+       hostdata->connected = cmd;
 #ifndef SUPPORT_TAGS
-    hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
-#endif    
-
-    initialize_SCp(cmd);
+       hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
+#endif
 
+       initialize_SCp(cmd);
 
-    return 0;
+       return 0;
 }
 
-/* 
- * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance, 
+/*
+ * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance,
  *      unsigned char *phase, int *count, unsigned char **data)
  *
  * Purpose : transfers data in given phase using polled I/O
  *
- * Inputs : instance - instance of driver, *phase - pointer to 
- *     what phase is expected, *count - pointer to number of 
+ * Inputs : instance - instance of driver, *phase - pointer to
+ *     what phase is expected, *count - pointer to number of
  *     bytes to transfer, **data - pointer to data pointer.
- * 
+ *
  * Returns : -1 when different phase is entered without transferring
  *     maximum number of bytes, 0 if all bytes are transfered or exit
  *     is in same phase.
  *
- *     Also, *phase, *count, *data are modified in place.
+ *     Also, *phase, *count, *data are modified in place.
  *
  * XXX Note : handling for bus free may be useful.
  */
 
 /*
- * Note : this code is not as quick as it could be, however it 
+ * Note : this code is not as quick as it could be, however it
  * IS 100% reliable, and for the actual data transfer where speed
  * counts, we will always do a pseudo DMA or DMA transfer.
  */
 
-static int NCR5380_transfer_pio( struct Scsi_Host *instance, 
-                                unsigned char *phase, int *count,
-                                unsigned char **data)
+static int NCR5380_transfer_pio(struct Scsi_Host *instance,
+                               unsigned char *phase, int *count,
+                               unsigned char **data)
 {
-    register unsigned char p = *phase, tmp;
-    register int c = *count;
-    register unsigned char *d = *data;
-
-    /* 
-     * The NCR5380 chip will only drive the SCSI bus when the 
-     * phase specified in the appropriate bits of the TARGET COMMAND
-     * REGISTER match the STATUS REGISTER
-     */
-
-    NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
-
-    do {
-       /* 
-        * Wait for assertion of REQ, after which the phase bits will be 
-        * valid 
+       register unsigned char p = *phase, tmp;
+       register int c = *count;
+       register unsigned char *d = *data;
+
+       /*
+        * The NCR5380 chip will only drive the SCSI bus when the
+        * phase specified in the appropriate bits of the TARGET COMMAND
+        * REGISTER match the STATUS REGISTER
         */
-       while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ));
 
-       HSH_PRINTK("scsi%d: REQ detected\n", HOSTNO);
+       NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
 
-       /* Check for phase mismatch */  
-       if ((tmp & PHASE_MASK) != p) {
-           PIO_PRINTK("scsi%d: phase mismatch\n", HOSTNO);
-           NCR_PRINT_PHASE(NDEBUG_PIO);
-           break;
-       }
+       do {
+               /*
+                * Wait for assertion of REQ, after which the phase bits will be
+                * valid
+                */
+               while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ))
+                       ;
 
-       /* Do actual transfer from SCSI bus to / from memory */
-       if (!(p & SR_IO)) 
-           NCR5380_write(OUTPUT_DATA_REG, *d);
-       else 
-           *d = NCR5380_read(CURRENT_SCSI_DATA_REG);
+               HSH_PRINTK("scsi%d: REQ detected\n", HOSTNO);
 
-       ++d;
+               /* Check for phase mismatch */
+               if ((tmp & PHASE_MASK) != p) {
+                       PIO_PRINTK("scsi%d: phase mismatch\n", HOSTNO);
+                       NCR_PRINT_PHASE(NDEBUG_PIO);
+                       break;
+               }
 
-       /* 
-        * The SCSI standard suggests that in MSGOUT phase, the initiator
-        * should drop ATN on the last byte of the message phase
-        * after REQ has been asserted for the handshake but before
-        * the initiator raises ACK.
-        */
+               /* Do actual transfer from SCSI bus to / from memory */
+               if (!(p & SR_IO))
+                       NCR5380_write(OUTPUT_DATA_REG, *d);
+               else
+                       *d = NCR5380_read(CURRENT_SCSI_DATA_REG);
 
-       if (!(p & SR_IO)) {
-           if (!((p & SR_MSG) && c > 1)) {
-               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
-                   ICR_ASSERT_DATA);
-               NCR_PRINT(NDEBUG_PIO);
-               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
-                       ICR_ASSERT_DATA | ICR_ASSERT_ACK);
-           } else {
-               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
-                   ICR_ASSERT_DATA | ICR_ASSERT_ATN);
-               NCR_PRINT(NDEBUG_PIO);
-               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
-                   ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
-           }
-       } else {
-           NCR_PRINT(NDEBUG_PIO);
-           NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
-       }
+               ++d;
 
-       while (NCR5380_read(STATUS_REG) & SR_REQ);
+               /*
+                * The SCSI standard suggests that in MSGOUT phase, the initiator
+                * should drop ATN on the last byte of the message phase
+                * after REQ has been asserted for the handshake but before
+                * the initiator raises ACK.
+                */
 
-       HSH_PRINTK("scsi%d: req false, handshake complete\n", HOSTNO);
+               if (!(p & SR_IO)) {
+                       if (!((p & SR_MSG) && c > 1)) {
+                               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
+                               NCR_PRINT(NDEBUG_PIO);
+                               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
+                                             ICR_ASSERT_DATA | ICR_ASSERT_ACK);
+                       } else {
+                               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
+                                             ICR_ASSERT_DATA | ICR_ASSERT_ATN);
+                               NCR_PRINT(NDEBUG_PIO);
+                               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
+                                             ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
+                       }
+               } else {
+                       NCR_PRINT(NDEBUG_PIO);
+                       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
+               }
 
-/*
- * We have several special cases to consider during REQ/ACK handshaking : 
- * 1.  We were in MSGOUT phase, and we are on the last byte of the 
- *     message.  ATN must be dropped as ACK is dropped.
- *
- * 2.  We are in a MSGIN phase, and we are on the last byte of the  
- *     message.  We must exit with ACK asserted, so that the calling
- *     code may raise ATN before dropping ACK to reject the message.
- *
- * 3.  ACK and ATN are clear and the target may proceed as normal.
- */
-       if (!(p == PHASE_MSGIN && c == 1)) {  
-           if (p == PHASE_MSGOUT && c > 1)
-               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
-           else
-               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-       } 
-    } while (--c);
-
-    PIO_PRINTK("scsi%d: residual %d\n", HOSTNO, c);
-
-    *count = c;
-    *data = d;
-    tmp = NCR5380_read(STATUS_REG);
-    /* The phase read from the bus is valid if either REQ is (already)
-     * asserted or if ACK hasn't been released yet. The latter is the case if
-     * we're in MSGIN and all wanted bytes have been received. */
-    if ((tmp & SR_REQ) || (p == PHASE_MSGIN && c == 0))
-       *phase = tmp & PHASE_MASK;
-    else 
-       *phase = PHASE_UNKNOWN;
-
-    if (!c || (*phase == p))
-       return 0;
-    else 
-       return -1;
+               while (NCR5380_read(STATUS_REG) & SR_REQ)
+                       ;
+
+               HSH_PRINTK("scsi%d: req false, handshake complete\n", HOSTNO);
+
+               /*
+                * We have several special cases to consider during REQ/ACK handshaking :
+                * 1.  We were in MSGOUT phase, and we are on the last byte of the
+                *      message.  ATN must be dropped as ACK is dropped.
+                *
+                * 2.  We are in a MSGIN phase, and we are on the last byte of the
+                *      message.  We must exit with ACK asserted, so that the calling
+                *      code may raise ATN before dropping ACK to reject the message.
+                *
+                * 3.  ACK and ATN are clear and the target may proceed as normal.
+                */
+               if (!(p == PHASE_MSGIN && c == 1)) {
+                       if (p == PHASE_MSGOUT && c > 1)
+                               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
+                       else
+                               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+               }
+       } while (--c);
+
+       PIO_PRINTK("scsi%d: residual %d\n", HOSTNO, c);
+
+       *count = c;
+       *data = d;
+       tmp = NCR5380_read(STATUS_REG);
+       /* The phase read from the bus is valid if either REQ is (already)
+        * asserted or if ACK hasn't been released yet. The latter is the case if
+        * we're in MSGIN and all wanted bytes have been received.
+        */
+       if ((tmp & SR_REQ) || (p == PHASE_MSGIN && c == 0))
+               *phase = tmp & PHASE_MASK;
+       else
+               *phase = PHASE_UNKNOWN;
+
+       if (!c || (*phase == p))
+               return 0;
+       else
+               return -1;
 }
 
 /*
  * Function : do_abort (Scsi_Host *host)
- * 
- * Purpose : abort the currently established nexus.  Should only be 
- *     called from a routine which can drop into a 
- * 
+ *
+ * Purpose : abort the currently established nexus.  Should only be
+ *     called from a routine which can drop into a
+ *
  * Returns : 0 on success, -1 on failure.
  */
 
-static int do_abort (struct Scsi_Host *host) 
+static int do_abort(struct Scsi_Host *host)
 {
-    unsigned char tmp, *msgptr, phase;
-    int len;
-
-    /* Request message out phase */
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
-
-    /* 
-     * Wait for the target to indicate a valid phase by asserting 
-     * REQ.  Once this happens, we'll have either a MSGOUT phase 
-     * and can immediately send the ABORT message, or we'll have some 
-     * other phase and will have to source/sink data.
-     * 
-     * We really don't care what value was on the bus or what value
-     * the target sees, so we just handshake.
-     */
-    
-    while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ);
-
-    NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
-
-    if ((tmp & PHASE_MASK) != PHASE_MSGOUT) {
-       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | 
-                     ICR_ASSERT_ACK);
-       while (NCR5380_read(STATUS_REG) & SR_REQ);
+       unsigned char tmp, *msgptr, phase;
+       int len;
+
+       /* Request message out phase */
        NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
-    }
-   
-    tmp = ABORT;
-    msgptr = &tmp;
-    len = 1;
-    phase = PHASE_MSGOUT;
-    NCR5380_transfer_pio (host, &phase, &len, &msgptr);
-
-    /*
-     * If we got here, and the command completed successfully,
-     * we're about to go into bus free state.
-     */
-
-    return len ? -1 : 0;
+
+       /*
+        * Wait for the target to indicate a valid phase by asserting
+        * REQ.  Once this happens, we'll have either a MSGOUT phase
+        * and can immediately send the ABORT message, or we'll have some
+        * other phase and will have to source/sink data.
+        *
+        * We really don't care what value was on the bus or what value
+        * the target sees, so we just handshake.
+        */
+
+       while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ)
+               ;
+
+       NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
+
+       if ((tmp & PHASE_MASK) != PHASE_MSGOUT) {
+               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN |
+                             ICR_ASSERT_ACK);
+               while (NCR5380_read(STATUS_REG) & SR_REQ)
+                       ;
+               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
+       }
+
+       tmp = ABORT;
+       msgptr = &tmp;
+       len = 1;
+       phase = PHASE_MSGOUT;
+       NCR5380_transfer_pio(host, &phase, &len, &msgptr);
+
+       /*
+        * If we got here, and the command completed successfully,
+        * we're about to go into bus free state.
+        */
+
+       return len ? -1 : 0;
 }
 
 #if defined(REAL_DMA)
-/* 
- * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, 
+/*
+ * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance,
  *      unsigned char *phase, int *count, unsigned char **data)
  *
  * Purpose : transfers data in given phase using either real
  *     or pseudo DMA.
  *
- * Inputs : instance - instance of driver, *phase - pointer to 
- *     what phase is expected, *count - pointer to number of 
+ * Inputs : instance - instance of driver, *phase - pointer to
+ *     what phase is expected, *count - pointer to number of
  *     bytes to transfer, **data - pointer to data pointer.
- * 
+ *
  * Returns : -1 when different phase is entered without transferring
  *     maximum number of bytes, 0 if all bytes or transfered or exit
  *     is in same phase.
  *
- *     Also, *phase, *count, *data are modified in place.
+ *     Also, *phase, *count, *data are modified in place.
  *
  */
 
 
-static int NCR5380_transfer_dma( struct Scsi_Host *instance, 
-                                unsigned char *phase, int *count,
-                                unsigned char **data)
+static int NCR5380_transfer_dma(struct Scsi_Host *instance,
+                               unsigned char *phase, int *count,
+                               unsigned char **data)
 {
-    SETUP_HOSTDATA(instance);
-    register int c = *count;
-    register unsigned char p = *phase;
-    register unsigned char *d = *data;
-    unsigned char tmp;
-    unsigned long flags;
-
-    if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {
-        *phase = tmp;
-        return -1;
-    }
+       SETUP_HOSTDATA(instance);
+       register int c = *count;
+       register unsigned char p = *phase;
+       register unsigned char *d = *data;
+       unsigned char tmp;
+       unsigned long flags;
+
+       if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {
+               *phase = tmp;
+               return -1;
+       }
 
-    if (atari_read_overruns && (p & SR_IO)) {
-       c -= atari_read_overruns;
-    }
+       if (atari_read_overruns && (p & SR_IO))
+               c -= atari_read_overruns;
 
-    DMA_PRINTK("scsi%d: initializing DMA for %s, %d bytes %s %p\n",
-              HOSTNO, (p & SR_IO) ? "reading" : "writing",
-              c, (p & SR_IO) ? "to" : "from", d);
+       DMA_PRINTK("scsi%d: initializing DMA for %s, %d bytes %s %p\n",
+                  HOSTNO, (p & SR_IO) ? "reading" : "writing",
+                  c, (p & SR_IO) ? "to" : "from", d);
 
-    NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
+       NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
 
 #ifdef REAL_DMA
-    NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY);
+       NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY);
 #endif /* def REAL_DMA  */
 
-    if (IS_A_TT()) {
-       /* On the Medusa, it is a must to initialize the DMA before
-        * starting the NCR. This is also the cleaner way for the TT.
-        */
-       local_irq_save(flags);
-       hostdata->dma_len = (p & SR_IO) ?
-           NCR5380_dma_read_setup(instance, d, c) : 
-           NCR5380_dma_write_setup(instance, d, c);
-       local_irq_restore(flags);
-    }
-    
-    if (p & SR_IO)
-       NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
-    else {
-       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
-       NCR5380_write(START_DMA_SEND_REG, 0);
-    }
-
-    if (!IS_A_TT()) {
-       /* On the Falcon, the DMA setup must be done after the last */
-       /* NCR access, else the DMA setup gets trashed!
-        */
-       local_irq_save(flags);
-       hostdata->dma_len = (p & SR_IO) ?
-           NCR5380_dma_read_setup(instance, d, c) : 
-           NCR5380_dma_write_setup(instance, d, c);
-       local_irq_restore(flags);
-    }
-    return 0;
+       if (IS_A_TT()) {
+               /* On the Medusa, it is a must to initialize the DMA before
+                * starting the NCR. This is also the cleaner way for the TT.
+                */
+               local_irq_save(flags);
+               hostdata->dma_len = (p & SR_IO) ?
+                       NCR5380_dma_read_setup(instance, d, c) :
+                       NCR5380_dma_write_setup(instance, d, c);
+               local_irq_restore(flags);
+       }
+
+       if (p & SR_IO)
+               NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
+       else {
+               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
+               NCR5380_write(START_DMA_SEND_REG, 0);
+       }
+
+       if (!IS_A_TT()) {
+               /* On the Falcon, the DMA setup must be done after the last */
+               /* NCR access, else the DMA setup gets trashed!
+                */
+               local_irq_save(flags);
+               hostdata->dma_len = (p & SR_IO) ?
+                       NCR5380_dma_read_setup(instance, d, c) :
+                       NCR5380_dma_write_setup(instance, d, c);
+               local_irq_restore(flags);
+       }
+       return 0;
 }
 #endif /* defined(REAL_DMA) */
 
 /*
  * Function : NCR5380_information_transfer (struct Scsi_Host *instance)
  *
- * Purpose : run through the various SCSI phases and do as the target 
- *     directs us to.  Operates on the currently connected command, 
+ * Purpose : run through the various SCSI phases and do as the target
+ *     directs us to.  Operates on the currently connected command,
  *     instance->connected.
  *
  * Inputs : instance, instance for which we are doing commands
  *
- * Side effects : SCSI things happen, the disconnected queue will be 
+ * Side effects : SCSI things happen, the disconnected queue will be
  *     modified if a command disconnects, *instance->connected will
  *     change.
  *
- * XXX Note : we need to watch for bus free or a reset condition here 
- *     to recover from an unexpected bus free condition.
+ * XXX Note : we need to watch for bus free or a reset condition here
+ *     to recover from an unexpected bus free condition.
  */
-static void NCR5380_information_transfer (struct Scsi_Host *instance)
+
+static void NCR5380_information_transfer(struct Scsi_Host *instance)
 {
-    SETUP_HOSTDATA(instance);
-    unsigned long flags;
-    unsigned char msgout = NOP;
-    int sink = 0;
-    int len;
+       SETUP_HOSTDATA(instance);
+       unsigned long flags;
+       unsigned char msgout = NOP;
+       int sink = 0;
+       int len;
 #if defined(REAL_DMA)
-    int transfersize;
+       int transfersize;
 #endif
-    unsigned char *data;
-    unsigned char phase, tmp, extended_msg[10], old_phase=0xff;
-    Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected;
+       unsigned char *data;
+       unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
+       Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected;
+
+       while (1) {
+               tmp = NCR5380_read(STATUS_REG);
+               /* We only have a valid SCSI phase when REQ is asserted */
+               if (tmp & SR_REQ) {
+                       phase = (tmp & PHASE_MASK);
+                       if (phase != old_phase) {
+                               old_phase = phase;
+                               NCR_PRINT_PHASE(NDEBUG_INFORMATION);
+                       }
 
-    while (1) {
-       tmp = NCR5380_read(STATUS_REG);
-       /* We only have a valid SCSI phase when REQ is asserted */
-       if (tmp & SR_REQ) {
-           phase = (tmp & PHASE_MASK); 
-           if (phase != old_phase) {
-               old_phase = phase;
-               NCR_PRINT_PHASE(NDEBUG_INFORMATION);
-           }
-           
-           if (sink && (phase != PHASE_MSGOUT)) {
-               NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
-
-               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | 
-                   ICR_ASSERT_ACK);
-               while (NCR5380_read(STATUS_REG) & SR_REQ);
-               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
-                   ICR_ASSERT_ATN);
-               sink = 0;
-               continue;
-           }
-
-           switch (phase) {
-           case PHASE_DATAOUT:
+                       if (sink && (phase != PHASE_MSGOUT)) {
+                               NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
+
+                               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN |
+                                             ICR_ASSERT_ACK);
+                               while (NCR5380_read(STATUS_REG) & SR_REQ)
+                                       ;
+                               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
+                                             ICR_ASSERT_ATN);
+                               sink = 0;
+                               continue;
+                       }
+
+                       switch (phase) {
+                       case PHASE_DATAOUT:
 #if (NDEBUG & NDEBUG_NO_DATAOUT)
-               printk("scsi%d: NDEBUG_NO_DATAOUT set, attempted DATAOUT "
-                      "aborted\n", HOSTNO);
-               sink = 1;
-               do_abort(instance);
-               cmd->result = DID_ERROR  << 16;
-               cmd->done(cmd);
-               return;
+                               printk("scsi%d: NDEBUG_NO_DATAOUT set, attempted DATAOUT "
+                                      "aborted\n", HOSTNO);
+                               sink = 1;
+                               do_abort(instance);
+                               cmd->result = DID_ERROR << 16;
+                               cmd->done(cmd);
+                               return;
 #endif
-           case PHASE_DATAIN:
-               /* 
-                * If there is no room left in the current buffer in the
-                * scatter-gather list, move onto the next one.
-                */
-
-               if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
-                   ++cmd->SCp.buffer;
-                   --cmd->SCp.buffers_residual;
-                   cmd->SCp.this_residual = cmd->SCp.buffer->length;
-                   cmd->SCp.ptr = page_address(cmd->SCp.buffer->page)+
-                                  cmd->SCp.buffer->offset;
-                   /* ++roman: Try to merge some scatter-buffers if
-                    * they are at contiguous physical addresses.
-                    */
-                   merge_contiguous_buffers( cmd );
-                   INF_PRINTK("scsi%d: %d bytes and %d buffers left\n",
-                              HOSTNO, cmd->SCp.this_residual,
-                              cmd->SCp.buffers_residual);
-               }
-
-               /*
-                * The preferred transfer method is going to be 
-                * PSEUDO-DMA for systems that are strictly PIO,
-                * since we can let the hardware do the handshaking.
-                *
-                * For this to work, we need to know the transfersize
-                * ahead of time, since the pseudo-DMA code will sit
-                * in an unconditional loop.
-                */
-
-/* ++roman: I suggest, this should be
- *   #if def(REAL_DMA)
- * instead of leaving REAL_DMA out.
- */
+                       case PHASE_DATAIN:
+                               /*
+                                * If there is no room left in the current buffer in the
+                                * scatter-gather list, move onto the next one.
+                                */
+
+                               if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
+                                       ++cmd->SCp.buffer;
+                                       --cmd->SCp.buffers_residual;
+                                       cmd->SCp.this_residual = cmd->SCp.buffer->length;
+                                       cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) +
+                                                  cmd->SCp.buffer->offset;
+                                       /* ++roman: Try to merge some scatter-buffers if
+                                        * they are at contiguous physical addresses.
+                                        */
+                                       merge_contiguous_buffers(cmd);
+                                       INF_PRINTK("scsi%d: %d bytes and %d buffers left\n",
+                                                  HOSTNO, cmd->SCp.this_residual,
+                                                  cmd->SCp.buffers_residual);
+                               }
+
+                               /*
+                                * The preferred transfer method is going to be
+                                * PSEUDO-DMA for systems that are strictly PIO,
+                                * since we can let the hardware do the handshaking.
+                                *
+                                * For this to work, we need to know the transfersize
+                                * ahead of time, since the pseudo-DMA code will sit
+                                * in an unconditional loop.
+                                */
+
+                               /* ++roman: I suggest, this should be
                               *   #if def(REAL_DMA)
                               * instead of leaving REAL_DMA out.
                               */
 
 #if defined(REAL_DMA)
-               if (!cmd->device->borken &&
-                   (transfersize = NCR5380_dma_xfer_len(instance,cmd,phase)) > 31) {
-                   len = transfersize;
-                   cmd->SCp.phase = phase;
-                   if (NCR5380_transfer_dma(instance, &phase,
-                       &len, (unsigned char **) &cmd->SCp.ptr)) {
-                       /*
-                        * If the watchdog timer fires, all future
-                        * accesses to this device will use the
-                        * polled-IO. */ 
-                       printk(KERN_NOTICE "scsi%d: switching target %d "
-                              "lun %d to slow handshake\n", HOSTNO,
-                              cmd->device->id, cmd->device->lun);
-                       cmd->device->borken = 1;
-                       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
-                           ICR_ASSERT_ATN);
-                       sink = 1;
-                       do_abort(instance);
-                       cmd->result = DID_ERROR  << 16;
-                       cmd->done(cmd);
-                       /* XXX - need to source or sink data here, as appropriate */
-                   } else {
+                               if (!cmd->device->borken &&
+                                   (transfersize = NCR5380_dma_xfer_len(instance,cmd,phase)) > 31) {
+                                       len = transfersize;
+                                       cmd->SCp.phase = phase;
+                                       if (NCR5380_transfer_dma(instance, &phase,
+                                           &len, (unsigned char **)&cmd->SCp.ptr)) {
+                                               /*
+                                                * If the watchdog timer fires, all future
+                                                * accesses to this device will use the
+                                                * polled-IO. */
+                                               printk(KERN_NOTICE "scsi%d: switching target %d "
+                                                          "lun %d to slow handshake\n", HOSTNO,
+                                                          cmd->device->id, cmd->device->lun);
+                                               cmd->device->borken = 1;
+                                               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
+                                                       ICR_ASSERT_ATN);
+                                               sink = 1;
+                                               do_abort(instance);
+                                               cmd->result = DID_ERROR << 16;
+                                               cmd->done(cmd);
+                                               /* XXX - need to source or sink data here, as appropriate */
+                                       } else {
 #ifdef REAL_DMA
-                       /* ++roman: When using real DMA,
-                        * information_transfer() should return after
-                        * starting DMA since it has nothing more to
-                        * do.
-                        */
-                       return;
-#else                  
-                       cmd->SCp.this_residual -= transfersize - len;
+                                               /* ++roman: When using real DMA,
+                                                * information_transfer() should return after
+                                                * starting DMA since it has nothing more to
+                                                * do.
+                                                */
+                                               return;
+#else
+                                               cmd->SCp.this_residual -= transfersize - len;
 #endif
-                   }
-               } else
+                                       }
+                               } else
 #endif /* defined(REAL_DMA) */
-                 NCR5380_transfer_pio(instance, &phase, 
-                   (int *) &cmd->SCp.this_residual, (unsigned char **)
-                   &cmd->SCp.ptr);
-               break;
-           case PHASE_MSGIN:
-               len = 1;
-               data = &tmp;
-               NCR5380_write(SELECT_ENABLE_REG, 0);    /* disable reselects */
-               NCR5380_transfer_pio(instance, &phase, &len, &data);
-               cmd->SCp.Message = tmp;
-
-               switch (tmp) {
-               /*
-                * Linking lets us reduce the time required to get the 
-                * next command out to the device, hopefully this will
-                * mean we don't waste another revolution due to the delays
-                * required by ARBITRATION and another SELECTION.
-                *
-                * In the current implementation proposal, low level drivers
-                * merely have to start the next command, pointed to by 
-                * next_link, done() is called as with unlinked commands.
-                */
+                                       NCR5380_transfer_pio(instance, &phase,
+                                                            (int *)&cmd->SCp.this_residual,
+                                                            (unsigned char **)&cmd->SCp.ptr);
+                               break;
+                       case PHASE_MSGIN:
+                               len = 1;
+                               data = &tmp;
+                               NCR5380_write(SELECT_ENABLE_REG, 0);    /* disable reselects */
+                               NCR5380_transfer_pio(instance, &phase, &len, &data);
+                               cmd->SCp.Message = tmp;
+
+                               switch (tmp) {
+                               /*
+                                * Linking lets us reduce the time required to get the
+                                * next command out to the device, hopefully this will
+                                * mean we don't waste another revolution due to the delays
+                                * required by ARBITRATION and another SELECTION.
+                                *
+                                * In the current implementation proposal, low level drivers
+                                * merely have to start the next command, pointed to by
+                                * next_link, done() is called as with unlinked commands.
+                                */
 #ifdef LINKED
-               case LINKED_CMD_COMPLETE:
-               case LINKED_FLG_CMD_COMPLETE:
-                   /* Accept message by clearing ACK */
-                   NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-                   
-                   LNK_PRINTK("scsi%d: target %d lun %d linked command "
-                              "complete.\n", HOSTNO, cmd->device->id, cmd->device->lun);
-
-                   /* Enable reselect interrupts */
-                   NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-                   /*
-                    * Sanity check : A linked command should only terminate
-                    * with one of these messages if there are more linked
-                    * commands available.
-                    */
-
-                   if (!cmd->next_link) {
-                        printk(KERN_NOTICE "scsi%d: target %d lun %d "
-                               "linked command complete, no next_link\n",
-                               HOSTNO, cmd->device->id, cmd->device->lun);
-                           sink = 1;
-                           do_abort (instance);
-                           return;
-                   }
-
-                   initialize_SCp(cmd->next_link);
-                   /* The next command is still part of this process; copy it
-                    * and don't free it! */
-                   cmd->next_link->tag = cmd->tag;
-                   cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); 
-                   LNK_PRINTK("scsi%d: target %d lun %d linked request "
-                              "done, calling scsi_done().\n",
-                              HOSTNO, cmd->device->id, cmd->device->lun);
+                               case LINKED_CMD_COMPLETE:
+                               case LINKED_FLG_CMD_COMPLETE:
+                                       /* Accept message by clearing ACK */
+                                       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+
+                                       LNK_PRINTK("scsi%d: target %d lun %d linked command "
+                                                  "complete.\n", HOSTNO, cmd->device->id, cmd->device->lun);
+
+                                       /* Enable reselect interrupts */
+                                       NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+                                       /*
+                                        * Sanity check : A linked command should only terminate
+                                        * with one of these messages if there are more linked
+                                        * commands available.
+                                        */
+
+                                       if (!cmd->next_link) {
+                                                printk(KERN_NOTICE "scsi%d: target %d lun %d "
+                                                       "linked command complete, no next_link\n",
+                                                       HOSTNO, cmd->device->id, cmd->device->lun);
+                                               sink = 1;
+                                               do_abort(instance);
+                                               return;
+                                       }
+
+                                       initialize_SCp(cmd->next_link);
+                                       /* The next command is still part of this process; copy it
+                                        * and don't free it! */
+                                       cmd->next_link->tag = cmd->tag;
+                                       cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
+                                       LNK_PRINTK("scsi%d: target %d lun %d linked request "
+                                                  "done, calling scsi_done().\n",
+                                                  HOSTNO, cmd->device->id, cmd->device->lun);
 #ifdef NCR5380_STATS
-                   collect_stats(hostdata, cmd);
+                                       collect_stats(hostdata, cmd);
 #endif
-                   cmd->scsi_done(cmd);
-                   cmd = hostdata->connected;
-                   break;
+                                       cmd->scsi_done(cmd);
+                                       cmd = hostdata->connected;
+                                       break;
 #endif /* def LINKED */
-               case ABORT:
-               case COMMAND_COMPLETE: 
-                   /* Accept message by clearing ACK */
-                   NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-                   /* ++guenther: possible race with Falcon locking */
-                   falcon_dont_release++;
-                   hostdata->connected = NULL;
-                   QU_PRINTK("scsi%d: command for target %d, lun %d "
-                             "completed\n", HOSTNO, cmd->device->id, cmd->device->lun);
+                               case ABORT:
+                               case COMMAND_COMPLETE:
+                                       /* Accept message by clearing ACK */
+                                       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+                                       /* ++guenther: possible race with Falcon locking */
+                                       falcon_dont_release++;
+                                       hostdata->connected = NULL;
+                                       QU_PRINTK("scsi%d: command for target %d, lun %d "
+                                                 "completed\n", HOSTNO, cmd->device->id, cmd->device->lun);
 #ifdef SUPPORT_TAGS
-                   cmd_free_tag( cmd );
-                   if (status_byte(cmd->SCp.Status) == QUEUE_FULL) {
-                       /* Turn a QUEUE FULL status into BUSY, I think the
-                        * mid level cannot handle QUEUE FULL :-( (The
-                        * command is retried after BUSY). Also update our
-                        * queue size to the number of currently issued
-                        * commands now.
-                        */
-                       /* ++Andreas: the mid level code knows about
-                          QUEUE_FULL now. */
-                       TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
-                       TAG_PRINTK("scsi%d: target %d lun %d returned "
-                                  "QUEUE_FULL after %d commands\n",
-                                  HOSTNO, cmd->device->id, cmd->device->lun,
-                                  ta->nr_allocated);
-                       if (ta->queue_size > ta->nr_allocated)
-                           ta->nr_allocated = ta->queue_size;
-                   }
+                                       cmd_free_tag(cmd);
+                                       if (status_byte(cmd->SCp.Status) == QUEUE_FULL) {
+                                               /* Turn a QUEUE FULL status into BUSY, I think the
+                                                * mid level cannot handle QUEUE FULL :-( (The
+                                                * command is retried after BUSY). Also update our
+                                                * queue size to the number of currently issued
+                                                * commands now.
+                                                */
+                                               /* ++Andreas: the mid level code knows about
+                                                  QUEUE_FULL now. */
+                                               TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+                                               TAG_PRINTK("scsi%d: target %d lun %d returned "
+                                                          "QUEUE_FULL after %d commands\n",
+                                                          HOSTNO, cmd->device->id, cmd->device->lun,
+                                                          ta->nr_allocated);
+                                               if (ta->queue_size > ta->nr_allocated)
+                                                       ta->nr_allocated = ta->queue_size;
+                                       }
 #else
-                   hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+                                       hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
 #endif
-                   /* Enable reselect interrupts */
-                   NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-
-                   /* 
-                    * I'm not sure what the correct thing to do here is : 
-                    * 
-                    * If the command that just executed is NOT a request 
-                    * sense, the obvious thing to do is to set the result
-                    * code to the values of the stored parameters.
-                    * 
-                    * If it was a REQUEST SENSE command, we need some way to
-                    * differentiate between the failure code of the original
-                    * and the failure code of the REQUEST sense - the obvious
-                    * case is success, where we fall through and leave the
-                    * result code unchanged.
-                    * 
-                    * The non-obvious place is where the REQUEST SENSE failed
-                    */
-
-                   if (cmd->cmnd[0] != REQUEST_SENSE) 
-                       cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); 
-                   else if (status_byte(cmd->SCp.Status) != GOOD)
-                       cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
-                   
-#ifdef AUTOSENSE
-                   if ((cmd->cmnd[0] != REQUEST_SENSE) && 
-                       (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) {
-                       ASEN_PRINTK("scsi%d: performing request sense\n",
-                                   HOSTNO);
-                       cmd->cmnd[0] = REQUEST_SENSE;
-                       cmd->cmnd[1] &= 0xe0;
-                       cmd->cmnd[2] = 0;
-                       cmd->cmnd[3] = 0;
-                       cmd->cmnd[4] = sizeof(cmd->sense_buffer);
-                       cmd->cmnd[5] = 0;
-                       cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
-
-                       cmd->use_sg = 0;
-                       /* this is initialized from initialize_SCp 
-                       cmd->SCp.buffer = NULL;
-                       cmd->SCp.buffers_residual = 0;
-                       */
-                       cmd->request_buffer = (char *) cmd->sense_buffer;
-                       cmd->request_bufflen = sizeof(cmd->sense_buffer);
+                                       /* Enable reselect interrupts */
+                                       NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+
+                                       /*
+                                        * I'm not sure what the correct thing to do here is :
+                                        *
+                                        * If the command that just executed is NOT a request
+                                        * sense, the obvious thing to do is to set the result
+                                        * code to the values of the stored parameters.
+                                        *
+                                        * If it was a REQUEST SENSE command, we need some way to
+                                        * differentiate between the failure code of the original
+                                        * and the failure code of the REQUEST sense - the obvious
+                                        * case is success, where we fall through and leave the
+                                        * result code unchanged.
+                                        *
+                                        * The non-obvious place is where the REQUEST SENSE failed
+                                        */
+
+                                       if (cmd->cmnd[0] != REQUEST_SENSE)
+                                               cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
+                                       else if (status_byte(cmd->SCp.Status) != GOOD)
+                                               cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
 
-                       local_irq_save(flags);
-                       LIST(cmd,hostdata->issue_queue);
-                       NEXT(cmd) = hostdata->issue_queue;
-                       hostdata->issue_queue = (Scsi_Cmnd *) cmd;
-                       local_irq_restore(flags);
-                       QU_PRINTK("scsi%d: REQUEST SENSE added to head of "
-                                 "issue queue\n", H_NO(cmd));
-                  } else
+#ifdef AUTOSENSE
+                                       if ((cmd->cmnd[0] != REQUEST_SENSE) &&
+                                           (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) {
+                                               ASEN_PRINTK("scsi%d: performing request sense\n", HOSTNO);
+                                               cmd->cmnd[0] = REQUEST_SENSE;
+                                               cmd->cmnd[1] &= 0xe0;
+                                               cmd->cmnd[2] = 0;
+                                               cmd->cmnd[3] = 0;
+                                               cmd->cmnd[4] = sizeof(cmd->sense_buffer);
+                                               cmd->cmnd[5] = 0;
+                                               cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
+
+                                               cmd->use_sg = 0;
+                                               /* this is initialized from initialize_SCp
+                                               cmd->SCp.buffer = NULL;
+                                               cmd->SCp.buffers_residual = 0;
+                                               */
+                                               cmd->request_buffer = (char *) cmd->sense_buffer;
+                                               cmd->request_bufflen = sizeof(cmd->sense_buffer);
+
+                                               local_irq_save(flags);
+                                               LIST(cmd,hostdata->issue_queue);
+                                               SET_NEXT(cmd, hostdata->issue_queue);
+                                               hostdata->issue_queue = (Scsi_Cmnd *) cmd;
+                                               local_irq_restore(flags);
+                                               QU_PRINTK("scsi%d: REQUEST SENSE added to head of "
+                                                         "issue queue\n", H_NO(cmd));
+                                       } else
 #endif /* def AUTOSENSE */
-                  {
+                                       {
 #ifdef NCR5380_STATS
-                      collect_stats(hostdata, cmd);
+                                               collect_stats(hostdata, cmd);
 #endif
-                      cmd->scsi_done(cmd);
-                   }
-
-                   NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-                   /* 
-                    * Restore phase bits to 0 so an interrupted selection, 
-                    * arbitration can resume.
-                    */
-                   NCR5380_write(TARGET_COMMAND_REG, 0);
-                   
-                   while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
-                       barrier();
-
-                   falcon_dont_release--;
-                   /* ++roman: For Falcon SCSI, release the lock on the
-                    * ST-DMA here if no other commands are waiting on the
-                    * disconnected queue.
-                    */
-                   falcon_release_lock_if_possible( hostdata );
-                   return;
-               case MESSAGE_REJECT:
-                   /* Accept message by clearing ACK */
-                   NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-                   /* Enable reselect interrupts */
-                   NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-                   switch (hostdata->last_message) {
-                   case HEAD_OF_QUEUE_TAG:
-                   case ORDERED_QUEUE_TAG:
-                   case SIMPLE_QUEUE_TAG:
-                       /* The target obviously doesn't support tagged
-                        * queuing, even though it announced this ability in
-                        * its INQUIRY data ?!? (maybe only this LUN?) Ok,
-                        * clear 'tagged_supported' and lock the LUN, since
-                        * the command is treated as untagged further on.
-                        */
-                       cmd->device->tagged_supported = 0;
-                       hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
-                       cmd->tag = TAG_NONE;
-                       TAG_PRINTK("scsi%d: target %d lun %d rejected "
-                                  "QUEUE_TAG message; tagged queuing "
-                                  "disabled\n",
-                                  HOSTNO, cmd->device->id, cmd->device->lun);
-                       break;
-                   }
-                   break;
-               case DISCONNECT:
-                   /* Accept message by clearing ACK */
-                   NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-                   local_irq_save(flags);
-                   cmd->device->disconnect = 1;
-                   LIST(cmd,hostdata->disconnected_queue);
-                   NEXT(cmd) = hostdata->disconnected_queue;
-                   hostdata->connected = NULL;
-                   hostdata->disconnected_queue = cmd;
-                   local_irq_restore(flags);
-                   QU_PRINTK("scsi%d: command for target %d lun %d was "
-                             "moved from connected to the "
-                             "disconnected_queue\n", HOSTNO, 
-                             cmd->device->id, cmd->device->lun);
-                   /* 
-                    * Restore phase bits to 0 so an interrupted selection, 
-                    * arbitration can resume.
-                    */
-                   NCR5380_write(TARGET_COMMAND_REG, 0);
-
-                   /* Enable reselect interrupts */
-                   NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-                   /* Wait for bus free to avoid nasty timeouts */
-                   while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
-                       barrier();
-                   return;
-               /* 
-                * The SCSI data pointer is *IMPLICITLY* saved on a disconnect
-                * operation, in violation of the SCSI spec so we can safely 
-                * ignore SAVE/RESTORE pointers calls.
-                *
-                * Unfortunately, some disks violate the SCSI spec and 
-                * don't issue the required SAVE_POINTERS message before
-                * disconnecting, and we have to break spec to remain 
-                * compatible.
-                */
-               case SAVE_POINTERS:
-               case RESTORE_POINTERS:
-                   /* Accept message by clearing ACK */
-                   NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-                   /* Enable reselect interrupts */
-                   NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-                   break;
-               case EXTENDED_MESSAGE:
-/* 
- * Extended messages are sent in the following format :
- * Byte        
- * 0           EXTENDED_MESSAGE == 1
- * 1           length (includes one byte for code, doesn't 
- *             include first two bytes)
- * 2           code
- * 3..length+1 arguments
- *
- * Start the extended message buffer with the EXTENDED_MESSAGE
- * byte, since spi_print_msg() wants the whole thing.  
- */
-                   extended_msg[0] = EXTENDED_MESSAGE;
-                   /* Accept first byte by clearing ACK */
-                   NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
-                   EXT_PRINTK("scsi%d: receiving extended message\n", HOSTNO);
-
-                   len = 2;
-                   data = extended_msg + 1;
-                   phase = PHASE_MSGIN;
-                   NCR5380_transfer_pio(instance, &phase, &len, &data);
-                   EXT_PRINTK("scsi%d: length=%d, code=0x%02x\n", HOSTNO,
-                              (int)extended_msg[1], (int)extended_msg[2]);
-
-                   if (!len && extended_msg[1] <= 
-                       (sizeof (extended_msg) - 1)) {
-                       /* Accept third byte by clearing ACK */
-                       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-                       len = extended_msg[1] - 1;
-                       data = extended_msg + 3;
-                       phase = PHASE_MSGIN;
-
-                       NCR5380_transfer_pio(instance, &phase, &len, &data);
-                       EXT_PRINTK("scsi%d: message received, residual %d\n",
-                                  HOSTNO, len);
-
-                       switch (extended_msg[2]) {
-                       case EXTENDED_SDTR:
-                       case EXTENDED_WDTR:
-                       case EXTENDED_MODIFY_DATA_POINTER:
-                       case EXTENDED_EXTENDED_IDENTIFY:
-                           tmp = 0;
-                       }
-                   } else if (len) {
-                       printk(KERN_NOTICE "scsi%d: error receiving "
-                              "extended message\n", HOSTNO);
-                       tmp = 0;
-                   } else {
-                       printk(KERN_NOTICE "scsi%d: extended message "
-                              "code %02x length %d is too long\n",
-                              HOSTNO, extended_msg[2], extended_msg[1]);
-                       tmp = 0;
-                   }
-               /* Fall through to reject message */
-
-               /* 
-                * If we get something weird that we aren't expecting, 
-                * reject it.
-                */
-               default:
-                   if (!tmp) {
-                       printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO);
-                       spi_print_msg(extended_msg);
-                       printk("\n");
-                   } else if (tmp != EXTENDED_MESSAGE)
-                       printk(KERN_DEBUG "scsi%d: rejecting unknown "
-                              "message %02x from target %d, lun %d\n",
-                              HOSTNO, tmp, cmd->device->id, cmd->device->lun);
-                   else
-                       printk(KERN_DEBUG "scsi%d: rejecting unknown "
-                              "extended message "
-                              "code %02x, length %d from target %d, lun %d\n",
-                              HOSTNO, extended_msg[1], extended_msg[0],
-                              cmd->device->id, cmd->device->lun);
-   
-
-                   msgout = MESSAGE_REJECT;
-                   NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
-                       ICR_ASSERT_ATN);
-                   break;
-               } /* switch (tmp) */
-               break;
-           case PHASE_MSGOUT:
-               len = 1;
-               data = &msgout;
-               hostdata->last_message = msgout;
-               NCR5380_transfer_pio(instance, &phase, &len, &data);
-               if (msgout == ABORT) {
+                                               cmd->scsi_done(cmd);
+                                       }
+
+                                       NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+                                       /*
+                                        * Restore phase bits to 0 so an interrupted selection,
+                                        * arbitration can resume.
+                                        */
+                                       NCR5380_write(TARGET_COMMAND_REG, 0);
+
+                                       while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
+                                               barrier();
+
+                                       falcon_dont_release--;
+                                       /* ++roman: For Falcon SCSI, release the lock on the
+                                        * ST-DMA here if no other commands are waiting on the
+                                        * disconnected queue.
+                                        */
+                                       falcon_release_lock_if_possible(hostdata);
+                                       return;
+                               case MESSAGE_REJECT:
+                                       /* Accept message by clearing ACK */
+                                       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+                                       /* Enable reselect interrupts */
+                                       NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+                                       switch (hostdata->last_message) {
+                                       case HEAD_OF_QUEUE_TAG:
+                                       case ORDERED_QUEUE_TAG:
+                                       case SIMPLE_QUEUE_TAG:
+                                               /* The target obviously doesn't support tagged
+                                                * queuing, even though it announced this ability in
+                                                * its INQUIRY data ?!? (maybe only this LUN?) Ok,
+                                                * clear 'tagged_supported' and lock the LUN, since
+                                                * the command is treated as untagged further on.
+                                                */
+                                               cmd->device->tagged_supported = 0;
+                                               hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
+                                               cmd->tag = TAG_NONE;
+                                               TAG_PRINTK("scsi%d: target %d lun %d rejected "
+                                                          "QUEUE_TAG message; tagged queuing "
+                                                          "disabled\n",
+                                                          HOSTNO, cmd->device->id, cmd->device->lun);
+                                               break;
+                                       }
+                                       break;
+                               case DISCONNECT:
+                                       /* Accept message by clearing ACK */
+                                       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+                                       local_irq_save(flags);
+                                       cmd->device->disconnect = 1;
+                                       LIST(cmd,hostdata->disconnected_queue);
+                                       SET_NEXT(cmd, hostdata->disconnected_queue);
+                                       hostdata->connected = NULL;
+                                       hostdata->disconnected_queue = cmd;
+                                       local_irq_restore(flags);
+                                       QU_PRINTK("scsi%d: command for target %d lun %d was "
+                                                 "moved from connected to the "
+                                                 "disconnected_queue\n", HOSTNO,
+                                                 cmd->device->id, cmd->device->lun);
+                                       /*
+                                        * Restore phase bits to 0 so an interrupted selection,
+                                        * arbitration can resume.
+                                        */
+                                       NCR5380_write(TARGET_COMMAND_REG, 0);
+
+                                       /* Enable reselect interrupts */
+                                       NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+                                       /* Wait for bus free to avoid nasty timeouts */
+                                       while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
+                                               barrier();
+                                       return;
+                                       /*
+                                        * The SCSI data pointer is *IMPLICITLY* saved on a disconnect
+                                        * operation, in violation of the SCSI spec so we can safely
+                                        * ignore SAVE/RESTORE pointers calls.
+                                        *
+                                        * Unfortunately, some disks violate the SCSI spec and
+                                        * don't issue the required SAVE_POINTERS message before
+                                        * disconnecting, and we have to break spec to remain
+                                        * compatible.
+                                        */
+                               case SAVE_POINTERS:
+                               case RESTORE_POINTERS:
+                                       /* Accept message by clearing ACK */
+                                       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+                                       /* Enable reselect interrupts */
+                                       NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+                                       break;
+                               case EXTENDED_MESSAGE:
+                                       /*
+                                        * Extended messages are sent in the following format :
+                                        * Byte
+                                        * 0            EXTENDED_MESSAGE == 1
+                                        * 1            length (includes one byte for code, doesn't
+                                        *              include first two bytes)
+                                        * 2            code
+                                        * 3..length+1  arguments
+                                        *
+                                        * Start the extended message buffer with the EXTENDED_MESSAGE
+                                        * byte, since spi_print_msg() wants the whole thing.
+                                        */
+                                       extended_msg[0] = EXTENDED_MESSAGE;
+                                       /* Accept first byte by clearing ACK */
+                                       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+
+                                       EXT_PRINTK("scsi%d: receiving extended message\n", HOSTNO);
+
+                                       len = 2;
+                                       data = extended_msg + 1;
+                                       phase = PHASE_MSGIN;
+                                       NCR5380_transfer_pio(instance, &phase, &len, &data);
+                                       EXT_PRINTK("scsi%d: length=%d, code=0x%02x\n", HOSTNO,
+                                                  (int)extended_msg[1], (int)extended_msg[2]);
+
+                                       if (!len && extended_msg[1] <=
+                                           (sizeof(extended_msg) - 1)) {
+                                               /* Accept third byte by clearing ACK */
+                                               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+                                               len = extended_msg[1] - 1;
+                                               data = extended_msg + 3;
+                                               phase = PHASE_MSGIN;
+
+                                               NCR5380_transfer_pio(instance, &phase, &len, &data);
+                                               EXT_PRINTK("scsi%d: message received, residual %d\n",
+                                                          HOSTNO, len);
+
+                                               switch (extended_msg[2]) {
+                                               case EXTENDED_SDTR:
+                                               case EXTENDED_WDTR:
+                                               case EXTENDED_MODIFY_DATA_POINTER:
+                                               case EXTENDED_EXTENDED_IDENTIFY:
+                                                       tmp = 0;
+                                               }
+                                       } else if (len) {
+                                               printk(KERN_NOTICE "scsi%d: error receiving "
+                                                      "extended message\n", HOSTNO);
+                                               tmp = 0;
+                                       } else {
+                                               printk(KERN_NOTICE "scsi%d: extended message "
+                                                          "code %02x length %d is too long\n",
+                                                          HOSTNO, extended_msg[2], extended_msg[1]);
+                                               tmp = 0;
+                                       }
+                                       /* Fall through to reject message */
+
+                                       /*
+                                        * If we get something weird that we aren't expecting,
+                                        * reject it.
+                                        */
+                               default:
+                                       if (!tmp) {
+                                               printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO);
+                                               spi_print_msg(extended_msg);
+                                               printk("\n");
+                                       } else if (tmp != EXTENDED_MESSAGE)
+                                               printk(KERN_DEBUG "scsi%d: rejecting unknown "
+                                                      "message %02x from target %d, lun %d\n",
+                                                      HOSTNO, tmp, cmd->device->id, cmd->device->lun);
+                                       else
+                                               printk(KERN_DEBUG "scsi%d: rejecting unknown "
+                                                      "extended message "
+                                                      "code %02x, length %d from target %d, lun %d\n",
+                                                      HOSTNO, extended_msg[1], extended_msg[0],
+                                                      cmd->device->id, cmd->device->lun);
+
+
+                                       msgout = MESSAGE_REJECT;
+                                       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
+                                       break;
+                               } /* switch (tmp) */
+                               break;
+                       case PHASE_MSGOUT:
+                               len = 1;
+                               data = &msgout;
+                               hostdata->last_message = msgout;
+                               NCR5380_transfer_pio(instance, &phase, &len, &data);
+                               if (msgout == ABORT) {
 #ifdef SUPPORT_TAGS
-                   cmd_free_tag( cmd );
+                                       cmd_free_tag(cmd);
 #else
-                   hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+                                       hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
 #endif
-                   hostdata->connected = NULL;
-                   cmd->result = DID_ERROR << 16;
+                                       hostdata->connected = NULL;
+                                       cmd->result = DID_ERROR << 16;
 #ifdef NCR5380_STATS
-                   collect_stats(hostdata, cmd);
+                                       collect_stats(hostdata, cmd);
 #endif
-                   cmd->scsi_done(cmd);
-                   NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-                   falcon_release_lock_if_possible( hostdata );
-                   return;
-               }
-               msgout = NOP;
-               break;
-           case PHASE_CMDOUT:
-               len = cmd->cmd_len;
-               data = cmd->cmnd;
-               /* 
-                * XXX for performance reasons, on machines with a 
-                * PSEUDO-DMA architecture we should probably 
-                * use the dma transfer function.  
-                */
-               NCR5380_transfer_pio(instance, &phase, &len, 
-                   &data);
-               break;
-           case PHASE_STATIN:
-               len = 1;
-               data = &tmp;
-               NCR5380_transfer_pio(instance, &phase, &len, &data);
-               cmd->SCp.Status = tmp;
-               break;
-           default:
-               printk("scsi%d: unknown phase\n", HOSTNO);
-               NCR_PRINT(NDEBUG_ANY);
-           } /* switch(phase) */
-       } /* if (tmp * SR_REQ) */ 
-    } /* while (1) */
+                                       cmd->scsi_done(cmd);
+                                       NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+                                       falcon_release_lock_if_possible(hostdata);
+                                       return;
+                               }
+                               msgout = NOP;
+                               break;
+                       case PHASE_CMDOUT:
+                               len = cmd->cmd_len;
+                               data = cmd->cmnd;
+                               /*
+                                * XXX for performance reasons, on machines with a
+                                * PSEUDO-DMA architecture we should probably
+                                * use the dma transfer function.
+                                */
+                               NCR5380_transfer_pio(instance, &phase, &len, &data);
+                               break;
+                       case PHASE_STATIN:
+                               len = 1;
+                               data = &tmp;
+                               NCR5380_transfer_pio(instance, &phase, &len, &data);
+                               cmd->SCp.Status = tmp;
+                               break;
+                       default:
+                               printk("scsi%d: unknown phase\n", HOSTNO);
+                               NCR_PRINT(NDEBUG_ANY);
+                       } /* switch(phase) */
+               } /* if (tmp * SR_REQ) */
+       } /* while (1) */
 }
 
 /*
  * Function : void NCR5380_reselect (struct Scsi_Host *instance)
  *
- * Purpose : does reselection, initializing the instance->connected 
- *     field to point to the Scsi_Cmnd for which the I_T_L or I_T_L_Q 
+ * Purpose : does reselection, initializing the instance->connected
+ *     field to point to the Scsi_Cmnd for which the I_T_L or I_T_L_Q
  *     nexus has been reestablished,
- *     
+ *
  * Inputs : instance - this instance of the NCR5380.
  *
  */
 
 
-static void NCR5380_reselect (struct Scsi_Host *instance)
+static void NCR5380_reselect(struct Scsi_Host *instance)
 {
-    SETUP_HOSTDATA(instance);
-    unsigned char target_mask;
-    unsigned char lun, phase;
-    int len;
+       SETUP_HOSTDATA(instance);
+       unsigned char target_mask;
+       unsigned char lun, phase;
+       int len;
 #ifdef SUPPORT_TAGS
-    unsigned char tag;
+       unsigned char tag;
 #endif
-    unsigned char msg[3];
-    unsigned char *data;
-    Scsi_Cmnd *tmp = NULL, *prev;
-/*    unsigned long flags; */
-
-    /*
-     * Disable arbitration, etc. since the host adapter obviously
-     * lost, and tell an interrupted NCR5380_select() to restart.
-     */
-
-    NCR5380_write(MODE_REG, MR_BASE);
-    hostdata->restart_select = 1;
-
-    target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask);
-
-    RSL_PRINTK("scsi%d: reselect\n", HOSTNO);
-
-    /* 
-     * At this point, we have detected that our SCSI ID is on the bus,
-     * SEL is true and BSY was false for at least one bus settle delay
-     * (400 ns).
-     *
-     * We must assert BSY ourselves, until the target drops the SEL
-     * signal.
-     */
-
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
-    
-    while (NCR5380_read(STATUS_REG) & SR_SEL);
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
-    /*
-     * Wait for target to go into MSGIN.
-     */
-
-    while (!(NCR5380_read(STATUS_REG) & SR_REQ));
-
-    len = 1;
-    data = msg;
-    phase = PHASE_MSGIN;
-    NCR5380_transfer_pio(instance, &phase, &len, &data);
-
-    if (!(msg[0] & 0x80)) {
-       printk(KERN_DEBUG "scsi%d: expecting IDENTIFY message, got ", HOSTNO);
-       spi_print_msg(msg);
-       do_abort(instance);
-       return;
-    }
-    lun = (msg[0] & 0x07);
+       unsigned char msg[3];
+       unsigned char *data;
+       Scsi_Cmnd *tmp = NULL, *prev;
+/*     unsigned long flags; */
+
+       /*
+        * Disable arbitration, etc. since the host adapter obviously
+        * lost, and tell an interrupted NCR5380_select() to restart.
+        */
+
+       NCR5380_write(MODE_REG, MR_BASE);
+       hostdata->restart_select = 1;
+
+       target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask);
+
+       RSL_PRINTK("scsi%d: reselect\n", HOSTNO);
+
+       /*
+        * At this point, we have detected that our SCSI ID is on the bus,
+        * SEL is true and BSY was false for at least one bus settle delay
+        * (400 ns).
+        *
+        * We must assert BSY ourselves, until the target drops the SEL
+        * signal.
+        */
+
+       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
+
+       while (NCR5380_read(STATUS_REG) & SR_SEL)
+               ;
+       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+
+       /*
+        * Wait for target to go into MSGIN.
+        */
+
+       while (!(NCR5380_read(STATUS_REG) & SR_REQ))
+               ;
+
+       len = 1;
+       data = msg;
+       phase = PHASE_MSGIN;
+       NCR5380_transfer_pio(instance, &phase, &len, &data);
+
+       if (!(msg[0] & 0x80)) {
+               printk(KERN_DEBUG "scsi%d: expecting IDENTIFY message, got ", HOSTNO);
+               spi_print_msg(msg);
+               do_abort(instance);
+               return;
+       }
+       lun = (msg[0] & 0x07);
 
 #ifdef SUPPORT_TAGS
-    /* If the phase is still MSGIN, the target wants to send some more
-     * messages. In case it supports tagged queuing, this is probably a
-     * SIMPLE_QUEUE_TAG for the I_T_L_Q nexus.
-     */
-    tag = TAG_NONE;
-    if (phase == PHASE_MSGIN && setup_use_tagged_queuing) {
-       /* Accept previous IDENTIFY message by clearing ACK */
-       NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
-       len = 2;
-       data = msg+1;
-       if (!NCR5380_transfer_pio(instance, &phase, &len, &data) &&
-           msg[1] == SIMPLE_QUEUE_TAG)
-           tag = msg[2];
-       TAG_PRINTK("scsi%d: target mask %02x, lun %d sent tag %d at "
-                  "reselection\n", HOSTNO, target_mask, lun, tag);
-    }
+       /* If the phase is still MSGIN, the target wants to send some more
+        * messages. In case it supports tagged queuing, this is probably a
+        * SIMPLE_QUEUE_TAG for the I_T_L_Q nexus.
+        */
+       tag = TAG_NONE;
+       if (phase == PHASE_MSGIN && setup_use_tagged_queuing) {
+               /* Accept previous IDENTIFY message by clearing ACK */
+               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+               len = 2;
+               data = msg + 1;
+               if (!NCR5380_transfer_pio(instance, &phase, &len, &data) &&
+                   msg[1] == SIMPLE_QUEUE_TAG)
+                       tag = msg[2];
+               TAG_PRINTK("scsi%d: target mask %02x, lun %d sent tag %d at "
+                          "reselection\n", HOSTNO, target_mask, lun, tag);
+       }
 #endif
-    
-    /* 
-     * Find the command corresponding to the I_T_L or I_T_L_Q  nexus we 
-     * just reestablished, and remove it from the disconnected queue.
-     */
-
-    for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; 
-        tmp; prev = tmp, tmp = NEXT(tmp) ) {
-       if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun)
+
+       /*
+        * Find the command corresponding to the I_T_L or I_T_L_Q  nexus we
+        * just reestablished, and remove it from the disconnected queue.
+        */
+
+       for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL;
+            tmp; prev = tmp, tmp = NEXT(tmp)) {
+               if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun)
 #ifdef SUPPORT_TAGS
-           && (tag == tmp->tag) 
+                   && (tag == tmp->tag)
 #endif
-           ) {
-           /* ++guenther: prevent race with falcon_release_lock */
-           falcon_dont_release++;
-           if (prev) {
-               REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
-               NEXT(prev) = NEXT(tmp);
-           } else {
-               REMOVE(-1, hostdata->disconnected_queue, tmp, NEXT(tmp));
-               hostdata->disconnected_queue = NEXT(tmp);
-           }
-           NEXT(tmp) = NULL;
-           break;
+                   ) {
+                       /* ++guenther: prevent race with falcon_release_lock */
+                       falcon_dont_release++;
+                       if (prev) {
+                               REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
+                               SET_NEXT(prev, NEXT(tmp));
+                       } else {
+                               REMOVE(-1, hostdata->disconnected_queue, tmp, NEXT(tmp));
+                               hostdata->disconnected_queue = NEXT(tmp);
+                       }
+                       SET_NEXT(tmp, NULL);
+                       break;
+               }
        }
-    }
-    
-    if (!tmp) {
-       printk(KERN_WARNING "scsi%d: warning: target bitmask %02x lun %d "
+
+       if (!tmp) {
+               printk(KERN_WARNING "scsi%d: warning: target bitmask %02x lun %d "
 #ifdef SUPPORT_TAGS
-               "tag %d "
+                      "tag %d "
 #endif
-               "not in disconnected_queue.\n",
-               HOSTNO, target_mask, lun
+                      "not in disconnected_queue.\n",
+                      HOSTNO, target_mask, lun
 #ifdef SUPPORT_TAGS
-               , tag
+                      , tag
 #endif
-               );
-       /* 
-        * Since we have an established nexus that we can't do anything
-        * with, we must abort it.  
-        */
-       do_abort(instance);
-       return;
-    }
+                       );
+               /*
+                * Since we have an established nexus that we can't do anything
+                * with, we must abort it.
+                */
+               do_abort(instance);
+               return;
+       }
 
-    /* Accept message by clearing ACK */
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+       /* Accept message by clearing ACK */
+       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 
-    hostdata->connected = tmp;
-    RSL_PRINTK("scsi%d: nexus established, target = %d, lun = %d, tag = %d\n",
-              HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag);
-    falcon_dont_release--;
+       hostdata->connected = tmp;
+       RSL_PRINTK("scsi%d: nexus established, target = %d, lun = %d, tag = %d\n",
+                  HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag);
+       falcon_dont_release--;
 }
 
 
@@ -2626,362 +2677,361 @@ static void NCR5380_reselect (struct Scsi_Host *instance)
  *
  * Purpose : abort a command
  *
- * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the 
- *     host byte of the result field to, if zero DID_ABORTED is 
+ * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the
+ *     host byte of the result field to, if zero DID_ABORTED is
  *     used.
  *
  * Returns : 0 - success, -1 on failure.
  *
- * XXX - there is no way to abort the command that is currently 
- *      connected, you have to wait for it to complete.  If this is 
+ * XXX - there is no way to abort the command that is currently
+ *      connected, you have to wait for it to complete.  If this is
  *      a problem, we could implement longjmp() / setjmp(), setjmp()
- *      called where the loop started in NCR5380_main().
+ *      called where the loop started in NCR5380_main().
  */
 
 static
-int NCR5380_abort (Scsi_Cmnd *cmd)
+int NCR5380_abort(Scsi_Cmnd *cmd)
 {
-    struct Scsi_Host *instance = cmd->device->host;
-    SETUP_HOSTDATA(instance);
-    Scsi_Cmnd *tmp, **prev;
-    unsigned long flags;
+       struct Scsi_Host *instance = cmd->device->host;
+       SETUP_HOSTDATA(instance);
+       Scsi_Cmnd *tmp, **prev;
+       unsigned long flags;
+
+       printk(KERN_NOTICE "scsi%d: aborting command\n", HOSTNO);
+       scsi_print_command(cmd);
 
-    printk(KERN_NOTICE "scsi%d: aborting command\n", HOSTNO);
-    scsi_print_command(cmd);
+       NCR5380_print_status(instance);
 
-    NCR5380_print_status (instance);
+       local_irq_save(flags);
 
-    local_irq_save(flags);
-    
-    if (!IS_A_TT() && !falcon_got_lock)
-       printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_abort\n",
-              HOSTNO);
+       if (!IS_A_TT() && !falcon_got_lock)
+               printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_abort\n",
+                      HOSTNO);
 
-    ABRT_PRINTK("scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO,
-               NCR5380_read(BUS_AND_STATUS_REG),
-               NCR5380_read(STATUS_REG));
+       ABRT_PRINTK("scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO,
+                   NCR5380_read(BUS_AND_STATUS_REG),
+                   NCR5380_read(STATUS_REG));
 
 #if 1
-/* 
- * Case 1 : If the command is the currently executing command, 
- * we'll set the aborted flag and return control so that 
- * information transfer routine can exit cleanly.
- */
+       /*
+        * Case 1 : If the command is the currently executing command,
+        * we'll set the aborted flag and return control so that
       * information transfer routine can exit cleanly.
       */
 
-    if (hostdata->connected == cmd) {
+       if (hostdata->connected == cmd) {
 
-       ABRT_PRINTK("scsi%d: aborting connected command\n", HOSTNO);
-/*
- * We should perform BSY checking, and make sure we haven't slipped
- * into BUS FREE.
- */
+               ABRT_PRINTK("scsi%d: aborting connected command\n", HOSTNO);
+               /*
               * We should perform BSY checking, and make sure we haven't slipped
               * into BUS FREE.
               */
 
-/*     NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_ATN); */
-/* 
- * Since we can't change phases until we've completed the current 
- * handshake, we have to source or sink a byte of data if the current
- * phase is not MSGOUT.
- */
+               /*      NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_ATN); */
+               /*
+                * Since we can't change phases until we've completed the current
               * handshake, we have to source or sink a byte of data if the current
               * phase is not MSGOUT.
               */
 
-/* 
- * Return control to the executing NCR drive so we can clear the
- * aborted flag and get back into our main loop.
- */ 
+               /*
               * Return control to the executing NCR drive so we can clear the
               * aborted flag and get back into our main loop.
+                */
 
-       if (do_abort(instance) == 0) {
-         hostdata->aborted = 1;
-         hostdata->connected = NULL;
-         cmd->result = DID_ABORT << 16;
+               if (do_abort(instance) == 0) {
+                       hostdata->aborted = 1;
+                       hostdata->connected = NULL;
+                       cmd->result = DID_ABORT << 16;
 #ifdef SUPPORT_TAGS
-         cmd_free_tag( cmd );
+                       cmd_free_tag(cmd);
 #else
-         hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+                       hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
 #endif
-         local_irq_restore(flags);
-         cmd->scsi_done(cmd);
-         falcon_release_lock_if_possible( hostdata );
-         return SCSI_ABORT_SUCCESS;
-       } else {
-/*       local_irq_restore(flags); */
-         printk("scsi%d: abort of connected command failed!\n", HOSTNO);
-         return SCSI_ABORT_ERROR;
-       } 
-   }
+                       local_irq_restore(flags);
+                       cmd->scsi_done(cmd);
+                       falcon_release_lock_if_possible(hostdata);
+                       return SCSI_ABORT_SUCCESS;
+               } else {
+/*                     local_irq_restore(flags); */
+                       printk("scsi%d: abort of connected command failed!\n", HOSTNO);
+                       return SCSI_ABORT_ERROR;
+               }
+       }
 #endif
 
-/* 
- * Case 2 : If the command hasn't been issued yet, we simply remove it 
- *         from the issue queue.
- */
-    for (prev = (Scsi_Cmnd **) &(hostdata->issue_queue), 
-       tmp = (Scsi_Cmnd *) hostdata->issue_queue;
-       tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp) )
-       if (cmd == tmp) {
-           REMOVE(5, *prev, tmp, NEXT(tmp));
-           (*prev) = NEXT(tmp);
-           NEXT(tmp) = NULL;
-           tmp->result = DID_ABORT << 16;
-           local_irq_restore(flags);
-           ABRT_PRINTK("scsi%d: abort removed command from issue queue.\n",
-                       HOSTNO);
-           /* Tagged queuing note: no tag to free here, hasn't been assigned
-            * yet... */
-           tmp->scsi_done(tmp);
-           falcon_release_lock_if_possible( hostdata );
-           return SCSI_ABORT_SUCCESS;
+       /*
+        * Case 2 : If the command hasn't been issued yet, we simply remove it
+        *          from the issue queue.
+        */
+       for (prev = (Scsi_Cmnd **)&(hostdata->issue_queue),
+            tmp = (Scsi_Cmnd *)hostdata->issue_queue;
+            tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) {
+               if (cmd == tmp) {
+                       REMOVE(5, *prev, tmp, NEXT(tmp));
+                       (*prev) = NEXT(tmp);
+                       SET_NEXT(tmp, NULL);
+                       tmp->result = DID_ABORT << 16;
+                       local_irq_restore(flags);
+                       ABRT_PRINTK("scsi%d: abort removed command from issue queue.\n",
+                                   HOSTNO);
+                       /* Tagged queuing note: no tag to free here, hasn't been assigned
+                        * yet... */
+                       tmp->scsi_done(tmp);
+                       falcon_release_lock_if_possible(hostdata);
+                       return SCSI_ABORT_SUCCESS;
+               }
        }
 
-/* 
- * Case 3 : If any commands are connected, we're going to fail the abort
- *         and let the high level SCSI driver retry at a later time or 
*         issue a reset.
- *
*         Timeouts, and therefore aborted commands, will be highly unlikely
- *          and handling them cleanly in this situation would make the common
*         case of noresets less efficient, and would pollute our code.  So,
*         we fail.
- */
+       /*
       * Case 3 : If any commands are connected, we're going to fail the abort
+        *          and let the high level SCSI driver retry at a later time or
       *          issue a reset.
       *
       *          Timeouts, and therefore aborted commands, will be highly unlikely
       *          and handling them cleanly in this situation would make the common
       *          case of noresets less efficient, and would pollute our code.  So,
       *          we fail.
       */
 
-    if (hostdata->connected) {
-       local_irq_restore(flags);
-       ABRT_PRINTK("scsi%d: abort failed, command connected.\n", HOSTNO);
-        return SCSI_ABORT_SNOOZE;
-    }
+       if (hostdata->connected) {
+               local_irq_restore(flags);
+               ABRT_PRINTK("scsi%d: abort failed, command connected.\n", HOSTNO);
+               return SCSI_ABORT_SNOOZE;
+       }
 
-/*
- * Case 4: If the command is currently disconnected from the bus, and 
- *     there are no connected commands, we reconnect the I_T_L or 
- *     I_T_L_Q nexus associated with it, go into message out, and send 
- *      an abort message.
- *
- * This case is especially ugly. In order to reestablish the nexus, we
- * need to call NCR5380_select().  The easiest way to implement this 
- * function was to abort if the bus was busy, and let the interrupt
- * handler triggered on the SEL for reselect take care of lost arbitrations
- * where necessary, meaning interrupts need to be enabled.
- *
- * When interrupts are enabled, the queues may change - so we 
- * can't remove it from the disconnected queue before selecting it
- * because that could cause a failure in hashing the nexus if that 
- * device reselected.
- * 
- * Since the queues may change, we can't use the pointers from when we
- * first locate it.
- *
- * So, we must first locate the command, and if NCR5380_select()
- * succeeds, then issue the abort, relocate the command and remove
- * it from the disconnected queue.
- */
+       /*
+        * Case 4: If the command is currently disconnected from the bus, and
+        *      there are no connected commands, we reconnect the I_T_L or
+        *      I_T_L_Q nexus associated with it, go into message out, and send
+        *      an abort message.
+        *
+        * This case is especially ugly. In order to reestablish the nexus, we
+        * need to call NCR5380_select().  The easiest way to implement this
+        * function was to abort if the bus was busy, and let the interrupt
+        * handler triggered on the SEL for reselect take care of lost arbitrations
+        * where necessary, meaning interrupts need to be enabled.
+        *
+        * When interrupts are enabled, the queues may change - so we
+        * can't remove it from the disconnected queue before selecting it
+        * because that could cause a failure in hashing the nexus if that
+        * device reselected.
+        *
+        * Since the queues may change, we can't use the pointers from when we
+        * first locate it.
+        *
+        * So, we must first locate the command, and if NCR5380_select()
+        * succeeds, then issue the abort, relocate the command and remove
+        * it from the disconnected queue.
+        */
+
+       for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp;
+            tmp = NEXT(tmp)) {
+               if (cmd == tmp) {
+                       local_irq_restore(flags);
+                       ABRT_PRINTK("scsi%d: aborting disconnected command.\n", HOSTNO);
 
-    for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp;
-        tmp = NEXT(tmp)) 
-        if (cmd == tmp) {
-            local_irq_restore(flags);
-           ABRT_PRINTK("scsi%d: aborting disconnected command.\n", HOSTNO);
-  
-            if (NCR5380_select (instance, cmd, (int) cmd->tag)) 
-               return SCSI_ABORT_BUSY;
-
-           ABRT_PRINTK("scsi%d: nexus reestablished.\n", HOSTNO);
-
-           do_abort (instance);
-
-           local_irq_save(flags);
-           for (prev = (Scsi_Cmnd **) &(hostdata->disconnected_queue), 
-               tmp = (Scsi_Cmnd *) hostdata->disconnected_queue;
-               tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp) )
-                   if (cmd == tmp) {
-                   REMOVE(5, *prev, tmp, NEXT(tmp));
-                   *prev = NEXT(tmp);
-                   NEXT(tmp) = NULL;
-                   tmp->result = DID_ABORT << 16;
-                   /* We must unlock the tag/LUN immediately here, since the
-                    * target goes to BUS FREE and doesn't send us another
-                    * message (COMMAND_COMPLETE or the like)
-                    */
+                       if (NCR5380_select(instance, cmd, (int)cmd->tag))
+                               return SCSI_ABORT_BUSY;
+
+                       ABRT_PRINTK("scsi%d: nexus reestablished.\n", HOSTNO);
+
+                       do_abort(instance);
+
+                       local_irq_save(flags);
+                       for (prev = (Scsi_Cmnd **)&(hostdata->disconnected_queue),
+                            tmp = (Scsi_Cmnd *)hostdata->disconnected_queue;
+                            tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) {
+                               if (cmd == tmp) {
+                                       REMOVE(5, *prev, tmp, NEXT(tmp));
+                                       *prev = NEXT(tmp);
+                                       SET_NEXT(tmp, NULL);
+                                       tmp->result = DID_ABORT << 16;
+                                       /* We must unlock the tag/LUN immediately here, since the
+                                        * target goes to BUS FREE and doesn't send us another
+                                        * message (COMMAND_COMPLETE or the like)
+                                        */
 #ifdef SUPPORT_TAGS
-                   cmd_free_tag( tmp );
+                                       cmd_free_tag(tmp);
 #else
-                   hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+                                       hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
 #endif
-                   local_irq_restore(flags);
-                   tmp->scsi_done(tmp);
-                   falcon_release_lock_if_possible( hostdata );
-                   return SCSI_ABORT_SUCCESS;
+                                       local_irq_restore(flags);
+                                       tmp->scsi_done(tmp);
+                                       falcon_release_lock_if_possible(hostdata);
+                                       return SCSI_ABORT_SUCCESS;
+                               }
+                       }
                }
        }
 
-/*
- * Case 5 : If we reached this point, the command was not found in any of 
*         the queues.
- *
- * We probably reached this point because of an unlikely race condition
- * between the command completing successfully and the abortion code,
- * so we won't panic, but we will notify the user in case something really
- * broke.
- */
+       /*
+        * Case 5 : If we reached this point, the command was not found in any of
       *          the queues.
       *
       * We probably reached this point because of an unlikely race condition
       * between the command completing successfully and the abortion code,
       * so we won't panic, but we will notify the user in case something really
       * broke.
       */
 
-    local_irq_restore(flags);
-    printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n"
-           KERN_INFO "        before abortion\n", HOSTNO); 
+       local_irq_restore(flags);
+       printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n"
+              KERN_INFO "        before abortion\n", HOSTNO);
 
-/* Maybe it is sufficient just to release the ST-DMA lock... (if
- * possible at all) At least, we should check if the lock could be
- * released after the abort, in case it is kept due to some bug.
- */
-    falcon_release_lock_if_possible( hostdata );
+       /* Maybe it is sufficient just to release the ST-DMA lock... (if
       * possible at all) At least, we should check if the lock could be
       * released after the abort, in case it is kept due to some bug.
       */
+       falcon_release_lock_if_possible(hostdata);
 
-    return SCSI_ABORT_NOT_RUNNING;
+       return SCSI_ABORT_NOT_RUNNING;
 }
 
 
-/* 
+/*
  * Function : int NCR5380_reset (Scsi_Cmnd *cmd)
- * 
+ *
  * Purpose : reset the SCSI bus.
  *
  * Returns : SCSI_RESET_WAKEUP
  *
- */ 
+ */
 
-static int NCR5380_bus_reset( Scsi_Cmnd *cmd)
+static int NCR5380_bus_reset(Scsi_Cmnd *cmd)
 {
-    SETUP_HOSTDATA(cmd->device->host);
-    int           i;
-    unsigned long flags;
+       SETUP_HOSTDATA(cmd->device->host);
+       int i;
+       unsigned long flags;
 #if 1
-    Scsi_Cmnd *connected, *disconnected_queue;
+       Scsi_Cmnd *connected, *disconnected_queue;
 #endif
 
-    if (!IS_A_TT() && !falcon_got_lock)
-       printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_reset\n",
-              H_NO(cmd) );
-
-    NCR5380_print_status (cmd->device->host);
-
-    /* get in phase */
-    NCR5380_write( TARGET_COMMAND_REG,
-                  PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
-    /* assert RST */
-    NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );
-    udelay (40);
-    /* reset NCR registers */
-    NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
-    NCR5380_write( MODE_REG, MR_BASE );
-    NCR5380_write( TARGET_COMMAND_REG, 0 );
-    NCR5380_write( SELECT_ENABLE_REG, 0 );
-    /* ++roman: reset interrupt condition! otherwise no interrupts don't get
-     * through anymore ... */
-    (void)NCR5380_read( RESET_PARITY_INTERRUPT_REG );
-
-#if 1 /* XXX Should now be done by midlevel code, but it's broken XXX */
-      /* XXX see below                                            XXX */
-
-    /* MSch: old-style reset: actually abort all command processing here */
-
-    /* After the reset, there are no more connected or disconnected commands
-     * and no busy units; to avoid problems with re-inserting the commands
-     * into the issue_queue (via scsi_done()), the aborted commands are
-     * remembered in local variables first.
-     */
-    local_irq_save(flags);
-    connected = (Scsi_Cmnd *)hostdata->connected;
-    hostdata->connected = NULL;
-    disconnected_queue = (Scsi_Cmnd *)hostdata->disconnected_queue;
-    hostdata->disconnected_queue = NULL;
+       if (!IS_A_TT() && !falcon_got_lock)
+               printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_reset\n",
+                      H_NO(cmd));
+
+       NCR5380_print_status(cmd->device->host);
+
+       /* get in phase */
+       NCR5380_write(TARGET_COMMAND_REG,
+                     PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG)));
+       /* assert RST */
+       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
+       udelay(40);
+       /* reset NCR registers */
+       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+       NCR5380_write(MODE_REG, MR_BASE);
+       NCR5380_write(TARGET_COMMAND_REG, 0);
+       NCR5380_write(SELECT_ENABLE_REG, 0);
+       /* ++roman: reset interrupt condition! otherwise no interrupts don't get
+        * through anymore ... */
+       (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+
+#if 1  /* XXX Should now be done by midlevel code, but it's broken XXX */
+       /* XXX see below                                            XXX */
+
+       /* MSch: old-style reset: actually abort all command processing here */
+
+       /* After the reset, there are no more connected or disconnected commands
+        * and no busy units; to avoid problems with re-inserting the commands
+        * into the issue_queue (via scsi_done()), the aborted commands are
+        * remembered in local variables first.
+        */
+       local_irq_save(flags);
+       connected = (Scsi_Cmnd *)hostdata->connected;
+       hostdata->connected = NULL;
+       disconnected_queue = (Scsi_Cmnd *)hostdata->disconnected_queue;
+       hostdata->disconnected_queue = NULL;
 #ifdef SUPPORT_TAGS
-    free_all_tags();
+       free_all_tags();
 #endif
-    for( i = 0; i < 8; ++i )
-       hostdata->busy[i] = 0;
+       for (i = 0; i < 8; ++i)
+               hostdata->busy[i] = 0;
 #ifdef REAL_DMA
-    hostdata->dma_len = 0;
+       hostdata->dma_len = 0;
 #endif
-    local_irq_restore(flags);
-
-    /* In order to tell the mid-level code which commands were aborted, 
-     * set the command status to DID_RESET and call scsi_done() !!!
-     * This ultimately aborts processing of these commands in the mid-level.
-     */
-
-    if ((cmd = connected)) {
-       ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd));
-       cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
-       cmd->scsi_done( cmd );
-    }
-
-    for (i = 0; (cmd = disconnected_queue); ++i) {
-       disconnected_queue = NEXT(cmd);
-       NEXT(cmd) = NULL;
-       cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
-       cmd->scsi_done( cmd );
-    }
-    if (i > 0)
-       ABRT_PRINTK("scsi: reset aborted %d disconnected command(s)\n", i);
-
-/* The Falcon lock should be released after a reset...
- */
-/* ++guenther: moved to atari_scsi_reset(), to prevent a race between
- * unlocking and enabling dma interrupt.
- */
-/*    falcon_release_lock_if_possible( hostdata );*/
+       local_irq_restore(flags);
+
+       /* In order to tell the mid-level code which commands were aborted,
+        * set the command status to DID_RESET and call scsi_done() !!!
+        * This ultimately aborts processing of these commands in the mid-level.
+        */
+
+       if ((cmd = connected)) {
+               ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd));
+               cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
+               cmd->scsi_done(cmd);
+       }
 
-    /* since all commands have been explicitly terminated, we need to tell
-     * the midlevel code that the reset was SUCCESSFUL, and there is no 
-     * need to 'wake up' the commands by a request_sense
-     */
-    return SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET;
+       for (i = 0; (cmd = disconnected_queue); ++i) {
+               disconnected_queue = NEXT(cmd);
+               SET_NEXT(cmd, NULL);
+               cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
+               cmd->scsi_done(cmd);
+       }
+       if (i > 0)
+               ABRT_PRINTK("scsi: reset aborted %d disconnected command(s)\n", i);
+
+       /* The Falcon lock should be released after a reset...
+        */
+       /* ++guenther: moved to atari_scsi_reset(), to prevent a race between
+        * unlocking and enabling dma interrupt.
+        */
+/*     falcon_release_lock_if_possible( hostdata );*/
+
+       /* since all commands have been explicitly terminated, we need to tell
+        * the midlevel code that the reset was SUCCESSFUL, and there is no
+        * need to 'wake up' the commands by a request_sense
+        */
+       return SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET;
 #else /* 1 */
 
-    /* MSch: new-style reset handling: let the mid-level do what it can */
-
-    /* ++guenther: MID-LEVEL IS STILL BROKEN.
-     * Mid-level is supposed to requeue all commands that were active on the
-     * various low-level queues. In fact it does this, but that's not enough
-     * because all these commands are subject to timeout. And if a timeout
-     * happens for any removed command, *_abort() is called but all queues
-     * are now empty. Abort then gives up the falcon lock, which is fatal,
-     * since the mid-level will queue more commands and must have the lock
-     * (it's all happening inside timer interrupt handler!!).
-     * Even worse, abort will return NOT_RUNNING for all those commands not
-     * on any queue, so they won't be retried ...
-     *
-     * Conclusion: either scsi.c disables timeout for all resetted commands
-     * immediately, or we lose!  As of linux-2.0.20 it doesn't.
-     */
-
-    /* After the reset, there are no more connected or disconnected commands
-     * and no busy units; so clear the low-level status here to avoid 
-     * conflicts when the mid-level code tries to wake up the affected 
-     * commands!
-     */
-
-    if (hostdata->issue_queue)
-       ABRT_PRINTK("scsi%d: reset aborted issued command(s)\n", H_NO(cmd));
-    if (hostdata->connected) 
-       ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd));
-    if (hostdata->disconnected_queue)
-       ABRT_PRINTK("scsi%d: reset aborted disconnected command(s)\n", H_NO(cmd));
-
-    local_irq_save(flags);
-    hostdata->issue_queue = NULL;
-    hostdata->connected = NULL;
-    hostdata->disconnected_queue = NULL;
+       /* MSch: new-style reset handling: let the mid-level do what it can */
+
+       /* ++guenther: MID-LEVEL IS STILL BROKEN.
+        * Mid-level is supposed to requeue all commands that were active on the
+        * various low-level queues. In fact it does this, but that's not enough
+        * because all these commands are subject to timeout. And if a timeout
+        * happens for any removed command, *_abort() is called but all queues
+        * are now empty. Abort then gives up the falcon lock, which is fatal,
+        * since the mid-level will queue more commands and must have the lock
+        * (it's all happening inside timer interrupt handler!!).
+        * Even worse, abort will return NOT_RUNNING for all those commands not
+        * on any queue, so they won't be retried ...
+        *
+        * Conclusion: either scsi.c disables timeout for all resetted commands
+        * immediately, or we lose!  As of linux-2.0.20 it doesn't.
+        */
+
+       /* After the reset, there are no more connected or disconnected commands
+        * and no busy units; so clear the low-level status here to avoid
+        * conflicts when the mid-level code tries to wake up the affected
+        * commands!
+        */
+
+       if (hostdata->issue_queue)
+               ABRT_PRINTK("scsi%d: reset aborted issued command(s)\n", H_NO(cmd));
+       if (hostdata->connected)
+               ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd));
+       if (hostdata->disconnected_queue)
+               ABRT_PRINTK("scsi%d: reset aborted disconnected command(s)\n", H_NO(cmd));
+
+       local_irq_save(flags);
+       hostdata->issue_queue = NULL;
+       hostdata->connected = NULL;
+       hostdata->disconnected_queue = NULL;
 #ifdef SUPPORT_TAGS
-    free_all_tags();
+       free_all_tags();
 #endif
-    for( i = 0; i < 8; ++i )
-       hostdata->busy[i] = 0;
+       for (i = 0; i < 8; ++i)
+               hostdata->busy[i] = 0;
 #ifdef REAL_DMA
-    hostdata->dma_len = 0;
+       hostdata->dma_len = 0;
 #endif
-    local_irq_restore(flags);
+       local_irq_restore(flags);
 
-    /* we did no complete reset of all commands, so a wakeup is required */
-    return SCSI_RESET_WAKEUP | SCSI_RESET_BUS_RESET;
+       /* we did no complete reset of all commands, so a wakeup is required */
+       return SCSI_RESET_WAKEUP | SCSI_RESET_BUS_RESET;
 #endif /* 1 */
 }
-
-/* Local Variables: */
-/* tab-width: 8     */
-/* End:             */
index 642de7b..6f8403b 100644 (file)
@@ -69,9 +69,9 @@
 
 #define NDEBUG (0)
 
-#define NDEBUG_ABORT   0x800000
-#define NDEBUG_TAGS    0x1000000
-#define NDEBUG_MERGING 0x2000000
+#define NDEBUG_ABORT           0x00100000
+#define NDEBUG_TAGS            0x00200000
+#define NDEBUG_MERGING         0x00400000
 
 #define AUTOSENSE
 /* For the Atari version, use only polled IO or REAL_DMA */
@@ -186,38 +186,37 @@ static inline void DISABLE_IRQ(void)
 /***************************** Prototypes *****************************/
 
 #ifdef REAL_DMA
-static int scsi_dma_is_ignored_buserr( unsigned char dma_stat );
-static void atari_scsi_fetch_restbytes( void );
-static long atari_scsi_dma_residual( struct Scsi_Host *instance );
-static int falcon_classify_cmd( Scsi_Cmnd *cmd );
-static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
-                                         Scsi_Cmnd *cmd, int write_flag );
+static int scsi_dma_is_ignored_buserr(unsigned char dma_stat);
+static void atari_scsi_fetch_restbytes(void);
+static long atari_scsi_dma_residual(struct Scsi_Host *instance);
+static int falcon_classify_cmd(Scsi_Cmnd *cmd);
+static unsigned long atari_dma_xfer_len(unsigned long wanted_len,
+                                       Scsi_Cmnd *cmd, int write_flag);
 #endif
-static irqreturn_t scsi_tt_intr( int irq, void *dummy);
-static irqreturn_t scsi_falcon_intr( int irq, void *dummy);
-static void falcon_release_lock_if_possible( struct NCR5380_hostdata *
-                                             hostdata );
-static void falcon_get_lock( void );
+static irqreturn_t scsi_tt_intr(int irq, void *dummy);
+static irqreturn_t scsi_falcon_intr(int irq, void *dummy);
+static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata);
+static void falcon_get_lock(void);
 #ifdef CONFIG_ATARI_SCSI_RESET_BOOT
-static void atari_scsi_reset_boot( void );
+static void atari_scsi_reset_boot(void);
 #endif
-static unsigned char atari_scsi_tt_reg_read( unsigned char reg );
-static void atari_scsi_tt_reg_write( unsigned char reg, unsigned char value);
-static unsigned char atari_scsi_falcon_reg_read( unsigned char reg );
-static void atari_scsi_falcon_reg_write( unsigned char reg, unsigned char value );
+static unsigned char atari_scsi_tt_reg_read(unsigned char reg);
+static void atari_scsi_tt_reg_write(unsigned char reg, unsigned char value);
+static unsigned char atari_scsi_falcon_reg_read(unsigned char reg);
+static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value);
 
 /************************* End of Prototypes **************************/
 
 
-static struct Scsi_Host *atari_scsi_host = NULL;
-static unsigned char (*atari_scsi_reg_read)( unsigned char reg );
-static void (*atari_scsi_reg_write)( unsigned char reg, unsigned char value );
+static struct Scsi_Host *atari_scsi_host;
+static unsigned char (*atari_scsi_reg_read)(unsigned char reg);
+static void (*atari_scsi_reg_write)(unsigned char reg, unsigned char value);
 
 #ifdef REAL_DMA
 static unsigned long   atari_dma_residual, atari_dma_startaddr;
 static short           atari_dma_active;
 /* pointer to the dribble buffer */
-static char            *atari_dma_buffer = NULL;
+static char            *atari_dma_buffer;
 /* precalculated physical address of the dribble buffer */
 static unsigned long   atari_dma_phys_buffer;
 /* != 0 tells the Falcon int handler to copy data from the dribble buffer */
@@ -233,7 +232,7 @@ static char         *atari_dma_orig_addr;
 static unsigned long   atari_dma_stram_mask;
 #define STRAM_ADDR(a)  (((a) & atari_dma_stram_mask) == 0)
 /* number of bytes to cut from a transfer to handle NCR overruns */
-static int atari_read_overruns = 0;
+static int atari_read_overruns;
 #endif
 
 static int setup_can_queue = -1;
@@ -256,10 +255,10 @@ module_param(setup_hostid, int, 0);
 
 #if defined(REAL_DMA)
 
-static int scsi_dma_is_ignored_buserr( unsigned char dma_stat )
+static int scsi_dma_is_ignored_buserr(unsigned char dma_stat)
 {
        int i;
-       unsigned long   addr = SCSI_DMA_READ_P( dma_addr ), end_addr;
+       unsigned long addr = SCSI_DMA_READ_P(dma_addr), end_addr;
 
        if (dma_stat & 0x01) {
 
@@ -267,15 +266,14 @@ static int scsi_dma_is_ignored_buserr( unsigned char dma_stat )
                 * physical memory chunk (DMA prefetch!), but that doesn't hurt.
                 * Check for this case:
                 */
-               
-               for( i = 0; i < m68k_num_memory; ++i ) {
-                       end_addr = m68k_memory[i].addr +
-                               m68k_memory[i].size;
+
+               for (i = 0; i < m68k_num_memory; ++i) {
+                       end_addr = m68k_memory[i].addr + m68k_memory[i].size;
                        if (end_addr <= addr && addr <= end_addr + 4)
-                               return( 1 );
+                               return 1;
                }
        }
-       return( 0 );
+       return 0;
 }
 
 
@@ -284,28 +282,27 @@ static int scsi_dma_is_ignored_buserr( unsigned char dma_stat )
  * end-of-DMA, both SCSI ints are triggered simultaneously, so the NCR int has
  * to clear the DMA int pending bit before it allows other level 6 interrupts.
  */
-static void scsi_dma_buserr (int irq, void *dummy)
+static void scsi_dma_buserr(int irq, void *dummy)
 {
-       unsigned char   dma_stat = tt_scsi_dma.dma_ctrl;
+       unsigned char dma_stat = tt_scsi_dma.dma_ctrl;
 
        /* Don't do anything if a NCR interrupt is pending. Probably it's just
         * masked... */
-       if (atari_irq_pending( IRQ_TT_MFP_SCSI ))
+       if (atari_irq_pending(IRQ_TT_MFP_SCSI))
                return;
-       
+
        printk("Bad SCSI DMA interrupt! dma_addr=0x%08lx dma_stat=%02x dma_cnt=%08lx\n",
               SCSI_DMA_READ_P(dma_addr), dma_stat, SCSI_DMA_READ_P(dma_cnt));
        if (dma_stat & 0x80) {
-               if (!scsi_dma_is_ignored_buserr( dma_stat ))
-                       printk( "SCSI DMA bus error -- bad DMA programming!\n" );
-       }
-       else {
+               if (!scsi_dma_is_ignored_buserr(dma_stat))
+                       printk("SCSI DMA bus error -- bad DMA programming!\n");
+       } else {
                /* Under normal circumstances we never should get to this point,
                 * since both interrupts are triggered simultaneously and the 5380
                 * int has higher priority. When this irq is handled, that DMA
                 * interrupt is cleared. So a warning message is printed here.
                 */
-               printk( "SCSI DMA intr ?? -- this shouldn't happen!\n" );
+               printk("SCSI DMA intr ?? -- this shouldn't happen!\n");
        }
 }
 #endif
@@ -313,7 +310,7 @@ static void scsi_dma_buserr (int irq, void *dummy)
 #endif
 
 
-static irqreturn_t scsi_tt_intr (int irq, void *dummy)
+static irqreturn_t scsi_tt_intr(int irq, void *dummy)
 {
 #ifdef REAL_DMA
        int dma_stat;
@@ -327,7 +324,7 @@ static irqreturn_t scsi_tt_intr (int irq, void *dummy)
         * is that a bus error occurred...
         */
        if (dma_stat & 0x80) {
-               if (!scsi_dma_is_ignored_buserr( dma_stat )) {
+               if (!scsi_dma_is_ignored_buserr(dma_stat)) {
                        printk(KERN_ERR "SCSI DMA caused bus error near 0x%08lx\n",
                               SCSI_DMA_READ_P(dma_addr));
                        printk(KERN_CRIT "SCSI DMA bus error -- bad DMA programming!");
@@ -344,8 +341,7 @@ static irqreturn_t scsi_tt_intr (int irq, void *dummy)
         * data reg!
         */
        if ((dma_stat & 0x02) && !(dma_stat & 0x40)) {
-               atari_dma_residual = HOSTDATA_DMALEN - (SCSI_DMA_READ_P( dma_addr ) -
-                                                                                               atari_dma_startaddr);
+               atari_dma_residual = HOSTDATA_DMALEN - (SCSI_DMA_READ_P(dma_addr) - atari_dma_startaddr);
 
                DMA_PRINTK("SCSI DMA: There are %ld residual bytes.\n",
                           atari_dma_residual);
@@ -353,28 +349,30 @@ static irqreturn_t scsi_tt_intr (int irq, void *dummy)
                if ((signed int)atari_dma_residual < 0)
                        atari_dma_residual = 0;
                if ((dma_stat & 1) == 0) {
-                       /* After read operations, we maybe have to
-                          transport some rest bytes */
+                       /*
+                        * After read operations, we maybe have to
+                        * transport some rest bytes
+                        */
                        atari_scsi_fetch_restbytes();
-               }
-               else {
-                       /* There seems to be a nasty bug in some SCSI-DMA/NCR
-                          combinations: If a target disconnects while a write
-                          operation is going on, the address register of the
-                          DMA may be a few bytes farer than it actually read.
-                          This is probably due to DMA prefetching and a delay
-                          between DMA and NCR.  Experiments showed that the
-                          dma_addr is 9 bytes to high, but this could vary.
-                          The problem is, that the residual is thus calculated
-                          wrong and the next transfer will start behind where
-                          it should.  So we round up the residual to the next
-                          multiple of a sector size, if it isn't already a
-                          multiple and the originally expected transfer size
-                          was.  The latter condition is there to ensure that
-                          the correction is taken only for "real" data
-                          transfers and not for, e.g., the parameters of some
-                          other command.  These shouldn't disconnect anyway.
-                          */
+               } else {
+                       /*
+                        * There seems to be a nasty bug in some SCSI-DMA/NCR
+                        * combinations: If a target disconnects while a write
+                        * operation is going on, the address register of the
+                        * DMA may be a few bytes farer than it actually read.
+                        * This is probably due to DMA prefetching and a delay
+                        * between DMA and NCR.  Experiments showed that the
+                        * dma_addr is 9 bytes to high, but this could vary.
+                        * The problem is, that the residual is thus calculated
+                        * wrong and the next transfer will start behind where
+                        * it should.  So we round up the residual to the next
+                        * multiple of a sector size, if it isn't already a
+                        * multiple and the originally expected transfer size
+                        * was.  The latter condition is there to ensure that
+                        * the correction is taken only for "real" data
+                        * transfers and not for, e.g., the parameters of some
+                        * other command.  These shouldn't disconnect anyway.
+                        */
                        if (atari_dma_residual & 0x1ff) {
                                DMA_PRINTK("SCSI DMA: DMA bug corrected, "
                                           "difference %ld bytes\n",
@@ -394,18 +392,18 @@ static irqreturn_t scsi_tt_intr (int irq, void *dummy)
        }
 
 #endif /* REAL_DMA */
-       
-       NCR5380_intr (0, 0, 0);
+
+       NCR5380_intr(0, 0);
 
 #if 0
        /* To be sure the int is not masked */
-       atari_enable_irq( IRQ_TT_MFP_SCSI );
+       atari_enable_irq(IRQ_TT_MFP_SCSI);
 #endif
        return IRQ_HANDLED;
 }
 
 
-static irqreturn_t scsi_falcon_intr (int irq, void *dummy)
+static irqreturn_t scsi_falcon_intr(int irq, void *dummy)
 {
 #ifdef REAL_DMA
        int dma_stat;
@@ -430,7 +428,7 @@ static irqreturn_t scsi_falcon_intr (int irq, void *dummy)
         * bytes are stuck in the ST-DMA fifo (there's no way to reach them!)
         */
        if (atari_dma_active && (dma_stat & 0x02)) {
-               unsigned long   transferred;
+               unsigned long transferred;
 
                transferred = SCSI_DMA_GETADR() - atari_dma_startaddr;
                /* The ST-DMA address is incremented in 2-byte steps, but the
@@ -445,8 +443,7 @@ static irqreturn_t scsi_falcon_intr (int irq, void *dummy)
                atari_dma_residual = HOSTDATA_DMALEN - transferred;
                DMA_PRINTK("SCSI DMA: There are %ld residual bytes.\n",
                           atari_dma_residual);
-       }
-       else
+       } else
                atari_dma_residual = 0;
        atari_dma_active = 0;
 
@@ -461,13 +458,13 @@ static irqreturn_t scsi_falcon_intr (int irq, void *dummy)
 
 #endif /* REAL_DMA */
 
-       NCR5380_intr (0, 0, 0);
+       NCR5380_intr(0, 0);
        return IRQ_HANDLED;
 }
 
 
 #ifdef REAL_DMA
-static void atari_scsi_fetch_restbytes( void )
+static void atari_scsi_fetch_restbytes(void)
 {
        int nr;
        char *src, *dst;
@@ -505,19 +502,17 @@ static int falcon_dont_release = 0;
  * again (but others waiting longer more probably will win).
  */
 
-static void
-falcon_release_lock_if_possible( struct NCR5380_hostdata * hostdata )
+static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata)
 {
        unsigned long flags;
-               
-       if (IS_A_TT()) return;
-       
+
+       if (IS_A_TT())
+               return;
+
        local_irq_save(flags);
 
-       if (falcon_got_lock &&
-               !hostdata->disconnected_queue &&
-               !hostdata->issue_queue &&
-               !hostdata->connected) {
+       if (falcon_got_lock && !hostdata->disconnected_queue &&
+           !hostdata->issue_queue && !hostdata->connected) {
 
                if (falcon_dont_release) {
 #if 0
@@ -528,7 +523,7 @@ falcon_release_lock_if_possible( struct NCR5380_hostdata * hostdata )
                }
                falcon_got_lock = 0;
                stdma_release();
-               wake_up( &falcon_fairness_wait );
+               wake_up(&falcon_fairness_wait);
        }
 
        local_irq_restore(flags);
@@ -549,31 +544,31 @@ falcon_release_lock_if_possible( struct NCR5380_hostdata * hostdata )
  * Complicated, complicated.... Sigh...
  */
 
-static void falcon_get_lock( void )
+static void falcon_get_lock(void)
 {
        unsigned long flags;
 
-       if (IS_A_TT()) return;
+       if (IS_A_TT())
+               return;
 
        local_irq_save(flags);
 
-       while( !in_interrupt() && falcon_got_lock && stdma_others_waiting() )
-               sleep_on( &falcon_fairness_wait );
+       while (!in_irq() && falcon_got_lock && stdma_others_waiting())
+               sleep_on(&falcon_fairness_wait);
 
        while (!falcon_got_lock) {
-               if (in_interrupt())
-                       panic( "Falcon SCSI hasn't ST-DMA lock in interrupt" );
+               if (in_irq())
+                       panic("Falcon SCSI hasn't ST-DMA lock in interrupt");
                if (!falcon_trying_lock) {
                        falcon_trying_lock = 1;
                        stdma_lock(scsi_falcon_intr, NULL);
                        falcon_got_lock = 1;
                        falcon_trying_lock = 0;
-                       wake_up( &falcon_try_wait );
-               }
-               else {
-                       sleep_on( &falcon_try_wait );
+                       wake_up(&falcon_try_wait);
+               } else {
+                       sleep_on(&falcon_try_wait);
                }
-       }       
+       }
 
        local_irq_restore(flags);
        if (!falcon_got_lock)
@@ -587,18 +582,18 @@ static void falcon_get_lock( void )
  */
 
 #if 0
-int atari_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
+int atari_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
 {
        /* falcon_get_lock();
         * ++guenther: moved to NCR5380_queue_command() to prevent
         * race condition, see there for an explanation.
         */
-       return( NCR5380_queue_command( cmd, done ) );
+       return NCR5380_queue_command(cmd, done);
 }
 #endif
 
 
-int atari_scsi_detect (struct scsi_host_template *host)
+int atari_scsi_detect(struct scsi_host_template *host)
 {
        static int called = 0;
        struct Scsi_Host *instance;
@@ -606,7 +601,7 @@ int atari_scsi_detect (struct scsi_host_template *host)
        if (!MACH_IS_ATARI ||
            (!ATARIHW_PRESENT(ST_SCSI) && !ATARIHW_PRESENT(TT_SCSI)) ||
            called)
-               return( 0 );
+               return 0;
 
        host->proc_name = "Atari";
 
@@ -655,32 +650,33 @@ int atari_scsi_detect (struct scsi_host_template *host)
            !ATARIHW_PRESENT(EXTD_DMA) && m68k_num_memory > 1) {
                atari_dma_buffer = atari_stram_alloc(STRAM_BUFFER_SIZE, "SCSI");
                if (!atari_dma_buffer) {
-                       printk( KERN_ERR "atari_scsi_detect: can't allocate ST-RAM "
-                                       "double buffer\n" );
-                       return( 0 );
+                       printk(KERN_ERR "atari_scsi_detect: can't allocate ST-RAM "
+                                       "double buffer\n");
+                       return 0;
                }
-               atari_dma_phys_buffer = virt_to_phys( atari_dma_buffer );
+               atari_dma_phys_buffer = virt_to_phys(atari_dma_buffer);
                atari_dma_orig_addr = 0;
        }
 #endif
-       instance = scsi_register (host, sizeof (struct NCR5380_hostdata));
-       if(instance == NULL)
-       {
+       instance = scsi_register(host, sizeof(struct NCR5380_hostdata));
+       if (instance == NULL) {
                atari_stram_free(atari_dma_buffer);
                atari_dma_buffer = 0;
                return 0;
        }
        atari_scsi_host = instance;
-       /* Set irq to 0, to avoid that the mid-level code disables our interrupt
-        * during queue_command calls. This is completely unnecessary, and even
-        * worse causes bad problems on the Falcon, where the int is shared with
-        * IDE and floppy! */
+       /*
+        * Set irq to 0, to avoid that the mid-level code disables our interrupt
+        * during queue_command calls. This is completely unnecessary, and even
+        * worse causes bad problems on the Falcon, where the int is shared with
+        * IDE and floppy!
+        */
        instance->irq = 0;
 
 #ifdef CONFIG_ATARI_SCSI_RESET_BOOT
        atari_scsi_reset_boot();
 #endif
-       NCR5380_init (instance, 0);
+       NCR5380_init(instance, 0);
 
        if (IS_A_TT()) {
 
@@ -727,11 +723,10 @@ int atari_scsi_detect (struct scsi_host_template *host)
                         * the rest data bug is fixed, this can be lowered to 1.
                         */
                        atari_read_overruns = 4;
-               }               
+               }
 #endif /*REAL_DMA*/
-       }
-       else { /* ! IS_A_TT */
-               
+       } else { /* ! IS_A_TT */
+
                /* Nothing to do for the interrupt: the ST-DMA is initialized
                 * already by atari_init_INTS()
                 */
@@ -756,23 +751,21 @@ int atari_scsi_detect (struct scsi_host_template *host)
                        setup_use_tagged_queuing ? "yes" : "no",
 #endif
                        instance->hostt->this_id );
-       NCR5380_print_options (instance);
-       printk ("\n");
+       NCR5380_print_options(instance);
+       printk("\n");
 
        called = 1;
-       return( 1 );
+       return 1;
 }
 
-#ifdef MODULE
-int atari_scsi_release (struct Scsi_Host *sh)
+int atari_scsi_release(struct Scsi_Host *sh)
 {
        if (IS_A_TT())
                free_irq(IRQ_TT_MFP_SCSI, scsi_tt_intr);
        if (atari_dma_buffer)
-               atari_stram_free (atari_dma_buffer);
+               atari_stram_free(atari_dma_buffer);
        return 1;
 }
-#endif
 
 void __init atari_scsi_setup(char *str, int *ints)
 {
@@ -781,9 +774,9 @@ void __init atari_scsi_setup(char *str, int *ints)
         * Defaults depend on TT or Falcon, hostid determined at run time.
         * Negative values mean don't change.
         */
-       
+
        if (ints[0] < 1) {
-               printk( "atari_scsi_setup: no arguments!\n" );
+               printk("atari_scsi_setup: no arguments!\n");
                return;
        }
 
@@ -809,7 +802,7 @@ void __init atari_scsi_setup(char *str, int *ints)
                if (ints[4] >= 0 && ints[4] <= 7)
                        setup_hostid = ints[4];
                else if (ints[4] > 7)
-                       printk( "atari_scsi_setup: invalid host ID %d !\n", ints[4] );
+                       printk("atari_scsi_setup: invalid host ID %d !\n", ints[4]);
        }
 #ifdef SUPPORT_TAGS
        if (ints[0] >= 5) {
@@ -821,7 +814,7 @@ void __init atari_scsi_setup(char *str, int *ints)
 
 int atari_scsi_bus_reset(Scsi_Cmnd *cmd)
 {
-       int             rv;
+       int rv;
        struct NCR5380_hostdata *hostdata =
                (struct NCR5380_hostdata *)cmd->device->host->hostdata;
 
@@ -831,13 +824,12 @@ int atari_scsi_bus_reset(Scsi_Cmnd *cmd)
         */
        /* And abort a maybe active DMA transfer */
        if (IS_A_TT()) {
-               atari_turnoff_irq( IRQ_TT_MFP_SCSI );
+               atari_turnoff_irq(IRQ_TT_MFP_SCSI);
 #ifdef REAL_DMA
                tt_scsi_dma.dma_ctrl = 0;
 #endif /* REAL_DMA */
-       }
-       else {
-               atari_turnoff_irq( IRQ_MFP_FSCSI );
+       } else {
+               atari_turnoff_irq(IRQ_MFP_FSCSI);
 #ifdef REAL_DMA
                st_dma.dma_mode_status = 0x90;
                atari_dma_active = 0;
@@ -849,52 +841,51 @@ int atari_scsi_bus_reset(Scsi_Cmnd *cmd)
 
        /* Re-enable ints */
        if (IS_A_TT()) {
-               atari_turnon_irq( IRQ_TT_MFP_SCSI );
-       }
-       else {
-               atari_turnon_irq( IRQ_MFP_FSCSI );
+               atari_turnon_irq(IRQ_TT_MFP_SCSI);
+       } else {
+               atari_turnon_irq(IRQ_MFP_FSCSI);
        }
        if ((rv & SCSI_RESET_ACTION) == SCSI_RESET_SUCCESS)
                falcon_release_lock_if_possible(hostdata);
 
-       return( rv );
+       return rv;
 }
 
-       
+
 #ifdef CONFIG_ATARI_SCSI_RESET_BOOT
 static void __init atari_scsi_reset_boot(void)
 {
        unsigned long end;
-       
+
        /*
         * Do a SCSI reset to clean up the bus during initialization. No messing
         * with the queues, interrupts, or locks necessary here.
         */
 
-       printk( "Atari SCSI: resetting the SCSI bus..." );
+       printk("Atari SCSI: resetting the SCSI bus...");
 
        /* get in phase */
-       NCR5380_write( TARGET_COMMAND_REG,
-                     PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
+       NCR5380_write(TARGET_COMMAND_REG,
+                     PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG)));
 
        /* assert RST */
-       NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );
+       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
        /* The min. reset hold time is 25us, so 40us should be enough */
-       udelay( 50 );
+       udelay(50);
        /* reset RST and interrupt */
-       NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
-       NCR5380_read( RESET_PARITY_INTERRUPT_REG );
+       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+       NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 
        end = jiffies + AFTER_RESET_DELAY;
        while (time_before(jiffies, end))
                barrier();
 
-       printk( " done\n" );
+       printk(" done\n");
 }
 #endif
 
 
-const char * atari_scsi_info (struct Scsi_Host *host)
+const char *atari_scsi_info(struct Scsi_Host *host)
 {
        /* atari_scsi_detect() is verbose enough... */
        static const char string[] = "Atari native SCSI";
@@ -904,10 +895,10 @@ const char * atari_scsi_info (struct Scsi_Host *host)
 
 #if defined(REAL_DMA)
 
-unsigned long atari_scsi_dma_setup( struct Scsi_Host *instance, void *data,
-                                  unsigned long count, int dir )
+unsigned long atari_scsi_dma_setup(struct Scsi_Host *instance, void *data,
+                                  unsigned long count, int dir)
 {
-       unsigned long addr = virt_to_phys( data );
+       unsigned long addr = virt_to_phys(data);
 
        DMA_PRINTK("scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, "
                   "dir = %d\n", instance->host_no, data, addr, count, dir);
@@ -919,38 +910,37 @@ unsigned long atari_scsi_dma_setup( struct Scsi_Host *instance, void *data,
                 * wanted address.
                 */
                if (dir)
-                       memcpy( atari_dma_buffer, data, count );
+                       memcpy(atari_dma_buffer, data, count);
                else
                        atari_dma_orig_addr = data;
                addr = atari_dma_phys_buffer;
        }
-       
+
        atari_dma_startaddr = addr;     /* Needed for calculating residual later. */
-  
+
        /* Cache cleanup stuff: On writes, push any dirty cache out before sending
         * it to the peripheral. (Must be done before DMA setup, since at least
         * the ST-DMA begins to fill internal buffers right after setup. For
         * reads, invalidate any cache, may be altered after DMA without CPU
         * knowledge.
-        * 
+        *
         * ++roman: For the Medusa, there's no need at all for that cache stuff,
         * because the hardware does bus snooping (fine!).
         */
-       dma_cache_maintenance( addr, count, dir );
+       dma_cache_maintenance(addr, count, dir);
 
        if (count == 0)
                printk(KERN_NOTICE "SCSI warning: DMA programmed for 0 bytes !\n");
 
        if (IS_A_TT()) {
                tt_scsi_dma.dma_ctrl = dir;
-               SCSI_DMA_WRITE_P( dma_addr, addr );
-               SCSI_DMA_WRITE_P( dma_cnt, count );
+               SCSI_DMA_WRITE_P(dma_addr, addr);
+               SCSI_DMA_WRITE_P(dma_cnt, count);
                tt_scsi_dma.dma_ctrl = dir | 2;
-       }
-       else { /* ! IS_A_TT */
-  
+       } else { /* ! IS_A_TT */
+
                /* set address */
-               SCSI_DMA_SETADR( addr );
+               SCSI_DMA_SETADR(addr);
 
                /* toggle direction bit to clear FIFO and set DMA direction */
                dir <<= 8;
@@ -968,13 +958,13 @@ unsigned long atari_scsi_dma_setup( struct Scsi_Host *instance, void *data,
                atari_dma_active = 1;
        }
 
-       return( count );
+       return count;
 }
 
 
-static long atari_scsi_dma_residual( struct Scsi_Host *instance )
+static long atari_scsi_dma_residual(struct Scsi_Host *instance)
 {
-       return( atari_dma_residual );
+       return atari_dma_residual;
 }
 
 
@@ -982,13 +972,13 @@ static long atari_scsi_dma_residual( struct Scsi_Host *instance )
 #define        CMD_SURELY_BYTE_MODE    1
 #define        CMD_MODE_UNKNOWN                2
 
-static int falcon_classify_cmd( Scsi_Cmnd *cmd )
+static int falcon_classify_cmd(Scsi_Cmnd *cmd)
 {
        unsigned char opcode = cmd->cmnd[0];
-       
+
        if (opcode == READ_DEFECT_DATA || opcode == READ_LONG ||
-               opcode == READ_BUFFER)
-               return( CMD_SURELY_BYTE_MODE );
+           opcode == READ_BUFFER)
+               return CMD_SURELY_BYTE_MODE;
        else if (opcode == READ_6 || opcode == READ_10 ||
                 opcode == 0xa8 /* READ_12 */ || opcode == READ_REVERSE ||
                 opcode == RECOVER_BUFFERED_DATA) {
@@ -996,12 +986,11 @@ static int falcon_classify_cmd( Scsi_Cmnd *cmd )
                 * needed here: The transfer is block-mode only if the 'fixed' bit is
                 * set! */
                if (cmd->device->type == TYPE_TAPE && !(cmd->cmnd[1] & 1))
-                       return( CMD_SURELY_BYTE_MODE );
+                       return CMD_SURELY_BYTE_MODE;
                else
-                       return( CMD_SURELY_BLOCK_MODE );
-       }
-       else
-               return( CMD_MODE_UNKNOWN );
+                       return CMD_SURELY_BLOCK_MODE;
+       } else
+               return CMD_MODE_UNKNOWN;
 }
 
 
@@ -1014,19 +1003,18 @@ static int falcon_classify_cmd( Scsi_Cmnd *cmd )
  * the overrun problem, so this question is academic :-)
  */
 
-static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
-                                       Scsi_Cmnd *cmd,
-                                       int write_flag )
+static unsigned long atari_dma_xfer_len(unsigned long wanted_len,
+                                       Scsi_Cmnd *cmd, int write_flag)
 {
        unsigned long   possible_len, limit;
 #ifndef CONFIG_TT_DMA_EMUL
        if (MACH_IS_HADES)
                /* Hades has no SCSI DMA at all :-( Always force use of PIO */
-               return( 0 );
-#endif 
+               return 0;
+#endif
        if (IS_A_TT())
                /* TT SCSI DMA can transfer arbitrary #bytes */
-               return( wanted_len );
+               return wanted_len;
 
        /* ST DMA chip is stupid -- only multiples of 512 bytes! (and max.
         * 255*512 bytes, but this should be enough)
@@ -1062,8 +1050,7 @@ static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
                 * this).
                 */
                possible_len = wanted_len;
-       }
-       else {
+       } else {
                /* Read operations: if the wanted transfer length is not a multiple of
                 * 512, we cannot use DMA, since the ST-DMA cannot split transfers
                 * (no interrupt on DMA finished!)
@@ -1073,15 +1060,15 @@ static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
                else {
                        /* Now classify the command (see above) and decide whether it is
                         * allowed to do DMA at all */
-                       switch( falcon_classify_cmd( cmd )) {
-                         case CMD_SURELY_BLOCK_MODE:
+                       switch (falcon_classify_cmd(cmd)) {
+                       case CMD_SURELY_BLOCK_MODE:
                                possible_len = wanted_len;
                                break;
-                         case CMD_SURELY_BYTE_MODE:
+                       case CMD_SURELY_BYTE_MODE:
                                possible_len = 0; /* DMA prohibited */
                                break;
-                         case CMD_MODE_UNKNOWN:
-                         default:
+                       case CMD_MODE_UNKNOWN:
+                       default:
                                /* For unknown commands assume block transfers if the transfer
                                 * size/allocation length is >= 1024 */
                                possible_len = (wanted_len < 1024) ? 0 : wanted_len;
@@ -1089,9 +1076,9 @@ static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
                        }
                }
        }
-       
+
        /* Last step: apply the hard limit on DMA transfers */
-       limit = (atari_dma_buffer && !STRAM_ADDR( virt_to_phys(cmd->SCp.ptr) )) ?
+       limit = (atari_dma_buffer && !STRAM_ADDR(virt_to_phys(cmd->SCp.ptr))) ?
                    STRAM_BUFFER_SIZE : 255*512;
        if (possible_len > limit)
                possible_len = limit;
@@ -1100,7 +1087,7 @@ static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
                DMA_PRINTK("Sorry, must cut DMA transfer size to %ld bytes "
                           "instead of %ld\n", possible_len, wanted_len);
 
-       return( possible_len );
+       return possible_len;
 }
 
 
@@ -1114,23 +1101,23 @@ static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
  * NCR5380_write call these functions via function pointers.
  */
 
-static unsigned char atari_scsi_tt_reg_read( unsigned char reg )
+static unsigned char atari_scsi_tt_reg_read(unsigned char reg)
 {
-       return( tt_scsi_regp[reg * 2] );
+       return tt_scsi_regp[reg * 2];
 }
 
-static void atari_scsi_tt_reg_write( unsigned char reg, unsigned char value )
+static void atari_scsi_tt_reg_write(unsigned char reg, unsigned char value)
 {
        tt_scsi_regp[reg * 2] = value;
 }
 
-static unsigned char atari_scsi_falcon_reg_read( unsigned char reg )
+static unsigned char atari_scsi_falcon_reg_read(unsigned char reg)
 {
        dma_wd.dma_mode_status= (u_short)(0x88 + reg);
-       return( (u_char)dma_wd.fdc_acces_seccount );
+       return (u_char)dma_wd.fdc_acces_seccount;
 }
 
-static void atari_scsi_falcon_reg_write( unsigned char reg, unsigned char value )
+static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value)
 {
        dma_wd.dma_mode_status = (u_short)(0x88 + reg);
        dma_wd.fdc_acces_seccount = (u_short)value;
index f917bdd..efadb8d 100644 (file)
 int atari_scsi_detect (struct scsi_host_template *);
 const char *atari_scsi_info (struct Scsi_Host *);
 int atari_scsi_reset (Scsi_Cmnd *, unsigned int);
-#ifdef MODULE
 int atari_scsi_release (struct Scsi_Host *);
-#else
-#define atari_scsi_release NULL
-#endif
 
 /* The values for CMD_PER_LUN and CAN_QUEUE are somehow arbitrary. Higher
  * values should work, too; try it! (but cmd_per_lun costs memory!) */
@@ -63,6 +59,32 @@ int atari_scsi_release (struct Scsi_Host *);
 #define        NCR5380_dma_xfer_len(i,cmd,phase) \
        atari_dma_xfer_len(cmd->SCp.this_residual,cmd,((phase) & SR_IO) ? 0 : 1)
 
+/* former generic SCSI error handling stuff */
+
+#define SCSI_ABORT_SNOOZE 0
+#define SCSI_ABORT_SUCCESS 1
+#define SCSI_ABORT_PENDING 2
+#define SCSI_ABORT_BUSY 3
+#define SCSI_ABORT_NOT_RUNNING 4
+#define SCSI_ABORT_ERROR 5
+
+#define SCSI_RESET_SNOOZE 0
+#define SCSI_RESET_PUNT 1
+#define SCSI_RESET_SUCCESS 2
+#define SCSI_RESET_PENDING 3
+#define SCSI_RESET_WAKEUP 4
+#define SCSI_RESET_NOT_RUNNING 5
+#define SCSI_RESET_ERROR 6
+
+#define SCSI_RESET_SYNCHRONOUS         0x01
+#define SCSI_RESET_ASYNCHRONOUS                0x02
+#define SCSI_RESET_SUGGEST_BUS_RESET   0x04
+#define SCSI_RESET_SUGGEST_HOST_RESET  0x08
+
+#define SCSI_RESET_BUS_RESET 0x100
+#define SCSI_RESET_HOST_RESET 0x200
+#define SCSI_RESET_ACTION   0xff
+
 /* Debugging printk definitions:
  *
  *  ARB  -> arbitration
@@ -91,144 +113,58 @@ int atari_scsi_release (struct Scsi_Host *);
  *
  */
 
-#if NDEBUG & NDEBUG_ARBITRATION
+#define dprint(flg, format...)                 \
+({                                             \
+       if (NDEBUG & (flg))                     \
+               printk(KERN_DEBUG format);      \
+})
+
 #define ARB_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define ARB_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_AUTOSENSE
+       dprint(NDEBUG_ARBITRATION, format , ## args)
 #define ASEN_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define ASEN_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_DMA
+       dprint(NDEBUG_AUTOSENSE, format , ## args)
 #define DMA_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define DMA_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_HANDSHAKE
+       dprint(NDEBUG_DMA, format , ## args)
 #define HSH_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define HSH_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_INFORMATION
+       dprint(NDEBUG_HANDSHAKE, format , ## args)
 #define INF_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define INF_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_INIT
+       dprint(NDEBUG_INFORMATION, format , ## args)
 #define INI_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define INI_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_INTR
+       dprint(NDEBUG_INIT, format , ## args)
 #define INT_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define INT_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_LINKED
+       dprint(NDEBUG_INTR, format , ## args)
 #define LNK_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define LNK_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_MAIN
+       dprint(NDEBUG_LINKED, format , ## args)
 #define MAIN_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define MAIN_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_NO_DATAOUT
+       dprint(NDEBUG_MAIN, format , ## args)
 #define NDAT_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define NDAT_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_NO_WRITE
+       dprint(NDEBUG_NO_DATAOUT, format , ## args)
 #define NWR_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define NWR_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_PIO
+       dprint(NDEBUG_NO_WRITE, format , ## args)
 #define PIO_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define PIO_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_PSEUDO_DMA
+       dprint(NDEBUG_PIO, format , ## args)
 #define PDMA_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define PDMA_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_QUEUES
+       dprint(NDEBUG_PSEUDO_DMA, format , ## args)
 #define QU_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define QU_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_RESELECTION
+       dprint(NDEBUG_QUEUES, format , ## args)
 #define RSL_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define RSL_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_SELECTION
+       dprint(NDEBUG_RESELECTION, format , ## args)
 #define SEL_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define SEL_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_USLEEP
+       dprint(NDEBUG_SELECTION, format , ## args)
 #define USL_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define USL_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_LAST_BYTE_SENT
+       dprint(NDEBUG_USLEEP, format , ## args)
 #define LBS_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define LBS_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_RESTART_SELECT
+       dprint(NDEBUG_LAST_BYTE_SENT, format , ## args)
 #define RSS_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define RSS_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_EXTENDED
+       dprint(NDEBUG_RESTART_SELECT, format , ## args)
 #define EXT_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define EXT_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_ABORT
+       dprint(NDEBUG_EXTENDED, format , ## args)
 #define ABRT_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define ABRT_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_TAGS
+       dprint(NDEBUG_ABORT, format , ## args)
 #define TAG_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define TAG_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_MERGING
+       dprint(NDEBUG_TAGS, format , ## args)
 #define MER_PRINTK(format, args...) \
-       printk(KERN_DEBUG format , ## args)
-#else
-#define MER_PRINTK(format, args...)
-#endif
+       dprint(NDEBUG_MERGING, format , ## args)
 
 /* conditional macros for NCR5380_print_{,phase,status} */
 
index 61f6024..2a458d6 100644 (file)
@@ -202,31 +202,29 @@ static const char * get_sa_name(const struct value_name_pair * arr,
 }
 
 /* attempt to guess cdb length if cdb_len==0 . No trailing linefeed. */
-static void print_opcode_name(unsigned char * cdbp, int cdb_len,
-                             int start_of_line)
+static void print_opcode_name(unsigned char * cdbp, int cdb_len)
 {
        int sa, len, cdb0;
        const char * name;
-       const char * leadin = start_of_line ? KERN_INFO : "";
 
        cdb0 = cdbp[0];
        switch(cdb0) {
        case VARIABLE_LENGTH_CMD:
                len = cdbp[7] + 8;
                if (len < 10) {
-                       printk("%sshort variable length command, "
-                              "len=%d ext_len=%d", leadin, len, cdb_len);
+                       printk("short variable length command, "
+                              "len=%d ext_len=%d", len, cdb_len);
                        break;
                }
                sa = (cdbp[8] << 8) + cdbp[9];
                name = get_sa_name(maint_in_arr, MAINT_IN_SZ, sa);
                if (name) {
-                       printk("%s%s", leadin, name);
+                       printk("%s", name);
                        if ((cdb_len > 0) && (len != cdb_len))
                                printk(", in_cdb_len=%d, ext_len=%d",
                                       len, cdb_len);
                } else {
-                       printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+                       printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
                        if ((cdb_len > 0) && (len != cdb_len))
                                printk(", in_cdb_len=%d, ext_len=%d",
                                       len, cdb_len);
@@ -236,83 +234,80 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len,
                sa = cdbp[1] & 0x1f;
                name = get_sa_name(maint_in_arr, MAINT_IN_SZ, sa);
                if (name)
-                       printk("%s%s", leadin, name);
+                       printk("%s", name);
                else
-                       printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+                       printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
                break;
        case MAINTENANCE_OUT:
                sa = cdbp[1] & 0x1f;
                name = get_sa_name(maint_out_arr, MAINT_OUT_SZ, sa);
                if (name)
-                       printk("%s%s", leadin, name);
+                       printk("%s", name);
                else
-                       printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+                       printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
                break;
        case SERVICE_ACTION_IN_12:
                sa = cdbp[1] & 0x1f;
                name = get_sa_name(serv_in12_arr, SERV_IN12_SZ, sa);
                if (name)
-                       printk("%s%s", leadin, name);
+                       printk("%s", name);
                else
-                       printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+                       printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
                break;
        case SERVICE_ACTION_OUT_12:
                sa = cdbp[1] & 0x1f;
                name = get_sa_name(serv_out12_arr, SERV_OUT12_SZ, sa);
                if (name)
-                       printk("%s%s", leadin, name);
+                       printk("%s", name);
                else
-                       printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+                       printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
                break;
        case SERVICE_ACTION_IN_16:
                sa = cdbp[1] & 0x1f;
                name = get_sa_name(serv_in16_arr, SERV_IN16_SZ, sa);
                if (name)
-                       printk("%s%s", leadin, name);
+                       printk("%s", name);
                else
-                       printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+                       printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
                break;
        case SERVICE_ACTION_OUT_16:
                sa = cdbp[1] & 0x1f;
                name = get_sa_name(serv_out16_arr, SERV_OUT16_SZ, sa);
                if (name)
-                       printk("%s%s", leadin, name);
+                       printk("%s", name);
                else
-                       printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+                       printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
                break;
        default:
                if (cdb0 < 0xc0) {
                        name = cdb_byte0_names[cdb0];
                        if (name)
-                               printk("%s%s", leadin, name);
+                               printk("%s", name);
                        else
-                               printk("%scdb[0]=0x%x (reserved)",
-                                      leadin, cdb0);
+                               printk("cdb[0]=0x%x (reserved)", cdb0);
                } else
-                       printk("%scdb[0]=0x%x (vendor)", leadin, cdb0);
+                       printk("cdb[0]=0x%x (vendor)", cdb0);
                break;
        }
 }
 
 #else /* ifndef CONFIG_SCSI_CONSTANTS */
 
-static void print_opcode_name(unsigned char * cdbp, int cdb_len,
-                             int start_of_line)
+static void print_opcode_name(unsigned char * cdbp, int cdb_len)
 {
        int sa, len, cdb0;
-       const char * leadin = start_of_line ? KERN_INFO : "";
 
        cdb0 = cdbp[0];
        switch(cdb0) {
        case VARIABLE_LENGTH_CMD:
                len = cdbp[7] + 8;
                if (len < 10) {
-                       printk("%sshort opcode=0x%x command, len=%d "
-                              "ext_len=%d", leadin, cdb0, len, cdb_len);
+                       printk("short opcode=0x%x command, len=%d "
+                              "ext_len=%d", cdb0, len, cdb_len);
                        break;
                }
                sa = (cdbp[8] << 8) + cdbp[9];
-               printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+               printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
                if (len != cdb_len)
                        printk(", in_cdb_len=%d, ext_len=%d", len, cdb_len);
                break;
@@ -323,49 +318,48 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len,
        case SERVICE_ACTION_IN_16:
        case SERVICE_ACTION_OUT_16:
                sa = cdbp[1] & 0x1f;
-               printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+               printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
                break;
        default:
                if (cdb0 < 0xc0)
-                       printk("%scdb[0]=0x%x", leadin, cdb0);
+                       printk("cdb[0]=0x%x", cdb0);
                else
-                       printk("%scdb[0]=0x%x (vendor)", leadin, cdb0);
+                       printk("cdb[0]=0x%x (vendor)", cdb0);
                break;
        }
 }
 #endif  
 
-void __scsi_print_command(unsigned char *command)
+void __scsi_print_command(unsigned char *cdb)
 {
        int k, len;
 
-       print_opcode_name(command, 0, 1);
-       if (VARIABLE_LENGTH_CMD == command[0])
-               len = command[7] + 8;
+       print_opcode_name(cdb, 0);
+       if (VARIABLE_LENGTH_CMD == cdb[0])
+               len = cdb[7] + 8;
        else
-               len = COMMAND_SIZE(command[0]);
+               len = COMMAND_SIZE(cdb[0]);
        /* print out all bytes in cdb */
        for (k = 0; k < len; ++k) 
-               printk(" %02x", command[k]);
+               printk(" %02x", cdb[k]);
        printk("\n");
 }
 EXPORT_SYMBOL(__scsi_print_command);
 
-/* This function (perhaps with the addition of peripheral device type)
- * is more approriate than __scsi_print_command(). Perhaps that static
- * can be dropped later if it replaces the __scsi_print_command version.
- */
-static void scsi_print_cdb(unsigned char *cdb, int cdb_len, int start_of_line)
+void scsi_print_command(struct scsi_cmnd *cmd)
 {
        int k;
 
-       print_opcode_name(cdb, cdb_len, start_of_line);
+       scmd_printk(KERN_INFO, cmd, "CDB: ");
+       print_opcode_name(cmd->cmnd, cmd->cmd_len);
+
        /* print out all bytes in cdb */
        printk(":");
-       for (k = 0; k < cdb_len; ++k) 
-               printk(" %02x", cdb[k]);
+       for (k = 0; k < cmd->cmd_len; ++k)
+               printk(" %02x", cmd->cmnd[k]);
        printk("\n");
 }
+EXPORT_SYMBOL(scsi_print_command);
 
 /**
  *
@@ -410,7 +404,11 @@ struct error_info {
        const char * text;
 };
 
-static struct error_info additional[] =
+/*
+ * The canonical list of T10 Additional Sense Codes is available at:
+ * http://www.t10.org/lists/asc-num.txt
+ */
+static const struct error_info additional[] =
 {
        {0x0000, "No additional sense information"},
        {0x0001, "Filemark detected"},
@@ -714,6 +712,7 @@ static struct error_info additional[] =
 
        {0x2F00, "Commands cleared by another initiator"},
        {0x2F01, "Commands cleared by power loss notification"},
+       {0x2F02, "Commands cleared by device server"},
 
        {0x3000, "Incompatible medium installed"},
        {0x3001, "Cannot read medium - unknown format"},
@@ -1176,67 +1175,77 @@ scsi_extd_sense_format(unsigned char asc, unsigned char ascq) {
 }
 EXPORT_SYMBOL(scsi_extd_sense_format);
 
-/* Print extended sense information; no leadin, no linefeed */
-static void
+void
 scsi_show_extd_sense(unsigned char asc, unsigned char ascq)
 {
-       const char *extd_sense_fmt = scsi_extd_sense_format(asc, ascq);
+        const char *extd_sense_fmt = scsi_extd_sense_format(asc, ascq);
 
        if (extd_sense_fmt) {
                if (strstr(extd_sense_fmt, "%x")) {
-                       printk("Additional sense: ");
+                       printk("Add. Sense: ");
                        printk(extd_sense_fmt, ascq);
                } else
-                       printk("Additional sense: %s", extd_sense_fmt);
+                       printk("Add. Sense: %s", extd_sense_fmt);
        } else {
                if (asc >= 0x80)
-                       printk("<<vendor>> ASC=0x%x ASCQ=0x%x", asc, ascq);
+                       printk("<<vendor>> ASC=0x%x ASCQ=0x%x", asc,
+                              ascq);
                if (ascq >= 0x80)
-                       printk("ASC=0x%x <<vendor>> ASCQ=0x%x", asc, ascq);
+                       printk("ASC=0x%x <<vendor>> ASCQ=0x%x", asc,
+                              ascq);
                else
                        printk("ASC=0x%x ASCQ=0x%x", asc, ascq);
        }
+
+       printk("\n");
 }
+EXPORT_SYMBOL(scsi_show_extd_sense);
 
 void
-scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr)
+scsi_show_sense_hdr(struct scsi_sense_hdr *sshdr)
 {
        const char *sense_txt;
-       /* An example of deferred is when an earlier write to disk cache
-        * succeeded, but now the disk discovers that it cannot write the
-        * data to the magnetic media.
-        */
-       const char *error = scsi_sense_is_deferred(sshdr) ? 
-               "<<DEFERRED>>" : "Current";
-       printk(KERN_INFO "%s: %s", name, error);
-       if (sshdr->response_code >= 0x72)
-               printk(" [descriptor]");
 
        sense_txt = scsi_sense_key_string(sshdr->sense_key);
        if (sense_txt)
-               printk(": sense key: %s\n", sense_txt);
+               printk("Sense Key : %s ", sense_txt);
        else
-               printk(": sense key=0x%x\n", sshdr->sense_key);
-       printk(KERN_INFO "    ");
-       scsi_show_extd_sense(sshdr->asc, sshdr->ascq);
+               printk("Sense Key : 0x%x ", sshdr->sense_key);
+
+       printk("%s", scsi_sense_is_deferred(sshdr) ? "[deferred] " :
+              "[current] ");
+
+       if (sshdr->response_code >= 0x72)
+               printk("[descriptor]");
+
        printk("\n");
 }
+EXPORT_SYMBOL(scsi_show_sense_hdr);
+
+/*
+ * Print normalized SCSI sense header with a prefix.
+ */
+void
+scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr)
+{
+       printk(KERN_INFO "%s: ", name);
+       scsi_show_sense_hdr(sshdr);
+       printk(KERN_INFO "%s: ", name);
+       scsi_show_extd_sense(sshdr->asc, sshdr->ascq);
+}
 EXPORT_SYMBOL(scsi_print_sense_hdr);
 
-/* Print sense information */
 void
-__scsi_print_sense(const char *name, const unsigned char *sense_buffer,
-                  int sense_len)
+scsi_decode_sense_buffer(const unsigned char *sense_buffer, int sense_len,
+                      struct scsi_sense_hdr *sshdr)
 {
        int k, num, res;
-       unsigned int info;
-       struct scsi_sense_hdr ssh;
     
-       res = scsi_normalize_sense(sense_buffer, sense_len, &ssh);
+       res = scsi_normalize_sense(sense_buffer, sense_len, sshdr);
        if (0 == res) {
                /* this may be SCSI-1 sense data */
                num = (sense_len < 32) ? sense_len : 32;
-               printk(KERN_INFO "Unrecognized sense data (in hex):");
+               printk("Unrecognized sense data (in hex):");
                for (k = 0; k < num; ++k) {
                        if (0 == (k % 16)) {
                                printk("\n");
@@ -1247,11 +1256,20 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
                printk("\n");
                return;
        }
-       scsi_print_sense_hdr(name, &ssh);
-       if (ssh.response_code < 0x72) {
+}
+
+void
+scsi_decode_sense_extras(const unsigned char *sense_buffer, int sense_len,
+                        struct scsi_sense_hdr *sshdr)
+{
+       int k, num, res;
+
+       if (sshdr->response_code < 0x72)
+       {
                /* only decode extras for "fixed" format now */
                char buff[80];
                int blen, fixed_valid;
+               unsigned int info;
 
                fixed_valid = sense_buffer[0] & 0x80;
                info = ((sense_buffer[3] << 24) | (sense_buffer[4] << 16) |
@@ -1281,13 +1299,13 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
                        res += snprintf(buff + res, blen - res, "ILI");
                }
                if (res > 0)
-                       printk(KERN_INFO "%s\n", buff);
-       } else if (ssh.additional_length > 0) {
+                       printk("%s\n", buff);
+       } else if (sshdr->additional_length > 0) {
                /* descriptor format with sense descriptors */
-               num = 8 + ssh.additional_length;
+               num = 8 + sshdr->additional_length;
                num = (sense_len < num) ? sense_len : num;
-               printk(KERN_INFO "Descriptor sense data with sense "
-                      "descriptors (in hex):");
+               printk("Descriptor sense data with sense descriptors "
+                      "(in hex):");
                for (k = 0; k < num; ++k) {
                        if (0 == (k % 16)) {
                                printk("\n");
@@ -1295,29 +1313,42 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
                        }
                        printk("%02x ", sense_buffer[k]);
                }
+
                printk("\n");
        }
+
 }
-EXPORT_SYMBOL(__scsi_print_sense);
 
-void scsi_print_sense(const char *devclass, struct scsi_cmnd *cmd)
+/* Normalize and print sense buffer with name prefix */
+void __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
+                       int sense_len)
 {
-       const char *name = devclass;
-
-       if (cmd->request->rq_disk)
-               name = cmd->request->rq_disk->disk_name;
-       __scsi_print_sense(name, cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
+       struct scsi_sense_hdr sshdr;
+
+       printk(KERN_INFO "%s: ", name);
+       scsi_decode_sense_buffer(sense_buffer, sense_len, &sshdr);
+       scsi_show_sense_hdr(&sshdr);
+       scsi_decode_sense_extras(sense_buffer, sense_len, &sshdr);
+       printk(KERN_INFO "%s: ", name);
+       scsi_show_extd_sense(sshdr.asc, sshdr.ascq);
 }
-EXPORT_SYMBOL(scsi_print_sense);
+EXPORT_SYMBOL(__scsi_print_sense);
 
-void scsi_print_command(struct scsi_cmnd *cmd)
+/* Normalize and print sense buffer in SCSI command */
+void scsi_print_sense(char *name, struct scsi_cmnd *cmd)
 {
-       /* Assume appended output (i.e. not at start of line) */
-       sdev_printk("", cmd->device, "\n");
-       printk(KERN_INFO "        command: ");
-       scsi_print_cdb(cmd->cmnd, cmd->cmd_len, 0);
+       struct scsi_sense_hdr sshdr;
+
+       scmd_printk(KERN_INFO, cmd, "");
+       scsi_decode_sense_buffer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE,
+                                &sshdr);
+       scsi_show_sense_hdr(&sshdr);
+       scsi_decode_sense_extras(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE,
+                                &sshdr);
+       scmd_printk(KERN_INFO, cmd, "");
+       scsi_show_extd_sense(sshdr.asc, sshdr.ascq);
 }
-EXPORT_SYMBOL(scsi_print_command);
+EXPORT_SYMBOL(scsi_print_sense);
 
 #ifdef CONFIG_SCSI_CONSTANTS
 
@@ -1327,25 +1358,6 @@ static const char * const hostbyte_table[]={
 "DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY"};
 #define NUM_HOSTBYTE_STRS ARRAY_SIZE(hostbyte_table)
 
-void scsi_print_hostbyte(int scsiresult)
-{
-       int hb = host_byte(scsiresult);
-
-       printk("Hostbyte=0x%02x", hb);
-       if (hb < NUM_HOSTBYTE_STRS)
-               printk("(%s) ", hostbyte_table[hb]);
-       else
-               printk("is invalid ");
-}
-#else
-void scsi_print_hostbyte(int scsiresult)
-{
-       printk("Hostbyte=0x%02x ", host_byte(scsiresult));
-}
-#endif
-
-#ifdef CONFIG_SCSI_CONSTANTS
-
 static const char * const driverbyte_table[]={
 "DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT",  "DRIVER_MEDIA", "DRIVER_ERROR",
 "DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE"};
@@ -1356,19 +1368,35 @@ static const char * const driversuggest_table[]={"SUGGEST_OK",
 "SUGGEST_5", "SUGGEST_6", "SUGGEST_7", "SUGGEST_SENSE"};
 #define NUM_SUGGEST_STRS ARRAY_SIZE(driversuggest_table)
 
-void scsi_print_driverbyte(int scsiresult)
+void scsi_show_result(int result)
 {
-       int dr = (driver_byte(scsiresult) & DRIVER_MASK);
-       int su = ((driver_byte(scsiresult) & SUGGEST_MASK) >> 4);
+       int hb = host_byte(result);
+       int db = (driver_byte(result) & DRIVER_MASK);
+       int su = ((driver_byte(result) & SUGGEST_MASK) >> 4);
 
-       printk("Driverbyte=0x%02x ", driver_byte(scsiresult));
-       printk("(%s,%s) ",
-              (dr < NUM_DRIVERBYTE_STRS ? driverbyte_table[dr] : "invalid"),
+       printk("Result: hostbyte=%s driverbyte=%s,%s\n",
+              (hb < NUM_HOSTBYTE_STRS ? hostbyte_table[hb]     : "invalid"),
+              (db < NUM_DRIVERBYTE_STRS ? driverbyte_table[db] : "invalid"),
               (su < NUM_SUGGEST_STRS ? driversuggest_table[su] : "invalid"));
 }
+
 #else
-void scsi_print_driverbyte(int scsiresult)
+
+void scsi_show_result(int result)
 {
-       printk("Driverbyte=0x%02x ", driver_byte(scsiresult));
+       printk("Result: hostbyte=0x%02x driverbyte=0x%02x\n",
+              host_byte(result), driver_byte(result));
 }
+
 #endif
+EXPORT_SYMBOL(scsi_show_result);
+
+
+void scsi_print_result(struct scsi_cmnd *cmd)
+{
+       scmd_printk(KERN_INFO, cmd, "");
+       scsi_show_result(cmd->result);
+}
+EXPORT_SYMBOL(scsi_print_result);
+
+
index 5a49216..100b49b 100644 (file)
@@ -31,7 +31,7 @@
  *     Tunable parameters first
  */
 
-/* How many different OSM's are we allowing */ 
+/* How many different OSM's are we allowing */
 #define MAX_I2O_MODULES                64
 
 #define I2O_EVT_CAPABILITY_OTHER               0x01
@@ -63,7 +63,7 @@ struct i2o_message
        u16     size;
        u32     target_tid:12;
        u32     init_tid:12;
-       u32     function:8;     
+       u32     function:8;
        u32     initiator_context;
        /* List follows */
 };
@@ -77,7 +77,7 @@ struct i2o_device
 
        char dev_name[8];               /* linux /dev name if available */
        i2o_lct_entry lct_data;/* Device LCT information */
-       u32 flags;              
+       u32 flags;
        struct proc_dir_entry* proc_entry;      /* /proc dir */
        struct adpt_device *owner;
        struct _adpt_hba *controller;   /* Controlling IOP */
@@ -86,7 +86,7 @@ struct i2o_device
 /*
  *     Each I2O controller has one of these objects
  */
+
 struct i2o_controller
 {
        char name[16];
@@ -111,9 +111,9 @@ struct i2o_sys_tbl_entry
        u32     iop_id:12;
        u32     reserved2:20;
        u16     seg_num:12;
-       u16     i2o_version:4;
-       u8      iop_state;
-       u8      msg_type;
+       u16     i2o_version:4;
+       u8      iop_state;
+       u8      msg_type;
        u16     frame_size;
        u16     reserved3;
        u32     last_changed;
@@ -124,14 +124,14 @@ struct i2o_sys_tbl_entry
 
 struct i2o_sys_tbl
 {
-       u8      num_entries;
-       u8      version;
-       u16     reserved1;
+       u8      num_entries;
+       u8      version;
+       u16     reserved1;
        u32     change_ind;
        u32     reserved2;
        u32     reserved3;
        struct i2o_sys_tbl_entry iops[0];
-};     
+};
 
 /*
  *     I2O classes / subclasses
@@ -146,7 +146,7 @@ struct i2o_sys_tbl
 /*  Class code names
  *  (from v1.5 Table 6-1 Class Code Assignments.)
  */
+
 #define    I2O_CLASS_EXECUTIVE                         0x000
 #define    I2O_CLASS_DDM                               0x001
 #define    I2O_CLASS_RANDOM_BLOCK_STORAGE              0x010
@@ -166,7 +166,7 @@ struct i2o_sys_tbl
 
 /*  Rest of 0x092 - 0x09f reserved for peer-to-peer classes
  */
+
 #define    I2O_CLASS_MATCH_ANYCLASS                    0xffffffff
 
 /*  Subclasses
@@ -175,7 +175,7 @@ struct i2o_sys_tbl
 #define    I2O_SUBCLASS_i960                           0x001
 #define    I2O_SUBCLASS_HDM                            0x020
 #define    I2O_SUBCLASS_ISM                            0x021
+
 /* Operation functions */
 
 #define I2O_PARAMS_FIELD_GET   0x0001
@@ -219,7 +219,7 @@ struct i2o_sys_tbl
 /*
  *     Messaging API values
  */
+
 #define        I2O_CMD_ADAPTER_ASSIGN          0xB3
 #define        I2O_CMD_ADAPTER_READ            0xB2
 #define        I2O_CMD_ADAPTER_RELEASE         0xB5
@@ -284,16 +284,16 @@ struct i2o_sys_tbl
 #define I2O_PRIVATE_MSG                        0xFF
 
 /*
- *     Init Outbound Q status 
+ *     Init Outbound Q status
  */
+
 #define I2O_CMD_OUTBOUND_INIT_IN_PROGRESS      0x01
 #define I2O_CMD_OUTBOUND_INIT_REJECTED         0x02
 #define I2O_CMD_OUTBOUND_INIT_FAILED           0x03
 #define I2O_CMD_OUTBOUND_INIT_COMPLETE         0x04
 
 /*
- *     I2O Get Status State values 
+ *     I2O Get Status State values
  */
 
 #define        ADAPTER_STATE_INITIALIZING              0x01
@@ -303,7 +303,7 @@ struct i2o_sys_tbl
 #define        ADAPTER_STATE_OPERATIONAL               0x08
 #define        ADAPTER_STATE_FAILED                    0x10
 #define        ADAPTER_STATE_FAULTED                   0x11
-       
+
 /* I2O API function return values */
 
 #define I2O_RTN_NO_ERROR                       0
@@ -321,9 +321,9 @@ struct i2o_sys_tbl
 
 /* Reply message status defines for all messages */
 
-#define I2O_REPLY_STATUS_SUCCESS                       0x00
-#define I2O_REPLY_STATUS_ABORT_DIRTY                   0x01
-#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER        0x02
+#define I2O_REPLY_STATUS_SUCCESS                       0x00
+#define I2O_REPLY_STATUS_ABORT_DIRTY                   0x01
+#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER                0x02
 #define        I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER         0x03
 #define        I2O_REPLY_STATUS_ERROR_DIRTY                    0x04
 #define        I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER         0x05
@@ -338,7 +338,7 @@ struct i2o_sys_tbl
 
 #define I2O_PARAMS_STATUS_SUCCESS              0x00
 #define I2O_PARAMS_STATUS_BAD_KEY_ABORT                0x01
-#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE     0x02
+#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE     0x02
 #define I2O_PARAMS_STATUS_BUFFER_FULL          0x03
 #define I2O_PARAMS_STATUS_BUFFER_TOO_SMALL     0x04
 #define I2O_PARAMS_STATUS_FIELD_UNREADABLE     0x05
@@ -390,7 +390,7 @@ struct i2o_sys_tbl
 #define        I2O_CLAIM_MANAGEMENT                                    0x02000000
 #define        I2O_CLAIM_AUTHORIZED                                    0x03000000
 #define        I2O_CLAIM_SECONDARY                                     0x04000000
+
 /* Message header defines for VersionOffset */
 #define I2OVER15       0x0001
 #define I2OVER20       0x0002
index 82d2486..cc784e8 100644 (file)
@@ -99,7 +99,7 @@ typedef struct {
        uCHAR    eataVersion;      /* EATA Version                    */
        uLONG    cpLength;         /* EATA Command Packet Length      */
        uLONG    spLength;         /* EATA Status Packet Length       */
-       uCHAR    drqNum;           /* DRQ Index (0,5,6,7)             */ 
+       uCHAR    drqNum;           /* DRQ Index (0,5,6,7)             */
        uCHAR    flag1;            /* EATA Flags 1 (Byte 9)           */
        uCHAR    flag2;            /* EATA Flags 2 (Byte 30)          */
 } CtrlInfo;
index 4bf4477..94bc894 100644 (file)
@@ -145,8 +145,8 @@ typedef unsigned long sigLONG;
 #define FT_LOGGER       12      /* Event Logger */
 #define FT_INSTALL      13      /* An Install Program */
 #define FT_LIBRARY      14      /* Storage Manager Real-Mode Calls */
-#define FT_RESOURCE    15      /* Storage Manager Resource File */
-#define FT_MODEM_DB    16      /* Storage Manager Modem Database */
+#define FT_RESOURCE    15      /* Storage Manager Resource File */
+#define FT_MODEM_DB    16      /* Storage Manager Modem Database */
 
 /* Filetype flags - sigBYTE dsFiletypeFlags;    FLAG BITS */
 /* ------------------------------------------------------------------ */
index cd36e81..f7b9dbd 100644 (file)
@@ -195,8 +195,6 @@ static int adpt_detect(struct scsi_host_template* sht)
                        pci_dev_get(pDev);
                }
        }
-       if (pDev)
-               pci_dev_put(pDev);
 
        /* In INIT state, Activate IOPs */
        for (pHba = hba_chain; pHba; pHba = pHba->next) {
index 635c148..5016af5 100644 (file)
  * Misc. definitions                        *
  *********************************************/
 
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
 #define R_LIMIT 0x20000
 
 #define MAXISA    4
index fbc1d5c..b10eefe 100644 (file)
@@ -85,7 +85,7 @@
 static int max_id = 64;
 static int max_channel = 3;
 static int init_timeout = 5;
-static int max_requests = 50;
+static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT;
 
 #define IBMVSCSI_VERSION "1.5.8"
 
@@ -538,7 +538,8 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
        int request_status;
        int rc;
 
-       /* If we have exhausted our request limit, just fail this request.
+       /* If we have exhausted our request limit, just fail this request,
+        * unless it is for a reset or abort.
         * Note that there are rare cases involving driver generated requests 
         * (such as task management requests) that the mid layer may think we
         * can handle more requests (can_queue) when we actually can't
@@ -551,9 +552,30 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
                 */
                if (request_status < -1)
                        goto send_error;
-               /* Otherwise, if we have run out of requests */
-               else if (request_status < 0)
-                       goto send_busy;
+               /* Otherwise, we may have run out of requests. */
+               /* Abort and reset calls should make it through.
+                * Nothing except abort and reset should use the last two
+                * slots unless we had two or less to begin with.
+                */
+               else if (request_status < 2 &&
+                        evt_struct->iu.srp.cmd.opcode != SRP_TSK_MGMT) {
+                       /* In the case that we have less than two requests
+                        * available, check the server limit as a combination
+                        * of the request limit and the number of requests
+                        * in-flight (the size of the send list).  If the
+                        * server limit is greater than 2, return busy so
+                        * that the last two are reserved for reset and abort.
+                        */
+                       int server_limit = request_status;
+                       struct srp_event_struct *tmp_evt;
+
+                       list_for_each_entry(tmp_evt, &hostdata->sent, list) {
+                               server_limit++;
+                       }
+
+                       if (server_limit > 2)
+                               goto send_busy;
+               }
        }
 
        /* Copy the IU into the transfer area */
@@ -572,6 +594,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
 
                printk(KERN_ERR "ibmvscsi: send error %d\n",
                       rc);
+               atomic_inc(&hostdata->request_limit);
                goto send_error;
        }
 
@@ -581,7 +604,8 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
        unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
 
        free_event_struct(&hostdata->pool, evt_struct);
-       return SCSI_MLQUEUE_HOST_BUSY;
+       atomic_inc(&hostdata->request_limit);
+       return SCSI_MLQUEUE_HOST_BUSY;
 
  send_error:
        unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
@@ -831,23 +855,16 @@ static void login_rsp(struct srp_event_struct *evt_struct)
 
        printk(KERN_INFO "ibmvscsi: SRP_LOGIN succeeded\n");
 
-       if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta >
-           (max_requests - 2))
-               evt_struct->xfer_iu->srp.login_rsp.req_lim_delta =
-                   max_requests - 2;
+       if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta < 0)
+               printk(KERN_ERR "ibmvscsi: Invalid request_limit.\n");
 
-       /* Now we know what the real request-limit is */
+       /* Now we know what the real request-limit is.
+        * This value is set rather than added to request_limit because
+        * request_limit could have been set to -1 by this client.
+        */
        atomic_set(&hostdata->request_limit,
                   evt_struct->xfer_iu->srp.login_rsp.req_lim_delta);
 
-       hostdata->host->can_queue =
-           evt_struct->xfer_iu->srp.login_rsp.req_lim_delta - 2;
-
-       if (hostdata->host->can_queue < 1) {
-               printk(KERN_ERR "ibmvscsi: Invalid request_limit_delta\n");
-               return;
-       }
-
        /* If we had any pending I/Os, kick them */
        scsi_unblock_requests(hostdata->host);
 
@@ -1337,6 +1354,27 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
        return rc;
 }
 
+/**
+ * ibmvscsi_slave_configure: Set the "allow_restart" flag for each disk.
+ * @sdev:      struct scsi_device device to configure
+ *
+ * Enable allow_restart for a device if it is a disk.  Adjust the
+ * queue_depth here also as is required by the documentation for
+ * struct scsi_host_template.
+ */
+static int ibmvscsi_slave_configure(struct scsi_device *sdev)
+{
+       struct Scsi_Host *shost = sdev->host;
+       unsigned long lock_flags = 0;
+
+       spin_lock_irqsave(shost->host_lock, lock_flags);
+       if (sdev->type == TYPE_DISK)
+               sdev->allow_restart = 1;
+       scsi_adjust_queue_depth(sdev, 0, shost->cmd_per_lun);
+       spin_unlock_irqrestore(shost->host_lock, lock_flags);
+       return 0;
+}
+
 /* ------------------------------------------------------------
  * sysfs attributes
  */
@@ -1482,8 +1520,9 @@ static struct scsi_host_template driver_template = {
        .queuecommand = ibmvscsi_queuecommand,
        .eh_abort_handler = ibmvscsi_eh_abort_handler,
        .eh_device_reset_handler = ibmvscsi_eh_device_reset_handler,
+       .slave_configure = ibmvscsi_slave_configure,
        .cmd_per_lun = 16,
-       .can_queue = 1,         /* Updated after SRP_LOGIN */
+       .can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT,
        .this_id = -1,
        .sg_tablesize = SG_ALL,
        .use_clustering = ENABLE_CLUSTERING,
@@ -1503,6 +1542,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
 
        vdev->dev.driver_data = NULL;
 
+       driver_template.can_queue = max_requests;
        host = scsi_host_alloc(&driver_template, sizeof(*hostdata));
        if (!host) {
                printk(KERN_ERR "ibmvscsi: couldn't allocate host data\n");
index 5c6d935..77cc1d4 100644 (file)
@@ -44,6 +44,8 @@ struct Scsi_Host;
  */
 #define MAX_INDIRECT_BUFS 10
 
+#define IBMVSCSI_MAX_REQUESTS_DEFAULT 100
+
 /* ------------------------------------------------------------
  * Data Structures
  */
index a39a478..6d223dd 100644 (file)
@@ -35,7 +35,7 @@
 #include "ibmvscsi.h"
 
 #define        INITIAL_SRP_LIMIT       16
-#define        DEFAULT_MAX_SECTORS     512
+#define        DEFAULT_MAX_SECTORS     256
 
 #define        TGT_NAME        "ibmvstgt"
 
@@ -248,8 +248,8 @@ static int ibmvstgt_rdma(struct scsi_cmnd *sc, struct scatterlist *sg, int nsg,
                                                  md[i].va + mdone);
 
                        if (err != H_SUCCESS) {
-                               eprintk("rdma error %d %d\n", dir, slen);
-                               goto out;
+                               eprintk("rdma error %d %d %ld\n", dir, slen, err);
+                               return -EIO;
                        }
 
                        mlen -= slen;
@@ -265,45 +265,35 @@ static int ibmvstgt_rdma(struct scsi_cmnd *sc, struct scatterlist *sg, int nsg,
                                if (sidx > nsg) {
                                        eprintk("out of sg %p %d %d\n",
                                                iue, sidx, nsg);
-                                       goto out;
+                                       return -EIO;
                                }
                        }
                };
 
                rest -= mlen;
        }
-out:
-
        return 0;
 }
 
-static int ibmvstgt_transfer_data(struct scsi_cmnd *sc,
-                                 void (*done)(struct scsi_cmnd *))
-{
-       struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
-       int err;
-
-       err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1);
-
-       done(sc);
-
-       return err;
-}
-
 static int ibmvstgt_cmd_done(struct scsi_cmnd *sc,
                             void (*done)(struct scsi_cmnd *))
 {
        unsigned long flags;
        struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
        struct srp_target *target = iue->target;
+       int err = 0;
 
-       dprintk("%p %p %x\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0]);
+       dprintk("%p %p %x %u\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0],
+               cmd->usg_sg);
+
+       if (sc->use_sg)
+               err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1);
 
        spin_lock_irqsave(&target->lock, flags);
        list_del(&iue->ilist);
        spin_unlock_irqrestore(&target->lock, flags);
 
-       if (sc->result != SAM_STAT_GOOD) {
+       if (err|| sc->result != SAM_STAT_GOOD) {
                eprintk("operation failed %p %d %x\n",
                        iue, sc->result, vio_iu(iue)->srp.cmd.cdb[0]);
                send_rsp(iue, sc, HARDWARE_ERROR, 0x00);
@@ -503,7 +493,8 @@ static void process_iu(struct viosrp_crq *crq, struct srp_target *target)
 {
        struct vio_port *vport = target_to_port(target);
        struct iu_entry *iue;
-       long err, done;
+       long err;
+       int done = 1;
 
        iue = srp_iu_get(target);
        if (!iue) {
@@ -518,7 +509,6 @@ static void process_iu(struct viosrp_crq *crq, struct srp_target *target)
 
        if (err != H_SUCCESS) {
                eprintk("%ld transferring data error %p\n", err, iue);
-               done = 1;
                goto out;
        }
 
@@ -794,7 +784,6 @@ static struct scsi_host_template ibmvstgt_sht = {
        .use_clustering         = DISABLE_CLUSTERING,
        .max_sectors            = DEFAULT_MAX_SECTORS,
        .transfer_response      = ibmvstgt_cmd_done,
-       .transfer_data          = ibmvstgt_transfer_data,
        .eh_abort_handler       = ibmvstgt_eh_abort_handler,
        .tsk_mgmt_response      = ibmvstgt_tsk_mgmt_response,
        .shost_attrs            = ibmvstgt_attrs,
index e9bd299..2c7b77e 100644 (file)
@@ -89,10 +89,9 @@ static unsigned int ipr_log_level = IPR_DEFAULT_LOG_LEVEL;
 static unsigned int ipr_max_speed = 1;
 static int ipr_testmode = 0;
 static unsigned int ipr_fastfail = 0;
-static unsigned int ipr_transop_timeout = IPR_OPERATIONAL_TIMEOUT;
+static unsigned int ipr_transop_timeout = 0;
 static unsigned int ipr_enable_cache = 1;
 static unsigned int ipr_debug = 0;
-static int ipr_auto_create = 1;
 static DEFINE_SPINLOCK(ipr_driver_lock);
 
 /* This table describes the differences between DMA controller chips */
@@ -159,15 +158,13 @@ module_param_named(enable_cache, ipr_enable_cache, int, 0);
 MODULE_PARM_DESC(enable_cache, "Enable adapter's non-volatile write cache (default: 1)");
 module_param_named(debug, ipr_debug, int, 0);
 MODULE_PARM_DESC(debug, "Enable device driver debugging logging. Set to 1 to enable. (default: 0)");
-module_param_named(auto_create, ipr_auto_create, int, 0);
-MODULE_PARM_DESC(auto_create, "Auto-create single device RAID 0 arrays when initialized (default: 1)");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(IPR_DRIVER_VERSION);
 
 /*  A constant array of IOASCs/URCs/Error Messages */
 static const
 struct ipr_error_table_t ipr_error_table[] = {
-       {0x00000000, 1, 1,
+       {0x00000000, 1, IPR_DEFAULT_LOG_LEVEL,
        "8155: An unknown error was received"},
        {0x00330000, 0, 0,
        "Soft underlength error"},
@@ -175,37 +172,37 @@ struct ipr_error_table_t ipr_error_table[] = {
        "Command to be cancelled not found"},
        {0x00808000, 0, 0,
        "Qualified success"},
-       {0x01080000, 1, 1,
+       {0x01080000, 1, IPR_DEFAULT_LOG_LEVEL,
        "FFFE: Soft device bus error recovered by the IOA"},
-       {0x01088100, 0, 1,
+       {0x01088100, 0, IPR_DEFAULT_LOG_LEVEL,
        "4101: Soft device bus fabric error"},
-       {0x01170600, 0, 1,
+       {0x01170600, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFF9: Device sector reassign successful"},
-       {0x01170900, 0, 1,
+       {0x01170900, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFF7: Media error recovered by device rewrite procedures"},
-       {0x01180200, 0, 1,
+       {0x01180200, 0, IPR_DEFAULT_LOG_LEVEL,
        "7001: IOA sector reassignment successful"},
-       {0x01180500, 0, 1,
+       {0x01180500, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFF9: Soft media error. Sector reassignment recommended"},
-       {0x01180600, 0, 1,
+       {0x01180600, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFF7: Media error recovered by IOA rewrite procedures"},
-       {0x01418000, 0, 1,
+       {0x01418000, 0, IPR_DEFAULT_LOG_LEVEL,
        "FF3D: Soft PCI bus error recovered by the IOA"},
-       {0x01440000, 1, 1,
+       {0x01440000, 1, IPR_DEFAULT_LOG_LEVEL,
        "FFF6: Device hardware error recovered by the IOA"},
-       {0x01448100, 0, 1,
+       {0x01448100, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFF6: Device hardware error recovered by the device"},
-       {0x01448200, 1, 1,
+       {0x01448200, 1, IPR_DEFAULT_LOG_LEVEL,
        "FF3D: Soft IOA error recovered by the IOA"},
-       {0x01448300, 0, 1,
+       {0x01448300, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFFA: Undefined device response recovered by the IOA"},
-       {0x014A0000, 1, 1,
+       {0x014A0000, 1, IPR_DEFAULT_LOG_LEVEL,
        "FFF6: Device bus error, message or command phase"},
-       {0x014A8000, 0, 1,
+       {0x014A8000, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFFE: Task Management Function failed"},
-       {0x015D0000, 0, 1,
+       {0x015D0000, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFF6: Failure prediction threshold exceeded"},
-       {0x015D9200, 0, 1,
+       {0x015D9200, 0, IPR_DEFAULT_LOG_LEVEL,
        "8009: Impending cache battery pack failure"},
        {0x02040400, 0, 0,
        "34FF: Disk device format in progress"},
@@ -215,85 +212,85 @@ struct ipr_error_table_t ipr_error_table[] = {
        "No ready, IOA shutdown"},
        {0x025A0000, 0, 0,
        "Not ready, IOA has been shutdown"},
-       {0x02670100, 0, 1,
+       {0x02670100, 0, IPR_DEFAULT_LOG_LEVEL,
        "3020: Storage subsystem configuration error"},
        {0x03110B00, 0, 0,
        "FFF5: Medium error, data unreadable, recommend reassign"},
        {0x03110C00, 0, 0,
        "7000: Medium error, data unreadable, do not reassign"},
-       {0x03310000, 0, 1,
+       {0x03310000, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFF3: Disk media format bad"},
-       {0x04050000, 0, 1,
+       {0x04050000, 0, IPR_DEFAULT_LOG_LEVEL,
        "3002: Addressed device failed to respond to selection"},
-       {0x04080000, 1, 1,
+       {0x04080000, 1, IPR_DEFAULT_LOG_LEVEL,
        "3100: Device bus error"},
-       {0x04080100, 0, 1,
+       {0x04080100, 0, IPR_DEFAULT_LOG_LEVEL,
        "3109: IOA timed out a device command"},
        {0x04088000, 0, 0,
        "3120: SCSI bus is not operational"},
-       {0x04088100, 0, 1,
+       {0x04088100, 0, IPR_DEFAULT_LOG_LEVEL,
        "4100: Hard device bus fabric error"},
-       {0x04118000, 0, 1,
+       {0x04118000, 0, IPR_DEFAULT_LOG_LEVEL,
        "9000: IOA reserved area data check"},
-       {0x04118100, 0, 1,
+       {0x04118100, 0, IPR_DEFAULT_LOG_LEVEL,
        "9001: IOA reserved area invalid data pattern"},
-       {0x04118200, 0, 1,
+       {0x04118200, 0, IPR_DEFAULT_LOG_LEVEL,
        "9002: IOA reserved area LRC error"},
-       {0x04320000, 0, 1,
+       {0x04320000, 0, IPR_DEFAULT_LOG_LEVEL,
        "102E: Out of alternate sectors for disk storage"},
-       {0x04330000, 1, 1,
+       {0x04330000, 1, IPR_DEFAULT_LOG_LEVEL,
        "FFF4: Data transfer underlength error"},
-       {0x04338000, 1, 1,
+       {0x04338000, 1, IPR_DEFAULT_LOG_LEVEL,
        "FFF4: Data transfer overlength error"},
-       {0x043E0100, 0, 1,
+       {0x043E0100, 0, IPR_DEFAULT_LOG_LEVEL,
        "3400: Logical unit failure"},
-       {0x04408500, 0, 1,
+       {0x04408500, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFF4: Device microcode is corrupt"},
-       {0x04418000, 1, 1,
+       {0x04418000, 1, IPR_DEFAULT_LOG_LEVEL,
        "8150: PCI bus error"},
        {0x04430000, 1, 0,
        "Unsupported device bus message received"},
-       {0x04440000, 1, 1,
+       {0x04440000, 1, IPR_DEFAULT_LOG_LEVEL,
        "FFF4: Disk device problem"},
-       {0x04448200, 1, 1,
+       {0x04448200, 1, IPR_DEFAULT_LOG_LEVEL,
        "8150: Permanent IOA failure"},
-       {0x04448300, 0, 1,
+       {0x04448300, 0, IPR_DEFAULT_LOG_LEVEL,
        "3010: Disk device returned wrong response to IOA"},
-       {0x04448400, 0, 1,
+       {0x04448400, 0, IPR_DEFAULT_LOG_LEVEL,
        "8151: IOA microcode error"},
        {0x04448500, 0, 0,
        "Device bus status error"},
-       {0x04448600, 0, 1,
+       {0x04448600, 0, IPR_DEFAULT_LOG_LEVEL,
        "8157: IOA error requiring IOA reset to recover"},
        {0x04448700, 0, 0,
        "ATA device status error"},
        {0x04490000, 0, 0,
        "Message reject received from the device"},
-       {0x04449200, 0, 1,
+       {0x04449200, 0, IPR_DEFAULT_LOG_LEVEL,
        "8008: A permanent cache battery pack failure occurred"},
-       {0x0444A000, 0, 1,
+       {0x0444A000, 0, IPR_DEFAULT_LOG_LEVEL,
        "9090: Disk unit has been modified after the last known status"},
-       {0x0444A200, 0, 1,
+       {0x0444A200, 0, IPR_DEFAULT_LOG_LEVEL,
        "9081: IOA detected device error"},
-       {0x0444A300, 0, 1,
+       {0x0444A300, 0, IPR_DEFAULT_LOG_LEVEL,
        "9082: IOA detected device error"},
-       {0x044A0000, 1, 1,
+       {0x044A0000, 1, IPR_DEFAULT_LOG_LEVEL,
        "3110: Device bus error, message or command phase"},
-       {0x044A8000, 1, 1,
+       {0x044A8000, 1, IPR_DEFAULT_LOG_LEVEL,
        "3110: SAS Command / Task Management Function failed"},
-       {0x04670400, 0, 1,
+       {0x04670400, 0, IPR_DEFAULT_LOG_LEVEL,
        "9091: Incorrect hardware configuration change has been detected"},
-       {0x04678000, 0, 1,
+       {0x04678000, 0, IPR_DEFAULT_LOG_LEVEL,
        "9073: Invalid multi-adapter configuration"},
-       {0x04678100, 0, 1,
+       {0x04678100, 0, IPR_DEFAULT_LOG_LEVEL,
        "4010: Incorrect connection between cascaded expanders"},
-       {0x04678200, 0, 1,
+       {0x04678200, 0, IPR_DEFAULT_LOG_LEVEL,
        "4020: Connections exceed IOA design limits"},
-       {0x04678300, 0, 1,
+       {0x04678300, 0, IPR_DEFAULT_LOG_LEVEL,
        "4030: Incorrect multipath connection"},
-       {0x04679000, 0, 1,
+       {0x04679000, 0, IPR_DEFAULT_LOG_LEVEL,
        "4110: Unsupported enclosure function"},
-       {0x046E0000, 0, 1,
+       {0x046E0000, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFF4: Command to logical unit failed"},
        {0x05240000, 1, 0,
        "Illegal request, invalid request type or request packet"},
@@ -313,101 +310,103 @@ struct ipr_error_table_t ipr_error_table[] = {
        "Illegal request, command sequence error"},
        {0x052C8000, 1, 0,
        "Illegal request, dual adapter support not enabled"},
-       {0x06040500, 0, 1,
+       {0x06040500, 0, IPR_DEFAULT_LOG_LEVEL,
        "9031: Array protection temporarily suspended, protection resuming"},
-       {0x06040600, 0, 1,
+       {0x06040600, 0, IPR_DEFAULT_LOG_LEVEL,
        "9040: Array protection temporarily suspended, protection resuming"},
-       {0x06288000, 0, 1,
+       {0x06288000, 0, IPR_DEFAULT_LOG_LEVEL,
        "3140: Device bus not ready to ready transition"},
-       {0x06290000, 0, 1,
+       {0x06290000, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFFB: SCSI bus was reset"},
        {0x06290500, 0, 0,
        "FFFE: SCSI bus transition to single ended"},
        {0x06290600, 0, 0,
        "FFFE: SCSI bus transition to LVD"},
-       {0x06298000, 0, 1,
+       {0x06298000, 0, IPR_DEFAULT_LOG_LEVEL,
        "FFFB: SCSI bus was reset by another initiator"},
-       {0x063F0300, 0, 1,
+       {0x063F0300, 0, IPR_DEFAULT_LOG_LEVEL,
        "3029: A device replacement has occurred"},
-       {0x064C8000, 0, 1,
+       {0x064C8000, 0, IPR_DEFAULT_LOG_LEVEL,
        "9051: IOA cache data exists for a missing or failed device"},
-       {0x064C8100, 0, 1,
+       {0x064C8100, 0, IPR_DEFAULT_LOG_LEVEL,
        "9055: Auxiliary cache IOA contains cache data needed by the primary IOA"},
-       {0x06670100, 0, 1,
+       {0x06670100, 0, IPR_DEFAULT_LOG_LEVEL,
        "9025: Disk unit is not supported at its physical location"},
-       {0x06670600, 0, 1,
+       {0x06670600, 0, IPR_DEFAULT_LOG_LEVEL,
        "3020: IOA detected a SCSI bus configuration error"},
-       {0x06678000, 0, 1,
+       {0x06678000, 0, IPR_DEFAULT_LOG_LEVEL,
        "3150: SCSI bus configuration error"},
-       {0x06678100, 0, 1,
+       {0x06678100, 0, IPR_DEFAULT_LOG_LEVEL,
        "9074: Asymmetric advanced function disk configuration"},
-       {0x06678300, 0, 1,
+       {0x06678300, 0, IPR_DEFAULT_LOG_LEVEL,
        "4040: Incomplete multipath connection between IOA and enclosure"},
-       {0x06678400, 0, 1,
+       {0x06678400, 0, IPR_DEFAULT_LOG_LEVEL,
        "4041: Incomplete multipath connection between enclosure and device"},
-       {0x06678500, 0, 1,
+       {0x06678500, 0, IPR_DEFAULT_LOG_LEVEL,
        "9075: Incomplete multipath connection between IOA and remote IOA"},
-       {0x06678600, 0, 1,
+       {0x06678600, 0, IPR_DEFAULT_LOG_LEVEL,
        "9076: Configuration error, missing remote IOA"},
-       {0x06679100, 0, 1,
+       {0x06679100, 0, IPR_DEFAULT_LOG_LEVEL,
        "4050: Enclosure does not support a required multipath function"},
-       {0x06690200, 0, 1,
+       {0x06690200, 0, IPR_DEFAULT_LOG_LEVEL,
        "9041: Array protection temporarily suspended"},
-       {0x06698200, 0, 1,
+       {0x06698200, 0, IPR_DEFAULT_LOG_LEVEL,
        "9042: Corrupt array parity detected on specified device"},
-       {0x066B0200, 0, 1,
+       {0x066B0200, 0, IPR_DEFAULT_LOG_LEVEL,
        "9030: Array no longer protected due to missing or failed disk unit"},
-       {0x066B8000, 0, 1,
+       {0x066B8000, 0, IPR_DEFAULT_LOG_LEVEL,
        "9071: Link operational transition"},
-       {0x066B8100, 0, 1,
+       {0x066B8100, 0, IPR_DEFAULT_LOG_LEVEL,
        "9072: Link not operational transition"},
-       {0x066B8200, 0, 1,
+       {0x066B8200, 0, IPR_DEFAULT_LOG_LEVEL,
        "9032: Array exposed but still protected"},
-       {0x066B9100, 0, 1,
+       {0x066B8300, 0, IPR_DEFAULT_LOG_LEVEL + 1,
+       "70DD: Device forced failed by disrupt device command"},
+       {0x066B9100, 0, IPR_DEFAULT_LOG_LEVEL,
        "4061: Multipath redundancy level got better"},
-       {0x066B9200, 0, 1,
+       {0x066B9200, 0, IPR_DEFAULT_LOG_LEVEL,
        "4060: Multipath redundancy level got worse"},
        {0x07270000, 0, 0,
        "Failure due to other device"},
-       {0x07278000, 0, 1,
+       {0x07278000, 0, IPR_DEFAULT_LOG_LEVEL,
        "9008: IOA does not support functions expected by devices"},
-       {0x07278100, 0, 1,
+       {0x07278100, 0, IPR_DEFAULT_LOG_LEVEL,
        "9010: Cache data associated with attached devices cannot be found"},
-       {0x07278200, 0, 1,
+       {0x07278200, 0, IPR_DEFAULT_LOG_LEVEL,
        "9011: Cache data belongs to devices other than those attached"},
-       {0x07278400, 0, 1,
+       {0x07278400, 0, IPR_DEFAULT_LOG_LEVEL,
        "9020: Array missing 2 or more devices with only 1 device present"},
-       {0x07278500, 0, 1,
+       {0x07278500, 0, IPR_DEFAULT_LOG_LEVEL,
        "9021: Array missing 2 or more devices with 2 or more devices present"},
-       {0x07278600, 0, 1,
+       {0x07278600, 0, IPR_DEFAULT_LOG_LEVEL,
        "9022: Exposed array is missing a required device"},
-       {0x07278700, 0, 1,
+       {0x07278700, 0, IPR_DEFAULT_LOG_LEVEL,
        "9023: Array member(s) not at required physical locations"},
-       {0x07278800, 0, 1,
+       {0x07278800, 0, IPR_DEFAULT_LOG_LEVEL,
        "9024: Array not functional due to present hardware configuration"},
-       {0x07278900, 0, 1,
+       {0x07278900, 0, IPR_DEFAULT_LOG_LEVEL,
        "9026: Array not functional due to present hardware configuration"},
-       {0x07278A00, 0, 1,
+       {0x07278A00, 0, IPR_DEFAULT_LOG_LEVEL,
        "9027: Array is missing a device and parity is out of sync"},
-       {0x07278B00, 0, 1,
+       {0x07278B00, 0, IPR_DEFAULT_LOG_LEVEL,
        "9028: Maximum number of arrays already exist"},
-       {0x07278C00, 0, 1,
+       {0x07278C00, 0, IPR_DEFAULT_LOG_LEVEL,
        "9050: Required cache data cannot be located for a disk unit"},
-       {0x07278D00, 0, 1,
+       {0x07278D00, 0, IPR_DEFAULT_LOG_LEVEL,
        "9052: Cache data exists for a device that has been modified"},
-       {0x07278F00, 0, 1,
+       {0x07278F00, 0, IPR_DEFAULT_LOG_LEVEL,
        "9054: IOA resources not available due to previous problems"},
-       {0x07279100, 0, 1,
+       {0x07279100, 0, IPR_DEFAULT_LOG_LEVEL,
        "9092: Disk unit requires initialization before use"},
-       {0x07279200, 0, 1,
+       {0x07279200, 0, IPR_DEFAULT_LOG_LEVEL,
        "9029: Incorrect hardware configuration change has been detected"},
-       {0x07279600, 0, 1,
+       {0x07279600, 0, IPR_DEFAULT_LOG_LEVEL,
        "9060: One or more disk pairs are missing from an array"},
-       {0x07279700, 0, 1,
+       {0x07279700, 0, IPR_DEFAULT_LOG_LEVEL,
        "9061: One or more disks are missing from an array"},
-       {0x07279800, 0, 1,
+       {0x07279800, 0, IPR_DEFAULT_LOG_LEVEL,
        "9062: One or more disks are missing from an array"},
-       {0x07279900, 0, 1,
+       {0x07279900, 0, IPR_DEFAULT_LOG_LEVEL,
        "9063: Maximum number of functional arrays has been exceeded"},
        {0x0B260000, 0, 0,
        "Aborted command, invalid descriptor"},
@@ -481,12 +480,16 @@ static void ipr_reinit_ipr_cmnd(struct ipr_cmnd *ipr_cmd)
 {
        struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
        struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;
+       dma_addr_t dma_addr = be32_to_cpu(ioarcb->ioarcb_host_pci_addr);
 
        memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt));
        ioarcb->write_data_transfer_length = 0;
        ioarcb->read_data_transfer_length = 0;
        ioarcb->write_ioadl_len = 0;
        ioarcb->read_ioadl_len = 0;
+       ioarcb->write_ioadl_addr =
+               cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, ioadl));
+       ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
        ioasa->ioasc = 0;
        ioasa->residual_data_len = 0;
        ioasa->u.gata.status = 0;
@@ -1610,7 +1613,7 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg,
        /* Set indication we have logged an error */
        ioa_cfg->errors_logged++;
 
-       if (ioa_cfg->log_level < IPR_DEFAULT_LOG_LEVEL)
+       if (ioa_cfg->log_level < ipr_error_table[error_index].log_hcam)
                return;
        if (be32_to_cpu(hostrcb->hcam.length) > sizeof(hostrcb->hcam.u.raw))
                hostrcb->hcam.length = cpu_to_be32(sizeof(hostrcb->hcam.u.raw));
@@ -3850,6 +3853,8 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd)
                if (ipr_cmd->ioarcb.res_handle == res->cfgte.res_handle) {
                        if (ipr_cmd->scsi_cmd)
                                ipr_cmd->done = ipr_scsi_eh_done;
+                       if (ipr_cmd->qc)
+                               ipr_cmd->done = ipr_sata_eh_done;
                        if (ipr_cmd->qc && !(ipr_cmd->qc->flags & ATA_QCFLAG_FAILED)) {
                                ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT;
                                ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED;
@@ -4230,6 +4235,14 @@ static int ipr_build_ioadl(struct ipr_ioa_cfg *ioa_cfg,
 
                sglist = scsi_cmd->request_buffer;
 
+               if (ipr_cmd->dma_use_sg <= ARRAY_SIZE(ioarcb->add_data.u.ioadl)) {
+                       ioadl = ioarcb->add_data.u.ioadl;
+                       ioarcb->write_ioadl_addr =
+                               cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) +
+                                           offsetof(struct ipr_ioarcb, add_data));
+                       ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
+               }
+
                for (i = 0; i < ipr_cmd->dma_use_sg; i++) {
                        ioadl[i].flags_and_data_len =
                                cpu_to_be32(ioadl_flags | sg_dma_len(&sglist[i]));
@@ -4260,6 +4273,11 @@ static int ipr_build_ioadl(struct ipr_ioa_cfg *ioa_cfg,
                                                     scsi_cmd->sc_data_direction);
 
                if (likely(!pci_dma_mapping_error(ipr_cmd->dma_handle))) {
+                       ioadl = ioarcb->add_data.u.ioadl;
+                       ioarcb->write_ioadl_addr =
+                               cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) +
+                                           offsetof(struct ipr_ioarcb, add_data));
+                       ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
                        ipr_cmd->dma_use_sg = 1;
                        ioadl[0].flags_and_data_len =
                                cpu_to_be32(ioadl_flags | length | IPR_IOADL_FLAGS_LAST);
@@ -4346,11 +4364,9 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd)
  **/
 static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd)
 {
-       struct ipr_ioarcb *ioarcb;
-       struct ipr_ioasa *ioasa;
-
-       ioarcb = &ipr_cmd->ioarcb;
-       ioasa = &ipr_cmd->ioasa;
+       struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
+       struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;
+       dma_addr_t dma_addr = be32_to_cpu(ioarcb->ioarcb_host_pci_addr);
 
        memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt));
        ioarcb->write_data_transfer_length = 0;
@@ -4359,6 +4375,9 @@ static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd)
        ioarcb->read_ioadl_len = 0;
        ioasa->ioasc = 0;
        ioasa->residual_data_len = 0;
+       ioarcb->write_ioadl_addr =
+               cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, ioadl));
+       ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
 }
 
 /**
@@ -4457,12 +4476,13 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg,
 {
        int i;
        u16 data_len;
-       u32 ioasc;
+       u32 ioasc, fd_ioasc;
        struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;
        __be32 *ioasa_data = (__be32 *)ioasa;
        int error_index;
 
        ioasc = be32_to_cpu(ioasa->ioasc) & IPR_IOASC_IOASC_MASK;
+       fd_ioasc = be32_to_cpu(ioasa->fd_ioasc) & IPR_IOASC_IOASC_MASK;
 
        if (0 == ioasc)
                return;
@@ -4470,13 +4490,19 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg,
        if (ioa_cfg->log_level < IPR_DEFAULT_LOG_LEVEL)
                return;
 
-       error_index = ipr_get_error(ioasc);
+       if (ioasc == IPR_IOASC_BUS_WAS_RESET && fd_ioasc)
+               error_index = ipr_get_error(fd_ioasc);
+       else
+               error_index = ipr_get_error(ioasc);
 
        if (ioa_cfg->log_level < IPR_MAX_LOG_LEVEL) {
                /* Don't log an error if the IOA already logged one */
                if (ioasa->ilid != 0)
                        return;
 
+               if (!ipr_is_gscsi(res))
+                       return;
+
                if (ipr_error_table[error_index].log_ioasa == 0)
                        return;
        }
@@ -4636,11 +4662,11 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg,
                return;
        }
 
-       if (ipr_is_gscsi(res))
-               ipr_dump_ioasa(ioa_cfg, ipr_cmd, res);
-       else
+       if (!ipr_is_gscsi(res))
                ipr_gen_sense(ipr_cmd);
 
+       ipr_dump_ioasa(ioa_cfg, ipr_cmd, res);
+
        switch (ioasc & IPR_IOASC_IOASC_MASK) {
        case IPR_IOASC_ABORTED_CMD_TERM_BY_HOST:
                if (ipr_is_naca_model(res))
@@ -5121,7 +5147,7 @@ static unsigned int ipr_qc_issue(struct ata_queued_cmd *qc)
        struct ipr_ioarcb_ata_regs *regs;
 
        if (unlikely(!ioa_cfg->allow_cmds || ioa_cfg->ioa_is_dead))
-               return -EIO;
+               return AC_ERR_SYSTEM;
 
        ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
        ioarcb = &ipr_cmd->ioarcb;
@@ -5166,7 +5192,7 @@ static unsigned int ipr_qc_issue(struct ata_queued_cmd *qc)
 
        default:
                WARN_ON(1);
-               return -1;
+               return AC_ERR_INVALID;
        }
 
        mb();
@@ -6188,7 +6214,7 @@ static int ipr_reset_enable_ioa(struct ipr_cmnd *ipr_cmd)
        dev_info(&ioa_cfg->pdev->dev, "Initializing IOA.\n");
 
        ipr_cmd->timer.data = (unsigned long) ipr_cmd;
-       ipr_cmd->timer.expires = jiffies + (ipr_transop_timeout * HZ);
+       ipr_cmd->timer.expires = jiffies + (ioa_cfg->transop_timeout * HZ);
        ipr_cmd->timer.function = (void (*)(unsigned long))ipr_oper_timeout;
        ipr_cmd->done = ipr_reset_ioa_job;
        add_timer(&ipr_cmd->timer);
@@ -6385,6 +6411,7 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd)
        rc = pci_write_config_byte(ioa_cfg->pdev, PCI_BIST, PCI_BIST_START);
 
        if (rc != PCIBIOS_SUCCESSFUL) {
+               pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev);
                ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR);
                rc = IPR_RC_JOB_CONTINUE;
        } else {
@@ -7117,8 +7144,6 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
        ioa_cfg->pdev = pdev;
        ioa_cfg->log_level = ipr_log_level;
        ioa_cfg->doorbell = IPR_DOORBELL;
-       if (!ipr_auto_create)
-               ioa_cfg->doorbell |= IPR_RUNTIME_RESET;
        sprintf(ioa_cfg->eye_catcher, IPR_EYECATCHER);
        sprintf(ioa_cfg->trace_start, IPR_TRACE_START_LABEL);
        sprintf(ioa_cfg->ipr_free_label, IPR_FREEQ_LABEL);
@@ -7233,6 +7258,13 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
                goto out_scsi_host_put;
        }
 
+       if (ipr_transop_timeout)
+               ioa_cfg->transop_timeout = ipr_transop_timeout;
+       else if (dev_id->driver_data & IPR_USE_LONG_TRANSOP_TIMEOUT)
+               ioa_cfg->transop_timeout = IPR_LONG_OPERATIONAL_TIMEOUT;
+       else
+               ioa_cfg->transop_timeout = IPR_OPERATIONAL_TIMEOUT;
+
        ipr_regs_pci = pci_resource_start(pdev, 0);
 
        rc = pci_request_regions(pdev, IPR_NAME);
@@ -7540,29 +7572,45 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = {
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
                PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571A, 0, 0, 0 },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
-               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575B, 0, 0, 0 },
+               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575B, 0, 0,
+               IPR_USE_LONG_TRANSOP_TIMEOUT },
        { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
              PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 },
        { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
              PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 },
        { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
-             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, 0 },
+             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0,
+             IPR_USE_LONG_TRANSOP_TIMEOUT },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
              PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
              PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
-             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, 0 },
+             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0,
+             IPR_USE_LONG_TRANSOP_TIMEOUT },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
+             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_574E, 0, 0, 0 },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
+             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575D, 0, 0,
+             IPR_USE_LONG_TRANSOP_TIMEOUT },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
+             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B3, 0, 0, 0 },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
-             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0, 0 },
+             PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0,
+             IPR_USE_LONG_TRANSOP_TIMEOUT },
        { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE,
                PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, 0, 0, 0 },
        { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
                PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571E, 0, 0, 0 },
        { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
-               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, 0, 0, 0 },
+               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, 0, 0,
+               IPR_USE_LONG_TRANSOP_TIMEOUT },
        { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
-               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, 0, 0, 0 },
+               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, 0, 0,
+               IPR_USE_LONG_TRANSOP_TIMEOUT },
+       { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SCAMP_E,
+               PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_574D, 0, 0,
+               IPR_USE_LONG_TRANSOP_TIMEOUT },
        { }
 };
 MODULE_DEVICE_TABLE(pci, ipr_pci_table);
index 88f285d..bc53d7c 100644 (file)
@@ -37,8 +37,8 @@
 /*
  * Literals
  */
-#define IPR_DRIVER_VERSION "2.3.1"
-#define IPR_DRIVER_DATE "(January 23, 2007)"
+#define IPR_DRIVER_VERSION "2.3.2"
+#define IPR_DRIVER_DATE "(March 23, 2007)"
 
 /*
  * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
@@ -55,6 +55,7 @@
 #define IPR_NUM_BASE_CMD_BLKS                          100
 
 #define PCI_DEVICE_ID_IBM_OBSIDIAN_E   0x0339
+#define PCI_DEVICE_ID_IBM_SCAMP_E              0x034A
 
 #define IPR_SUBS_DEV_ID_2780   0x0264
 #define IPR_SUBS_DEV_ID_5702   0x0266
 #define IPR_SUBS_DEV_ID_572A   0x02C1
 #define IPR_SUBS_DEV_ID_572B   0x02C2
 #define IPR_SUBS_DEV_ID_572F   0x02C3
+#define IPR_SUBS_DEV_ID_574D   0x030B
+#define IPR_SUBS_DEV_ID_574E   0x030A
 #define IPR_SUBS_DEV_ID_575B   0x030D
 #define IPR_SUBS_DEV_ID_575C   0x0338
+#define IPR_SUBS_DEV_ID_575D   0x033E
+#define IPR_SUBS_DEV_ID_57B3   0x033A
 #define IPR_SUBS_DEV_ID_57B7   0x0360
 #define IPR_SUBS_DEV_ID_57B8   0x02C2
 
 #define IPR_IOASC_IOA_WAS_RESET                        0x10000001
 #define IPR_IOASC_PCI_ACCESS_ERROR                     0x10000002
 
+/* Driver data flags */
+#define IPR_USE_LONG_TRANSOP_TIMEOUT           0x00000001
+
 #define IPR_DEFAULT_MAX_ERROR_DUMP                     984
 #define IPR_NUM_LOG_HCAMS                              2
 #define IPR_NUM_CFG_CHG_HCAMS                          2
 #define IPR_SET_SUP_DEVICE_TIMEOUT             (2 * 60 * HZ)
 #define IPR_REQUEST_SENSE_TIMEOUT              (10 * HZ)
 #define IPR_OPERATIONAL_TIMEOUT                (5 * 60)
+#define IPR_LONG_OPERATIONAL_TIMEOUT   (12 * 60)
 #define IPR_WAIT_FOR_RESET_TIMEOUT             (2 * HZ)
 #define IPR_CHECK_FOR_RESET_TIMEOUT            (HZ / 10)
 #define IPR_WAIT_FOR_BIST_TIMEOUT              (2 * HZ)
@@ -413,9 +422,25 @@ struct ipr_ioarcb_ata_regs {
        u8 ctl;
 }__attribute__ ((packed, aligned(4)));
 
+struct ipr_ioadl_desc {
+       __be32 flags_and_data_len;
+#define IPR_IOADL_FLAGS_MASK           0xff000000
+#define IPR_IOADL_GET_FLAGS(x) (be32_to_cpu(x) & IPR_IOADL_FLAGS_MASK)
+#define IPR_IOADL_DATA_LEN_MASK                0x00ffffff
+#define IPR_IOADL_GET_DATA_LEN(x) (be32_to_cpu(x) & IPR_IOADL_DATA_LEN_MASK)
+#define IPR_IOADL_FLAGS_READ           0x48000000
+#define IPR_IOADL_FLAGS_READ_LAST      0x49000000
+#define IPR_IOADL_FLAGS_WRITE          0x68000000
+#define IPR_IOADL_FLAGS_WRITE_LAST     0x69000000
+#define IPR_IOADL_FLAGS_LAST           0x01000000
+
+       __be32 address;
+}__attribute__((packed, aligned (8)));
+
 struct ipr_ioarcb_add_data {
        union {
                struct ipr_ioarcb_ata_regs regs;
+               struct ipr_ioadl_desc ioadl[5];
                __be32 add_cmd_parms[10];
        }u;
 }__attribute__ ((packed, aligned(4)));
@@ -447,21 +472,6 @@ struct ipr_ioarcb {
        struct ipr_ioarcb_add_data add_data;
 }__attribute__((packed, aligned (4)));
 
-struct ipr_ioadl_desc {
-       __be32 flags_and_data_len;
-#define IPR_IOADL_FLAGS_MASK           0xff000000
-#define IPR_IOADL_GET_FLAGS(x) (be32_to_cpu(x) & IPR_IOADL_FLAGS_MASK)
-#define IPR_IOADL_DATA_LEN_MASK                0x00ffffff
-#define IPR_IOADL_GET_DATA_LEN(x) (be32_to_cpu(x) & IPR_IOADL_DATA_LEN_MASK)
-#define IPR_IOADL_FLAGS_READ           0x48000000
-#define IPR_IOADL_FLAGS_READ_LAST      0x49000000
-#define IPR_IOADL_FLAGS_WRITE          0x68000000
-#define IPR_IOADL_FLAGS_WRITE_LAST     0x69000000
-#define IPR_IOADL_FLAGS_LAST           0x01000000
-
-       __be32 address;
-}__attribute__((packed, aligned (8)));
-
 struct ipr_ioasa_vset {
        __be32 failing_lba_hi;
        __be32 failing_lba_lo;
@@ -1119,6 +1129,7 @@ struct ipr_ioa_cfg {
 
        struct ipr_bus_attributes bus_attr[IPR_MAX_NUM_BUSES];
 
+       unsigned int transop_timeout;
        const struct ipr_chip_cfg_t *chip_cfg;
 
        void __iomem *hdw_dma_regs;     /* iomapped PCI memory space */
index 8f55e14..c9a3abf 100644 (file)
@@ -527,12 +527,12 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn)
                 * than 8K, but there are no targets that currently do this.
                 * For now we fail until we find a vendor that needs it
                 */
-               if (DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH <
+               if (ISCSI_DEF_MAX_RECV_SEG_LEN <
                    tcp_conn->in.datalen) {
                        printk(KERN_ERR "iscsi_tcp: received buffer of len %u "
                              "but conn buffer is only %u (opcode %0x)\n",
                              tcp_conn->in.datalen,
-                             DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, opcode);
+                             ISCSI_DEF_MAX_RECV_SEG_LEN, opcode);
                        rc = ISCSI_ERR_PROTO;
                        break;
                }
@@ -1762,7 +1762,7 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
         * due to strange issues with iser these are not set
         * in iscsi_conn_setup
         */
-       conn->max_recv_dlength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
+       conn->max_recv_dlength = ISCSI_DEF_MAX_RECV_SEG_LEN;
 
        tcp_conn = kzalloc(sizeof(*tcp_conn), GFP_KERNEL);
        if (!tcp_conn)
@@ -1777,14 +1777,24 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
        tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
                                                  CRYPTO_ALG_ASYNC);
        tcp_conn->tx_hash.flags = 0;
-       if (IS_ERR(tcp_conn->tx_hash.tfm))
+       if (IS_ERR(tcp_conn->tx_hash.tfm)) {
+               printk(KERN_ERR "Could not create connection due to crc32c "
+                      "loading error %ld. Make sure the crc32c module is "
+                      "built as a module or into the kernel\n",
+                       PTR_ERR(tcp_conn->tx_hash.tfm));
                goto free_tcp_conn;
+       }
 
        tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
                                                  CRYPTO_ALG_ASYNC);
        tcp_conn->rx_hash.flags = 0;
-       if (IS_ERR(tcp_conn->rx_hash.tfm))
+       if (IS_ERR(tcp_conn->rx_hash.tfm)) {
+               printk(KERN_ERR "Could not create connection due to crc32c "
+                      "loading error %ld. Make sure the crc32c module is "
+                      "built as a module or into the kernel\n",
+                       PTR_ERR(tcp_conn->rx_hash.tfm));
                goto free_tx_tfm;
+       }
 
        return cls_conn;
 
@@ -2138,6 +2148,7 @@ static struct scsi_host_template iscsi_sht = {
        .change_queue_depth     = iscsi_change_queue_depth,
        .can_queue              = ISCSI_XMIT_CMDS_MAX - 1,
        .sg_tablesize           = ISCSI_SG_TABLESIZE,
+       .max_sectors            = 0xFFFF,
        .cmd_per_lun            = ISCSI_DEF_CMD_PER_LUN,
        .eh_abort_handler       = iscsi_eh_abort,
        .eh_host_reset_handler  = iscsi_eh_host_reset,
index 7c75771..3f5b9b4 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/mutex.h>
 #include <linux/kfifo.h>
 #include <linux/delay.h>
+#include <asm/unaligned.h>
 #include <net/tcp.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
@@ -269,14 +270,14 @@ invalid_datalen:
                        goto out;
                }
 
-               senselen = be16_to_cpu(*(__be16 *)data);
+               senselen = be16_to_cpu(get_unaligned((__be16 *) data));
                if (datalen < senselen)
                        goto invalid_datalen;
 
                memcpy(sc->sense_buffer, data + 2,
                       min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
                debug_scsi("copied %d bytes of sense\n",
-                          min(senselen, SCSI_SENSE_BUFFERSIZE));
+                          min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
        }
 
        if (sc->sc_data_direction == DMA_TO_DEVICE)
@@ -577,7 +578,7 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
 }
 EXPORT_SYMBOL_GPL(iscsi_conn_failure);
 
-static int iscsi_xmit_imm_task(struct iscsi_conn *conn)
+static int iscsi_xmit_mtask(struct iscsi_conn *conn)
 {
        struct iscsi_hdr *hdr = conn->mtask->hdr;
        int rc, was_logout = 0;
@@ -591,6 +592,9 @@ static int iscsi_xmit_imm_task(struct iscsi_conn *conn)
        if (rc)
                return rc;
 
+       /* done with this in-progress mtask */
+       conn->mtask = NULL;
+
        if (was_logout) {
                set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
                return -ENODATA;
@@ -643,11 +647,9 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
                conn->ctask = NULL;
        }
        if (conn->mtask) {
-               rc = iscsi_xmit_imm_task(conn);
+               rc = iscsi_xmit_mtask(conn);
                if (rc)
                        goto again;
-               /* done with this in-progress mtask */
-               conn->mtask = NULL;
        }
 
        /* process immediate first */
@@ -658,12 +660,10 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
                        list_add_tail(&conn->mtask->running,
                                      &conn->mgmt_run_list);
                        spin_unlock_bh(&conn->session->lock);
-                       rc = iscsi_xmit_imm_task(conn);
+                       rc = iscsi_xmit_mtask(conn);
                        if (rc)
                                goto again;
                }
-               /* done with this mtask */
-               conn->mtask = NULL;
        }
 
        /* process command queue */
@@ -701,12 +701,10 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
                        list_add_tail(&conn->mtask->running,
                                      &conn->mgmt_run_list);
                        spin_unlock_bh(&conn->session->lock);
-                       rc = tt->xmit_mgmt_task(conn, conn->mtask);
-                       if (rc)
+                       rc = iscsi_xmit_mtask(conn);
+                       if (rc)
                                goto again;
                }
-               /* done with this mtask */
-               conn->mtask = NULL;
        }
 
        return -ENODATA;
@@ -1523,7 +1521,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
        }
        spin_unlock_bh(&session->lock);
 
-       data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL);
+       data = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN, GFP_KERNEL);
        if (!data)
                goto login_mtask_data_alloc_fail;
        conn->login_mtask->data = conn->data = data;
@@ -1597,6 +1595,9 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
                wake_up(&conn->ehwait);
        }
 
+       /* flush queued up work because we free the connection below */
+       scsi_flush_work(session->host);
+
        spin_lock_bh(&session->lock);
        kfree(conn->data);
        kfree(conn->persistent_address);
index dc70c18..e34442e 100644 (file)
@@ -22,7 +22,6 @@
  *
  */
 
-#include <linux/pci.h>
 #include <linux/scatterlist.h>
 
 #include "sas_internal.h"
index 89403b0..5631c19 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/kfifo.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
-#include <linux/pci.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_tcq.h>
@@ -225,8 +224,7 @@ static int srp_indirect_data(struct scsi_cmnd *sc, struct srp_cmd *cmd,
        struct srp_direct_buf *md = NULL;
        struct scatterlist dummy, *sg = NULL;
        dma_addr_t token = 0;
-       long err;
-       unsigned int done = 0;
+       int err = 0;
        int nmd, nsg = 0, len;
 
        if (dma_map || ext_desc) {
@@ -258,8 +256,8 @@ static int srp_indirect_data(struct scsi_cmnd *sc, struct srp_cmd *cmd,
                sg_dma_address(&dummy) = token;
                err = rdma_io(sc, &dummy, 1, &id->table_desc, 1, DMA_TO_DEVICE,
                              id->table_desc.len);
-               if (err < 0) {
-                       eprintk("Error copying indirect table %ld\n", err);
+               if (err) {
+                       eprintk("Error copying indirect table %d\n", err);
                        goto free_mem;
                }
        } else {
@@ -272,6 +270,7 @@ rdma:
                nsg = dma_map_sg(iue->target->dev, sg, sc->use_sg, DMA_BIDIRECTIONAL);
                if (!nsg) {
                        eprintk("fail to map %p %d\n", iue, sc->use_sg);
+                       err = -EIO;
                        goto free_mem;
                }
                len = min(sc->request_bufflen, id->len);
@@ -287,7 +286,7 @@ free_mem:
        if (token && dma_map)
                dma_free_coherent(iue->target->dev, id->table_desc.len, md, token);
 
-       return done;
+       return err;
 }
 
 static int data_out_desc_size(struct srp_cmd *cmd)
@@ -352,7 +351,7 @@ int srp_transfer_data(struct scsi_cmnd *sc, struct srp_cmd *cmd,
                break;
        default:
                eprintk("Unknown format %d %x\n", dir, format);
-               break;
+               err = -EINVAL;
        }
 
        return err;
index 057fd7e..dcf6106 100644 (file)
@@ -671,7 +671,7 @@ static int
 lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd, int len)
 {
        uint8_t lenlo, lenhi;
-       uint32_t Length;
+       int Length;
        int i, j;
        int finished = 0;
        int index = 0;
index 0aa3304..7fc6e06 100644 (file)
@@ -2088,7 +2088,7 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor)
 static inline int
 make_local_pdev(adapter_t *adapter, struct pci_dev **pdev)
 {
-       *pdev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
+       *pdev = alloc_pci_dev();
 
        if( *pdev == NULL ) return -1;
 
index a967fad..08060fb 100644 (file)
@@ -87,6 +87,7 @@ MODULE_AUTHOR("Willem Riede");
 MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
 
 module_param(max_dev, int, 0444);
 MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
diff --git a/drivers/scsi/pci2000.h b/drivers/scsi/pci2000.h
deleted file mode 100644 (file)
index 0ebd8ce..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-/****************************************************************************
- * Perceptive Solutions, Inc. PCI-2000 device driver for Linux.
- *
- * pci2000.h - Linux Host Driver for PCI-2000 IntelliCache SCSI Adapters
- *
- * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
- * All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that redistributions of source
- * code retain the above copyright notice and this comment without
- * modification.
- *
- * Technical updates and product information at:
- *  http://www.psidisk.com
- *
- * Please send questions, comments, bug reports to:
- *  tech@psidisk.com Technical Support
- *
- ****************************************************************************/
-#ifndef _PCI2000_H
-#define _PCI2000_H
-
-#include <linux/types.h>
-
-#ifndef        PSI_EIDE_SCSIOP
-#define        PSI_EIDE_SCSIOP 1
-
-#define        LINUXVERSION(v,p,s)    (((v)<<16) + ((p)<<8) + (s))
-
-/************************************************/
-/*             definition of standard data types               */
-/************************************************/
-#define        CHAR    char
-#define        UCHAR   unsigned char
-#define        SHORT   short
-#define        USHORT  unsigned short
-#define        BOOL    long
-#define        LONG    long
-#define        ULONG   unsigned long
-#define        VOID    void
-
-typedef        CHAR    *PCHAR;
-typedef        UCHAR   *PUCHAR;
-typedef        SHORT   *PSHORT;
-typedef        USHORT  *PUSHORT;
-typedef        BOOL    *PBOOL;
-typedef        LONG    *PLONG;
-typedef        ULONG   *PULONG;
-typedef        VOID    *PVOID;
-
-
-/************************************************/
-/*             Misc. macros                                                    */
-/************************************************/
-#define ANY2SCSI(up, p)                                        \
-((UCHAR *)up)[0] = (((ULONG)(p)) >> 8);        \
-((UCHAR *)up)[1] = ((ULONG)(p));
-
-#define SCSI2LONG(up)                                  \
-( (((long)*(((UCHAR *)up))) << 16)             \
-+ (((long)(((UCHAR *)up)[1])) << 8)            \
-+ ((long)(((UCHAR *)up)[2])) )
-
-#define XANY2SCSI(up, p)                               \
-((UCHAR *)up)[0] = ((long)(p)) >> 24;  \
-((UCHAR *)up)[1] = ((long)(p)) >> 16;  \
-((UCHAR *)up)[2] = ((long)(p)) >> 8;   \
-((UCHAR *)up)[3] = ((long)(p));
-
-#define XSCSI2LONG(up)                                 \
-( (((long)(((UCHAR *)up)[0])) << 24)   \
-+ (((long)(((UCHAR *)up)[1])) << 16)   \
-+ (((long)(((UCHAR *)up)[2])) <<  8)   \
-+ ((long)(((UCHAR *)up)[3])) )
-
-/************************************************/
-/*             SCSI CDB operation codes                                */
-/************************************************/
-#define SCSIOP_TEST_UNIT_READY         0x00
-#define SCSIOP_REZERO_UNIT                     0x01
-#define SCSIOP_REWIND                          0x01
-#define SCSIOP_REQUEST_BLOCK_ADDR      0x02
-#define SCSIOP_REQUEST_SENSE           0x03
-#define SCSIOP_FORMAT_UNIT                     0x04
-#define SCSIOP_READ_BLOCK_LIMITS       0x05
-#define SCSIOP_REASSIGN_BLOCKS         0x07
-#define SCSIOP_READ6                           0x08
-#define SCSIOP_RECEIVE                         0x08
-#define SCSIOP_WRITE6                          0x0A
-#define SCSIOP_PRINT                           0x0A
-#define SCSIOP_SEND                                    0x0A
-#define SCSIOP_SEEK6                           0x0B
-#define SCSIOP_TRACK_SELECT                    0x0B
-#define SCSIOP_SLEW_PRINT                      0x0B
-#define SCSIOP_SEEK_BLOCK                      0x0C
-#define SCSIOP_PARTITION                       0x0D
-#define SCSIOP_READ_REVERSE                    0x0F
-#define SCSIOP_WRITE_FILEMARKS         0x10
-#define SCSIOP_FLUSH_BUFFER                    0x10
-#define SCSIOP_SPACE                           0x11
-#define SCSIOP_INQUIRY                         0x12
-#define SCSIOP_VERIFY6                         0x13
-#define SCSIOP_RECOVER_BUF_DATA                0x14
-#define SCSIOP_MODE_SELECT                     0x15
-#define SCSIOP_RESERVE_UNIT                    0x16
-#define SCSIOP_RELEASE_UNIT                    0x17
-#define SCSIOP_COPY                                    0x18
-#define SCSIOP_ERASE                           0x19
-#define SCSIOP_MODE_SENSE                      0x1A
-#define SCSIOP_START_STOP_UNIT         0x1B
-#define SCSIOP_STOP_PRINT                      0x1B
-#define SCSIOP_LOAD_UNLOAD                     0x1B
-#define SCSIOP_RECEIVE_DIAGNOSTIC      0x1C
-#define SCSIOP_SEND_DIAGNOSTIC         0x1D
-#define SCSIOP_MEDIUM_REMOVAL          0x1E
-#define SCSIOP_READ_CAPACITY           0x25
-#define SCSIOP_READ                                    0x28
-#define SCSIOP_WRITE                           0x2A
-#define SCSIOP_SEEK                                    0x2B
-#define SCSIOP_LOCATE                          0x2B
-#define SCSIOP_WRITE_VERIFY                    0x2E
-#define SCSIOP_VERIFY                          0x2F
-#define SCSIOP_SEARCH_DATA_HIGH                0x30
-#define SCSIOP_SEARCH_DATA_EQUAL       0x31
-#define SCSIOP_SEARCH_DATA_LOW         0x32
-#define SCSIOP_SET_LIMITS                      0x33
-#define SCSIOP_READ_POSITION           0x34
-#define SCSIOP_SYNCHRONIZE_CACHE       0x35
-#define SCSIOP_COMPARE                         0x39
-#define SCSIOP_COPY_COMPARE                    0x3A
-#define SCSIOP_WRITE_DATA_BUFF         0x3B
-#define SCSIOP_READ_DATA_BUFF          0x3C
-#define SCSIOP_CHANGE_DEFINITION       0x40
-#define SCSIOP_READ_SUB_CHANNEL                0x42
-#define SCSIOP_READ_TOC                                0x43
-#define SCSIOP_READ_HEADER                     0x44
-#define SCSIOP_PLAY_AUDIO                      0x45
-#define SCSIOP_PLAY_AUDIO_MSF          0x47
-#define SCSIOP_PLAY_TRACK_INDEX                0x48
-#define SCSIOP_PLAY_TRACK_RELATIVE     0x49
-#define SCSIOP_PAUSE_RESUME                    0x4B
-#define SCSIOP_LOG_SELECT                      0x4C
-#define SCSIOP_LOG_SENSE                       0x4D
-#define SCSIOP_MODE_SELECT10           0x55
-#define SCSIOP_MODE_SENSE10                    0x5A
-#define SCSIOP_LOAD_UNLOAD_SLOT                0xA6
-#define SCSIOP_MECHANISM_STATUS                0xBD
-#define SCSIOP_READ_CD                         0xBE
-
-// SCSI read capacity structure
-typedef        struct _READ_CAPACITY_DATA
-       {
-       ULONG blks;                             /* total blocks (converted to little endian) */
-       ULONG blksiz;                   /* size of each (converted to little endian) */
-       }       READ_CAPACITY_DATA, *PREAD_CAPACITY_DATA;
-
-// SCSI inquiry data
-typedef struct _INQUIRYDATA
-       {
-       UCHAR DeviceType                        :5;
-       UCHAR DeviceTypeQualifier       :3;
-       UCHAR DeviceTypeModifier        :7;
-       UCHAR RemovableMedia            :1;
-    UCHAR Versions;
-    UCHAR ResponseDataFormat;
-    UCHAR AdditionalLength;
-    UCHAR Reserved[2];
-       UCHAR SoftReset                         :1;
-       UCHAR CommandQueue                      :1;
-       UCHAR Reserved2                         :1;
-       UCHAR LinkedCommands            :1;
-       UCHAR Synchronous                       :1;
-       UCHAR Wide16Bit                         :1;
-       UCHAR Wide32Bit                         :1;
-       UCHAR RelativeAddressing        :1;
-    UCHAR VendorId[8];
-    UCHAR ProductId[16];
-    UCHAR ProductRevisionLevel[4];
-    UCHAR VendorSpecific[20];
-    UCHAR Reserved3[40];
-       }       INQUIRYDATA, *PINQUIRYDATA;
-
-#endif
-
-// function prototypes
-int Pci2000_Detect                     (struct scsi_host_template *tpnt);
-int Pci2000_Command                    (Scsi_Cmnd *SCpnt);
-int Pci2000_QueueCommand       (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
-int Pci2000_Abort                      (Scsi_Cmnd *SCpnt);
-int Pci2000_Reset                      (Scsi_Cmnd *SCpnt, unsigned int flags);
-int Pci2000_Release                    (struct Scsi_Host *pshost);
-int Pci2000_BiosParam          (struct scsi_device *sdev,
-                                       struct block_device *bdev,
-                                       sector_t capacity, int geom[]);
-
-#endif
index eac8e17..7dd787f 100644 (file)
@@ -3,11 +3,11 @@
 #
 
 menu "PCMCIA SCSI adapter support"
-       depends on SCSI!=n && PCMCIA!=n && MODULES
+       depends on SCSI!=n && PCMCIA!=n
 
 config PCMCIA_AHA152X
        tristate "Adaptec AHA152X PCMCIA support"
-       depends on m && !64BIT
+       depends on !64BIT
        select SCSI_SPI_ATTRS
        help
          Say Y here if you intend to attach this type of PCMCIA SCSI host
@@ -18,7 +18,6 @@ config PCMCIA_AHA152X
 
 config PCMCIA_FDOMAIN
        tristate "Future Domain PCMCIA support"
-       depends on m
        help
          Say Y here if you intend to attach this type of PCMCIA SCSI host
          adapter to your computer.
@@ -28,7 +27,7 @@ config PCMCIA_FDOMAIN
 
 config PCMCIA_NINJA_SCSI
        tristate "NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support"
-       depends on m && !64BIT
+       depends on !64BIT
        help
          If you intend to attach this type of PCMCIA SCSI host adapter to
          your computer, say Y here and read
@@ -62,7 +61,6 @@ config PCMCIA_NINJA_SCSI
 
 config PCMCIA_QLOGIC
        tristate "Qlogic PCMCIA support"
-       depends on m
        help
          Say Y here if you intend to attach this type of PCMCIA SCSI host
          adapter to your computer.
@@ -72,7 +70,6 @@ config PCMCIA_QLOGIC
 
 config PCMCIA_SYM53C500
        tristate "Symbios 53c500 PCMCIA support"
-       depends on m
        help
          Say Y here if you have a New Media Bus Toaster or other PCMCIA
          SCSI adapter based on the Symbios 53c500 controller.
index 05f4f2a..e8948b6 100644 (file)
@@ -1478,14 +1478,17 @@ typedef union {
        uint32_t b24 : 24;
 
        struct {
-               uint8_t d_id[3];
-               uint8_t rsvd_1;
-       } r;
-
-       struct {
+#ifdef __BIG_ENDIAN
+               uint8_t domain;
+               uint8_t area;
+               uint8_t al_pa;
+#elif __LITTLE_ENDIAN
                uint8_t al_pa;
                uint8_t area;
                uint8_t domain;
+#else
+#error "__BIG_ENDIAN or __LITTLE_ENDIAN must be defined!"
+#endif
                uint8_t rsvd_1;
        } b;
 } port_id_t;
index 98c01cd..3e296ab 100644 (file)
 
 #include "qla_devtbl.h"
 
+#ifdef CONFIG_SPARC
+#include <asm/prom.h>
+#include <asm/pbm.h>
+#endif
+
 /* XXX(hch): this is ugly, but we don't want to pull in exioctl.h */
 #ifndef EXT_IS_LUN_BIT_SET
 #define EXT_IS_LUN_BIT_SET(P,L) \
@@ -88,12 +93,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
 
        qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n");
 
-       rval = ha->isp_ops.nvram_config(ha);
-       if (rval) {
-               DEBUG2(printk("scsi(%ld): Unable to verify NVRAM data.\n",
-                   ha->host_no));
-               return rval;
-       }
+       ha->isp_ops.nvram_config(ha);
 
        if (ha->flags.disable_serdes) {
                /* Mask HBA via NVRAM settings? */
@@ -1393,6 +1393,28 @@ qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *de
        }
 }
 
+/* On sparc systems, obtain port and node WWN from firmware
+ * properties.
+ */
+static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, nvram_t *nv)
+{
+#ifdef CONFIG_SPARC
+       struct pci_dev *pdev = ha->pdev;
+       struct pcidev_cookie *pcp = pdev->sysdata;
+       struct device_node *dp = pcp->prom_node;
+       u8 *val;
+       int len;
+
+       val = of_get_property(dp, "port-wwn", &len);
+       if (val && len >= WWN_SIZE)
+               memcpy(nv->port_name, val, WWN_SIZE);
+
+       val = of_get_property(dp, "node-wwn", &len);
+       if (val && len >= WWN_SIZE)
+               memcpy(nv->node_name, val, WWN_SIZE);
+#endif
+}
+
 /*
 * NVRAM configuration for ISP 2xxx
 *
@@ -1409,6 +1431,7 @@ qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *de
 int
 qla2x00_nvram_config(scsi_qla_host_t *ha)
 {
+       int             rval;
        uint8_t         chksum = 0;
        uint16_t        cnt;
        uint8_t         *dptr1, *dptr2;
@@ -1417,6 +1440,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
        uint8_t         *ptr = (uint8_t *)ha->request_ring;
        struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
 
+       rval = QLA_SUCCESS;
+
        /* Determine NVRAM starting address. */
        ha->nvram_size = sizeof(nvram_t);
        ha->nvram_base = 0;
@@ -1440,7 +1465,57 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
                qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: "
                    "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0],
                    nv->nvram_version);
-               return QLA_FUNCTION_FAILED;
+               qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
+                   "invalid -- WWPN) defaults.\n");
+
+               /*
+                * Set default initialization control block.
+                */
+               memset(nv, 0, ha->nvram_size);
+               nv->parameter_block_version = ICB_VERSION;
+
+               if (IS_QLA23XX(ha)) {
+                       nv->firmware_options[0] = BIT_2 | BIT_1;
+                       nv->firmware_options[1] = BIT_7 | BIT_5;
+                       nv->add_firmware_options[0] = BIT_5;
+                       nv->add_firmware_options[1] = BIT_5 | BIT_4;
+                       nv->frame_payload_size = __constant_cpu_to_le16(2048);
+                       nv->special_options[1] = BIT_7;
+               } else if (IS_QLA2200(ha)) {
+                       nv->firmware_options[0] = BIT_2 | BIT_1;
+                       nv->firmware_options[1] = BIT_7 | BIT_5;
+                       nv->add_firmware_options[0] = BIT_5;
+                       nv->add_firmware_options[1] = BIT_5 | BIT_4;
+                       nv->frame_payload_size = __constant_cpu_to_le16(1024);
+               } else if (IS_QLA2100(ha)) {
+                       nv->firmware_options[0] = BIT_3 | BIT_1;
+                       nv->firmware_options[1] = BIT_5;
+                       nv->frame_payload_size = __constant_cpu_to_le16(1024);
+               }
+
+               nv->max_iocb_allocation = __constant_cpu_to_le16(256);
+               nv->execution_throttle = __constant_cpu_to_le16(16);
+               nv->retry_count = 8;
+               nv->retry_delay = 1;
+
+               nv->port_name[0] = 33;
+               nv->port_name[3] = 224;
+               nv->port_name[4] = 139;
+
+               qla2xxx_nvram_wwn_from_ofw(ha, nv);
+
+               nv->login_timeout = 4;
+
+               /*
+                * Set default host adapter parameters
+                */
+               nv->host_p[1] = BIT_2;
+               nv->reset_delay = 5;
+               nv->port_down_retry_count = 8;
+               nv->max_luns_per_target = __constant_cpu_to_le16(8);
+               nv->link_down_timeout = 60;
+
+               rval = 1;
        }
 
 #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
@@ -1653,7 +1728,11 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
                }
        }
 
-       return QLA_SUCCESS;
+       if (rval) {
+               DEBUG2_3(printk(KERN_WARNING
+                   "scsi(%ld): NVRAM configuration failed!\n", ha->host_no));
+       }
+       return (rval);
 }
 
 static void
@@ -3071,9 +3150,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
 
                ha->isp_ops.get_flash_version(ha, ha->request_ring);
 
-               rval = ha->isp_ops.nvram_config(ha);
-               if (rval)
-                       goto isp_abort_retry;
+               ha->isp_ops.nvram_config(ha);
 
                if (!qla2x00_restart_isp(ha)) {
                        clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
@@ -3103,7 +3180,6 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
                                }
                        }
                } else {        /* failed the ISP abort */
-isp_abort_retry:
                        ha->flags.online = 1;
                        if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) {
                                if (ha->isp_abort_cnt == 0) {
@@ -3290,9 +3366,32 @@ qla24xx_reset_adapter(scsi_qla_host_t *ha)
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 }
 
+/* On sparc systems, obtain port and node WWN from firmware
+ * properties.
+ */
+static void qla24xx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, struct nvram_24xx *nv)
+{
+#ifdef CONFIG_SPARC
+       struct pci_dev *pdev = ha->pdev;
+       struct pcidev_cookie *pcp = pdev->sysdata;
+       struct device_node *dp = pcp->prom_node;
+       u8 *val;
+       int len;
+
+       val = of_get_property(dp, "port-wwn", &len);
+       if (val && len >= WWN_SIZE)
+               memcpy(nv->port_name, val, WWN_SIZE);
+
+       val = of_get_property(dp, "node-wwn", &len);
+       if (val && len >= WWN_SIZE)
+               memcpy(nv->node_name, val, WWN_SIZE);
+#endif
+}
+
 int
 qla24xx_nvram_config(scsi_qla_host_t *ha)
 {
+       int   rval;
        struct init_cb_24xx *icb;
        struct nvram_24xx *nv;
        uint32_t *dptr;
@@ -3300,6 +3399,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
        uint32_t chksum;
        uint16_t cnt;
 
+       rval = QLA_SUCCESS;
        icb = (struct init_cb_24xx *)ha->init_cb;
        nv = (struct nvram_24xx *)ha->request_ring;
 
@@ -3332,7 +3432,52 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
                qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: "
                    "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0],
                    le16_to_cpu(nv->nvram_version));
-               return QLA_FUNCTION_FAILED;
+               qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
+                   "invalid -- WWPN) defaults.\n");
+
+               /*
+                * Set default initialization control block.
+                */
+               memset(nv, 0, ha->nvram_size);
+               nv->nvram_version = __constant_cpu_to_le16(ICB_VERSION);
+               nv->version = __constant_cpu_to_le16(ICB_VERSION);
+               nv->frame_payload_size = __constant_cpu_to_le16(2048);
+               nv->execution_throttle = __constant_cpu_to_le16(0xFFFF);
+               nv->exchange_count = __constant_cpu_to_le16(0);
+               nv->hard_address = __constant_cpu_to_le16(124);
+               nv->port_name[0] = 0x21;
+               nv->port_name[1] = 0x00 + PCI_FUNC(ha->pdev->devfn);
+               nv->port_name[2] = 0x00;
+               nv->port_name[3] = 0xe0;
+               nv->port_name[4] = 0x8b;
+               nv->port_name[5] = 0x1c;
+               nv->port_name[6] = 0x55;
+               nv->port_name[7] = 0x86;
+               nv->node_name[0] = 0x20;
+               nv->node_name[1] = 0x00;
+               nv->node_name[2] = 0x00;
+               nv->node_name[3] = 0xe0;
+               nv->node_name[4] = 0x8b;
+               nv->node_name[5] = 0x1c;
+               nv->node_name[6] = 0x55;
+               nv->node_name[7] = 0x86;
+               qla24xx_nvram_wwn_from_ofw(ha, nv);
+               nv->login_retry_count = __constant_cpu_to_le16(8);
+               nv->interrupt_delay_timer = __constant_cpu_to_le16(0);
+               nv->login_timeout = __constant_cpu_to_le16(0);
+               nv->firmware_options_1 =
+                   __constant_cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1);
+               nv->firmware_options_2 = __constant_cpu_to_le32(2 << 4);
+               nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_12);
+               nv->firmware_options_3 = __constant_cpu_to_le32(2 << 13);
+               nv->host_p = __constant_cpu_to_le32(BIT_11|BIT_10);
+               nv->efi_parameters = __constant_cpu_to_le32(0);
+               nv->reset_delay = 5;
+               nv->max_luns_per_target = __constant_cpu_to_le16(128);
+               nv->port_down_retry_count = __constant_cpu_to_le16(30);
+               nv->link_down_timeout = __constant_cpu_to_le16(30);
+
+               rval = 1;
        }
 
        /* Reset Initialization control block */
@@ -3479,7 +3624,11 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
                ha->flags.process_response_queue = 1;
        }
 
-       return QLA_SUCCESS;
+       if (rval) {
+               DEBUG2_3(printk(KERN_WARNING
+                   "scsi(%ld): NVRAM configuration failed!\n", ha->host_no));
+       }
+       return (rval);
 }
 
 static int
index 83376f6..71e32a2 100644 (file)
@@ -1280,14 +1280,14 @@ qla2x00_get_port_name(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t *name,
        } else {
                if (name != NULL) {
                        /* This function returns name in big endian. */
-                       name[0] = LSB(mcp->mb[2]);
-                       name[1] = MSB(mcp->mb[2]);
-                       name[2] = LSB(mcp->mb[3]);
-                       name[3] = MSB(mcp->mb[3]);
-                       name[4] = LSB(mcp->mb[6]);
-                       name[5] = MSB(mcp->mb[6]);
-                       name[6] = LSB(mcp->mb[7]);
-                       name[7] = MSB(mcp->mb[7]);
+                       name[0] = MSB(mcp->mb[2]);
+                       name[1] = LSB(mcp->mb[2]);
+                       name[2] = MSB(mcp->mb[3]);
+                       name[3] = LSB(mcp->mb[3]);
+                       name[4] = MSB(mcp->mb[6]);
+                       name[5] = LSB(mcp->mb[6]);
+                       name[6] = MSB(mcp->mb[7]);
+                       name[7] = LSB(mcp->mb[7]);
                }
 
                DEBUG11(printk("qla2x00_get_port_name(%ld): done.\n",
index 68f5d24..b78919a 100644 (file)
@@ -62,7 +62,7 @@ MODULE_PARM_DESC(ql2xallocfwdump,
                "vary by ISP type.  Default is 1 - allocate memory.");
 
 int ql2xextended_error_logging;
-module_param(ql2xextended_error_logging, int, S_IRUGO|S_IRUSR);
+module_param(ql2xextended_error_logging, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(ql2xextended_error_logging,
                "Option to enable extended error logging, "
                "Default is 0 - no logging. 1 - log errors.");
@@ -157,6 +157,8 @@ static struct scsi_host_template qla24xx_driver_template = {
 
        .slave_alloc            = qla2xxx_slave_alloc,
        .slave_destroy          = qla2xxx_slave_destroy,
+       .scan_finished          = qla2xxx_scan_finished,
+       .scan_start             = qla2xxx_scan_start,
        .change_queue_depth     = qla2x00_change_queue_depth,
        .change_queue_type      = qla2x00_change_queue_type,
        .this_id                = -1,
@@ -1705,6 +1707,7 @@ qla2x00_remove_one(struct pci_dev *pdev)
 
        scsi_host_put(ha->host);
 
+       pci_disable_device(pdev);
        pci_set_drvdata(pdev, NULL);
 }
 
@@ -1747,8 +1750,6 @@ qla2x00_free_device(scsi_qla_host_t *ha)
        if (ha->iobase)
                iounmap(ha->iobase);
        pci_release_regions(ha->pdev);
-
-       pci_disable_device(ha->pdev);
 }
 
 static inline void
index ff1dd41..206bda0 100644 (file)
@@ -466,6 +466,7 @@ qla24xx_read_flash_dword(scsi_qla_host_t *ha, uint32_t addr)
                        udelay(10);
                else
                        rval = QLA_FUNCTION_TIMEOUT;
+               cond_resched();
        }
 
        /* TODO: What happens if we time out? */
@@ -508,6 +509,7 @@ qla24xx_write_flash_dword(scsi_qla_host_t *ha, uint32_t addr, uint32_t data)
                        udelay(10);
                else
                        rval = QLA_FUNCTION_TIMEOUT;
+               cond_resched();
        }
        return rval;
 }
@@ -1255,6 +1257,7 @@ qla2x00_poll_flash(scsi_qla_host_t *ha, uint32_t addr, uint8_t poll_data,
                }
                udelay(10);
                barrier();
+               cond_resched();
        }
        return status;
 }
@@ -1403,6 +1406,7 @@ qla2x00_read_flash_data(scsi_qla_host_t *ha, uint8_t *tmp_buf, uint32_t saddr,
                if (saddr % 100)
                        udelay(10);
                *tmp_buf = data;
+               cond_resched();
        }
 }
 
@@ -1449,7 +1453,6 @@ uint8_t *
 qla2x00_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
     uint32_t offset, uint32_t length)
 {
-       unsigned long flags;
        uint32_t addr, midpoint;
        uint8_t *data;
        struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
@@ -1458,7 +1461,6 @@ qla2x00_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
        qla2x00_suspend_hba(ha);
 
        /* Go with read. */
-       spin_lock_irqsave(&ha->hardware_lock, flags);
        midpoint = ha->optrom_size / 2;
 
        qla2x00_flash_enable(ha);
@@ -1473,7 +1475,6 @@ qla2x00_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
                *data = qla2x00_read_flash_byte(ha, addr);
        }
        qla2x00_flash_disable(ha);
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        /* Resume HBA. */
        qla2x00_resume_hba(ha);
@@ -1487,7 +1488,6 @@ qla2x00_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
 {
 
        int rval;
-       unsigned long flags;
        uint8_t man_id, flash_id, sec_number, data;
        uint16_t wd;
        uint32_t addr, liter, sec_mask, rest_addr;
@@ -1500,7 +1500,6 @@ qla2x00_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
        sec_number = 0;
 
        /* Reset ISP chip. */
-       spin_lock_irqsave(&ha->hardware_lock, flags);
        WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
        pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
 
@@ -1689,10 +1688,10 @@ update_flash:
                                rval = QLA_FUNCTION_FAILED;
                                break;
                        }
+                       cond_resched();
                }
        } while (0);
        qla2x00_flash_disable(ha);
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        /* Resume HBA. */
        qla2x00_resume_hba(ha);
index 61347ae..dc85495 100644 (file)
@@ -7,7 +7,7 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.01.07-k5"
+#define QLA2XXX_VERSION      "8.01.07-k6"
 
 #define QLA_DRIVER_MAJOR_VER   8
 #define QLA_DRIVER_MINOR_VER   1
index 1c89ee3..4c1e313 100644 (file)
@@ -344,7 +344,6 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost)
 void scsi_log_send(struct scsi_cmnd *cmd)
 {
        unsigned int level;
-       struct scsi_device *sdev;
 
        /*
         * If ML QUEUE log level is greater than or equal to:
@@ -361,22 +360,17 @@ void scsi_log_send(struct scsi_cmnd *cmd)
                level = SCSI_LOG_LEVEL(SCSI_LOG_MLQUEUE_SHIFT,
                                       SCSI_LOG_MLQUEUE_BITS);
                if (level > 1) {
-                       sdev = cmd->device;
-                       sdev_printk(KERN_INFO, sdev, "send ");
+                       scmd_printk(KERN_INFO, cmd, "Send: ");
                        if (level > 2)
                                printk("0x%p ", cmd);
-                       /*
-                        * spaces to match disposition and cmd->result
-                        * output in scsi_log_completion.
-                        */
-                       printk("                 ");
+                       printk("\n");
                        scsi_print_command(cmd);
                        if (level > 3) {
                                printk(KERN_INFO "buffer = 0x%p, bufflen = %d,"
                                       " done = 0x%p, queuecommand 0x%p\n",
                                        cmd->request_buffer, cmd->request_bufflen,
                                        cmd->done,
-                                       sdev->host->hostt->queuecommand);
+                                       cmd->device->host->hostt->queuecommand);
 
                        }
                }
@@ -386,7 +380,6 @@ void scsi_log_send(struct scsi_cmnd *cmd)
 void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
 {
        unsigned int level;
-       struct scsi_device *sdev;
 
        /*
         * If ML COMPLETE log level is greater than or equal to:
@@ -405,8 +398,7 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
                                       SCSI_LOG_MLCOMPLETE_BITS);
                if (((level > 0) && (cmd->result || disposition != SUCCESS)) ||
                    (level > 1)) {
-                       sdev = cmd->device;
-                       sdev_printk(KERN_INFO, sdev, "done ");
+                       scmd_printk(KERN_INFO, cmd, "Done: ");
                        if (level > 2)
                                printk("0x%p ", cmd);
                        /*
@@ -415,40 +407,35 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
                         */
                        switch (disposition) {
                        case SUCCESS:
-                               printk("SUCCESS");
+                               printk("SUCCESS\n");
                                break;
                        case NEEDS_RETRY:
-                               printk("RETRY  ");
+                               printk("RETRY\n");
                                break;
                        case ADD_TO_MLQUEUE:
-                               printk("MLQUEUE");
+                               printk("MLQUEUE\n");
                                break;
                        case FAILED:
-                               printk("FAILED ");
+                               printk("FAILED\n");
                                break;
                        case TIMEOUT_ERROR:
                                /* 
                                 * If called via scsi_times_out.
                                 */
-                               printk("TIMEOUT");
+                               printk("TIMEOUT\n");
                                break;
                        default:
-                               printk("UNKNOWN");
+                               printk("UNKNOWN\n");
                        }
-                       printk(" %8x ", cmd->result);
+                       scsi_print_result(cmd);
                        scsi_print_command(cmd);
-                       if (status_byte(cmd->result) & CHECK_CONDITION) {
-                               /*
-                                * XXX The scsi_print_sense formatting/prefix
-                                * doesn't match this function.
-                                */
+                       if (status_byte(cmd->result) & CHECK_CONDITION)
                                scsi_print_sense("", cmd);
-                       }
-                       if (level > 3) {
-                               printk(KERN_INFO "scsi host busy %d failed %d\n",
-                                      sdev->host->host_busy,
-                                      sdev->host->host_failed);
-                       }
+                       if (level > 3)
+                               scmd_printk(KERN_INFO, cmd,
+                                           "scsi host busy %d failed %d\n",
+                                           cmd->device->host->host_busy,
+                                           cmd->device->host->host_failed);
                }
        }
 }
index 918bb60..3963e70 100644 (file)
@@ -184,10 +184,19 @@ int scsi_delete_timer(struct scsi_cmnd *scmd)
  **/
 void scsi_times_out(struct scsi_cmnd *scmd)
 {
+       enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *);
+
        scsi_log_completion(scmd, TIMEOUT_ERROR);
 
        if (scmd->device->host->transportt->eh_timed_out)
-               switch (scmd->device->host->transportt->eh_timed_out(scmd)) {
+               eh_timed_out = scmd->device->host->transportt->eh_timed_out;
+       else if (scmd->device->host->hostt->eh_timed_out)
+               eh_timed_out = scmd->device->host->hostt->eh_timed_out;
+       else
+               eh_timed_out = NULL;
+
+       if (eh_timed_out)
+               switch (eh_timed_out(scmd)) {
                case EH_HANDLED:
                        __scsi_done(scmd);
                        return;
@@ -923,10 +932,12 @@ static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
        static unsigned char stu_command[6] = {START_STOP, 0, 0, 0, 1, 0};
 
        if (scmd->device->allow_restart) {
-               int rtn;
+               int i, rtn = NEEDS_RETRY;
+
+               for (i = 0; rtn == NEEDS_RETRY && i < 2; i++)
+                       rtn = scsi_send_eh_cmnd(scmd, stu_command, 6,
+                                               START_UNIT_TIMEOUT, 0);
 
-               rtn = scsi_send_eh_cmnd(scmd, stu_command, 6,
-                                       START_UNIT_TIMEOUT, 0);
                if (rtn == SUCCESS)
                        return 0;
        }
index 05d79af..61fbcdc 100644 (file)
@@ -848,8 +848,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                memcpy(req->sense, cmd->sense_buffer,  len);
                                req->sense_len = len;
                        }
-               } else
-                       req->data_len = cmd->resid;
+               }
+               req->data_len = cmd->resid;
        }
 
        /*
@@ -968,9 +968,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
        }
        if (result) {
                if (!(req->cmd_flags & REQ_QUIET)) {
-                       scmd_printk(KERN_INFO, cmd,
-                                   "SCSI error: return code = 0x%08x\n",
-                                   result);
+                       scsi_print_result(cmd);
                        if (driver_byte(result) & DRIVER_SENSE)
                                scsi_print_sense("", cmd);
                }
index 0949145..a67f315 100644 (file)
@@ -181,10 +181,8 @@ int scsi_complete_async_scans(void)
        return 0;
 }
 
-#ifdef MODULE
 /* Only exported for the benefit of scsi_wait_scan */
 EXPORT_SYMBOL_GPL(scsi_complete_async_scans);
-#endif
 
 /**
  * scsi_unlock_floptical - unlock device via a special MODE SENSE command
index 939de0d..67a38a1 100644 (file)
@@ -276,8 +276,22 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
        return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
 }
 
+static int scsi_bus_uevent(struct device *dev, char **envp, int num_envp,
+                          char *buffer, int buffer_size)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
+       int i = 0;
+       int length = 0;
+
+       add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+                      "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type);
+       envp[i] = NULL;
+       return 0;
+}
+
 static int scsi_bus_suspend(struct device * dev, pm_message_t state)
 {
+       struct device_driver *drv = dev->driver;
        struct scsi_device *sdev = to_scsi_device(dev);
        struct scsi_host_template *sht = sdev->host->hostt;
        int err;
@@ -286,28 +300,51 @@ static int scsi_bus_suspend(struct device * dev, pm_message_t state)
        if (err)
                return err;
 
-       if (sht->suspend)
+       /* call HLD suspend first */
+       if (drv && drv->suspend) {
+               err = drv->suspend(dev, state);
+               if (err)
+                       return err;
+       }
+
+       /* then, call host suspend */
+       if (sht->suspend) {
                err = sht->suspend(sdev, state);
+               if (err) {
+                       if (drv && drv->resume)
+                               drv->resume(dev);
+                       return err;
+               }
+       }
 
-       return err;
+       return 0;
 }
 
 static int scsi_bus_resume(struct device * dev)
 {
+       struct device_driver *drv = dev->driver;
        struct scsi_device *sdev = to_scsi_device(dev);
        struct scsi_host_template *sht = sdev->host->hostt;
-       int err = 0;
+       int err = 0, err2 = 0;
 
+       /* call host resume first */
        if (sht->resume)
                err = sht->resume(sdev);
 
+       /* then, call HLD resume */
+       if (drv && drv->resume)
+               err2 = drv->resume(dev);
+
        scsi_device_resume(sdev);
-       return err;
+
+       /* favor LLD failure */
+       return err ? err : err2;;
 }
 
 struct bus_type scsi_bus_type = {
         .name          = "scsi",
         .match         = scsi_bus_match,
+       .uevent         = scsi_bus_uevent,
        .suspend        = scsi_bus_suspend,
        .resume         = scsi_bus_resume,
 };
@@ -547,6 +584,14 @@ show_sdev_iostat(iorequest_cnt);
 show_sdev_iostat(iodone_cnt);
 show_sdev_iostat(ioerr_cnt);
 
+static ssize_t
+sdev_show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct scsi_device *sdev;
+       sdev = to_scsi_device(dev);
+       return snprintf (buf, 20, SCSI_DEVICE_MODALIAS_FMT "\n", sdev->type);
+}
+static DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL);
 
 /* Default template for device attributes.  May NOT be modified */
 static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
@@ -566,6 +611,7 @@ static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
        &dev_attr_iorequest_cnt,
        &dev_attr_iodone_cnt,
        &dev_attr_ioerr_cnt,
+       &dev_attr_modalias,
        NULL
 };
 
index 0e08817..ca22ddf 100644 (file)
@@ -179,10 +179,12 @@ static int event_recv_msg(struct tgt_event *ev)
        switch (ev->hdr.type) {
        case TGT_UEVENT_CMD_RSP:
                err = scsi_tgt_kspace_exec(ev->p.cmd_rsp.host_no,
-                                          ev->p.cmd_rsp.tag,
                                           ev->p.cmd_rsp.result,
-                                          ev->p.cmd_rsp.len,
+                                          ev->p.cmd_rsp.tag,
                                           ev->p.cmd_rsp.uaddr,
+                                          ev->p.cmd_rsp.len,
+                                          ev->p.cmd_rsp.sense_uaddr,
+                                          ev->p.cmd_rsp.sense_len,
                                           ev->p.cmd_rsp.rw);
                break;
        case TGT_UEVENT_TSK_MGMT_RSP:
index d402aff..2570f48 100644 (file)
@@ -28,7 +28,6 @@
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tgt.h>
-#include <../drivers/md/dm-bio-list.h>
 
 #include "scsi_tgt_priv.h"
 
@@ -42,16 +41,12 @@ static struct kmem_cache *scsi_tgt_cmd_cache;
 struct scsi_tgt_cmd {
        /* TODO replace work with James b's code */
        struct work_struct work;
-       /* TODO replace the lists with a large bio */
-       struct bio_list xfer_done_list;
-       struct bio_list xfer_list;
+       /* TODO fix limits of some drivers */
+       struct bio *bio;
 
        struct list_head hash_list;
        struct request *rq;
        u64 tag;
-
-       void *buffer;
-       unsigned bufflen;
 };
 
 #define TGT_HASH_ORDER 4
@@ -93,7 +88,12 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost,
        if (!tcmd)
                goto put_dev;
 
-       rq = blk_get_request(shost->uspace_req_q, write, gfp_mask);
+       /*
+        * The blk helpers are used to the READ/WRITE requests
+        * transfering data from a initiator point of view. Since
+        * we are in target mode we want the opposite.
+        */
+       rq = blk_get_request(shost->uspace_req_q, !write, gfp_mask);
        if (!rq)
                goto free_tcmd;
 
@@ -111,8 +111,6 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost,
        rq->cmd_flags |= REQ_TYPE_BLOCK_PC;
        rq->end_io_data = tcmd;
 
-       bio_list_init(&tcmd->xfer_list);
-       bio_list_init(&tcmd->xfer_done_list);
        tcmd->rq = rq;
 
        return cmd;
@@ -157,22 +155,6 @@ void scsi_host_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
 }
 EXPORT_SYMBOL_GPL(scsi_host_put_command);
 
-static void scsi_unmap_user_pages(struct scsi_tgt_cmd *tcmd)
-{
-       struct bio *bio;
-
-       /* must call bio_endio in case bio was bounced */
-       while ((bio = bio_list_pop(&tcmd->xfer_done_list))) {
-               bio_endio(bio, bio->bi_size, 0);
-               bio_unmap_user(bio);
-       }
-
-       while ((bio = bio_list_pop(&tcmd->xfer_list))) {
-               bio_endio(bio, bio->bi_size, 0);
-               bio_unmap_user(bio);
-       }
-}
-
 static void cmd_hashlist_del(struct scsi_cmnd *cmd)
 {
        struct request_queue *q = cmd->request->q;
@@ -185,6 +167,11 @@ static void cmd_hashlist_del(struct scsi_cmnd *cmd)
        spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags);
 }
 
+static void scsi_unmap_user_pages(struct scsi_tgt_cmd *tcmd)
+{
+       blk_rq_unmap_user(tcmd->bio);
+}
+
 static void scsi_tgt_cmd_destroy(struct work_struct *work)
 {
        struct scsi_tgt_cmd *tcmd =
@@ -193,16 +180,6 @@ static void scsi_tgt_cmd_destroy(struct work_struct *work)
 
        dprintk("cmd %p %d %lu\n", cmd, cmd->sc_data_direction,
                rq_data_dir(cmd->request));
-       /*
-        * We fix rq->cmd_flags here since when we told bio_map_user
-        * to write vm for WRITE commands, blk_rq_bio_prep set
-        * rq_data_dir the flags to READ.
-        */
-       if (cmd->sc_data_direction == DMA_TO_DEVICE)
-               cmd->request->cmd_flags |= REQ_RW;
-       else
-               cmd->request->cmd_flags &= ~REQ_RW;
-
        scsi_unmap_user_pages(tcmd);
        scsi_host_put_command(scsi_tgt_cmd_to_host(cmd), cmd);
 }
@@ -215,6 +192,7 @@ static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd,
        struct list_head *head;
 
        tcmd->tag = tag;
+       tcmd->bio = NULL;
        INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy);
        spin_lock_irqsave(&qdata->cmd_hash_lock, flags);
        head = &qdata->cmd_hash[cmd_hashfn(tag)];
@@ -349,10 +327,14 @@ static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd)
        dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request));
 
        scsi_tgt_uspace_send_status(cmd, tcmd->tag);
+
+       if (cmd->request_buffer)
+               scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len);
+
        queue_work(scsi_tgtd, &tcmd->work);
 }
 
-static int __scsi_tgt_transfer_response(struct scsi_cmnd *cmd)
+static int scsi_tgt_transfer_response(struct scsi_cmnd *cmd)
 {
        struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd);
        int err;
@@ -365,30 +347,12 @@ static int __scsi_tgt_transfer_response(struct scsi_cmnd *cmd)
        case SCSI_MLQUEUE_DEVICE_BUSY:
                return -EAGAIN;
        }
-
        return 0;
 }
 
-static void scsi_tgt_transfer_response(struct scsi_cmnd *cmd)
-{
-       struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data;
-       int err;
-
-       err = __scsi_tgt_transfer_response(cmd);
-       if (!err)
-               return;
-
-       cmd->result = DID_BUS_BUSY << 16;
-       err = scsi_tgt_uspace_send_status(cmd, tcmd->tag);
-       if (err <= 0)
-               /* the eh will have to pick this up */
-               printk(KERN_ERR "Could not send cmd %p status\n", cmd);
-}
-
 static int scsi_tgt_init_cmd(struct scsi_cmnd *cmd, gfp_t gfp_mask)
 {
        struct request *rq = cmd->request;
-       struct scsi_tgt_cmd *tcmd = rq->end_io_data;
        int count;
 
        cmd->use_sg = rq->nr_phys_segments;
@@ -398,143 +362,54 @@ static int scsi_tgt_init_cmd(struct scsi_cmnd *cmd, gfp_t gfp_mask)
 
        cmd->request_bufflen = rq->data_len;
 
-       dprintk("cmd %p addr %p cnt %d %lu\n", cmd, tcmd->buffer, cmd->use_sg,
-               rq_data_dir(rq));
+       dprintk("cmd %p cnt %d %lu\n", cmd, cmd->use_sg, rq_data_dir(rq));
        count = blk_rq_map_sg(rq->q, rq, cmd->request_buffer);
        if (likely(count <= cmd->use_sg)) {
                cmd->use_sg = count;
                return 0;
        }
 
-       eprintk("cmd %p addr %p cnt %d\n", cmd, tcmd->buffer, cmd->use_sg);
+       eprintk("cmd %p cnt %d\n", cmd, cmd->use_sg);
        scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len);
        return -EINVAL;
 }
 
 /* TODO: test this crap and replace bio_map_user with new interface maybe */
 static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd,
-                              int rw)
+                              unsigned long uaddr, unsigned int len, int rw)
 {
        struct request_queue *q = cmd->request->q;
        struct request *rq = cmd->request;
-       void *uaddr = tcmd->buffer;
-       unsigned int len = tcmd->bufflen;
-       struct bio *bio;
        int err;
 
-       while (len > 0) {
-               dprintk("%lx %u\n", (unsigned long) uaddr, len);
-               bio = bio_map_user(q, NULL, (unsigned long) uaddr, len, rw);
-               if (IS_ERR(bio)) {
-                       err = PTR_ERR(bio);
-                       dprintk("fail to map %lx %u %d %x\n",
-                               (unsigned long) uaddr, len, err, cmd->cmnd[0]);
-                       goto unmap_bios;
-               }
-
-               uaddr += bio->bi_size;
-               len -= bio->bi_size;
-
+       dprintk("%lx %u\n", uaddr, len);
+       err = blk_rq_map_user(q, rq, (void *)uaddr, len);
+       if (err) {
                /*
-                * The first bio is added and merged. We could probably
-                * try to add others using scsi_merge_bio() but for now
-                * we keep it simple. The first bio should be pretty large
-                * (either hitting the 1 MB bio pages limit or a queue limit)
-                * already but for really large IO we may want to try and
-                * merge these.
+                * TODO: need to fixup sg_tablesize, max_segment_size,
+                * max_sectors, etc for modern HW and software drivers
+                * where this value is bogus.
+                *
+                * TODO2: we can alloc a reserve buffer of max size
+                * we can handle and do the slow copy path for really large
+                * IO.
                 */
-               if (!rq->bio) {
-                       blk_rq_bio_prep(q, rq, bio);
-                       rq->data_len = bio->bi_size;
-               } else
-                       /* put list of bios to transfer in next go around */
-                       bio_list_add(&tcmd->xfer_list, bio);
+               eprintk("Could not handle request of size %u.\n", len);
+               return err;
        }
 
-       cmd->offset = 0;
+       tcmd->bio = rq->bio;
        err = scsi_tgt_init_cmd(cmd, GFP_KERNEL);
        if (err)
-               goto unmap_bios;
+               goto unmap_rq;
 
        return 0;
 
-unmap_bios:
-       if (rq->bio) {
-               bio_unmap_user(rq->bio);
-               while ((bio = bio_list_pop(&tcmd->xfer_list)))
-                       bio_unmap_user(bio);
-       }
-
+unmap_rq:
+       scsi_unmap_user_pages(tcmd);
        return err;
 }
 
-static int scsi_tgt_transfer_data(struct scsi_cmnd *);
-
-static void scsi_tgt_data_transfer_done(struct scsi_cmnd *cmd)
-{
-       struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data;
-       struct bio *bio;
-       int err;
-
-       /* should we free resources here on error ? */
-       if (cmd->result) {
-send_uspace_err:
-               err = scsi_tgt_uspace_send_status(cmd, tcmd->tag);
-               if (err <= 0)
-                       /* the tgt uspace eh will have to pick this up */
-                       printk(KERN_ERR "Could not send cmd %p status\n", cmd);
-               return;
-       }
-
-       dprintk("cmd %p request_bufflen %u bufflen %u\n",
-               cmd, cmd->request_bufflen, tcmd->bufflen);
-
-       scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len);
-       bio_list_add(&tcmd->xfer_done_list, cmd->request->bio);
-
-       tcmd->buffer += cmd->request_bufflen;
-       cmd->offset += cmd->request_bufflen;
-
-       if (!tcmd->xfer_list.head) {
-               scsi_tgt_transfer_response(cmd);
-               return;
-       }
-
-       dprintk("cmd2 %p request_bufflen %u bufflen %u\n",
-               cmd, cmd->request_bufflen, tcmd->bufflen);
-
-       bio = bio_list_pop(&tcmd->xfer_list);
-       BUG_ON(!bio);
-
-       blk_rq_bio_prep(cmd->request->q, cmd->request, bio);
-       cmd->request->data_len = bio->bi_size;
-       err = scsi_tgt_init_cmd(cmd, GFP_ATOMIC);
-       if (err) {
-               cmd->result = DID_ERROR << 16;
-               goto send_uspace_err;
-       }
-
-       if (scsi_tgt_transfer_data(cmd)) {
-               cmd->result = DID_NO_CONNECT << 16;
-               goto send_uspace_err;
-       }
-}
-
-static int scsi_tgt_transfer_data(struct scsi_cmnd *cmd)
-{
-       int err;
-       struct Scsi_Host *host = scsi_tgt_cmd_to_host(cmd);
-
-       err = host->hostt->transfer_data(cmd, scsi_tgt_data_transfer_done);
-       switch (err) {
-               case SCSI_MLQUEUE_HOST_BUSY:
-               case SCSI_MLQUEUE_DEVICE_BUSY:
-                       return -EAGAIN;
-       default:
-               return 0;
-       }
-}
-
 static int scsi_tgt_copy_sense(struct scsi_cmnd *cmd, unsigned long uaddr,
                                unsigned len)
 {
@@ -584,8 +459,9 @@ static struct request *tgt_cmd_hash_lookup(struct request_queue *q, u64 tag)
        return rq;
 }
 
-int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len,
-                        unsigned long uaddr, u8 rw)
+int scsi_tgt_kspace_exec(int host_no, int result, u64 tag,
+                        unsigned long uaddr, u32 len, unsigned long sense_uaddr,
+                        u32 sense_len, u8 rw)
 {
        struct Scsi_Host *shost;
        struct scsi_cmnd *cmd;
@@ -617,8 +493,9 @@ int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len,
        }
        cmd = rq->special;
 
-       dprintk("cmd %p result %d len %d bufflen %u %lu %x\n", cmd,
-               result, len, cmd->request_bufflen, rq_data_dir(rq), cmd->cmnd[0]);
+       dprintk("cmd %p scb %x result %d len %d bufflen %u %lu %x\n",
+               cmd, cmd->cmnd[0], result, len, cmd->request_bufflen,
+               rq_data_dir(rq), cmd->cmnd[0]);
 
        if (result == TASK_ABORTED) {
                scsi_tgt_abort_cmd(shost, cmd);
@@ -629,36 +506,36 @@ int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len,
         * in the request_* values
         */
        tcmd = cmd->request->end_io_data;
-       tcmd->buffer = (void *)uaddr;
-       tcmd->bufflen = len;
        cmd->result = result;
 
-       if (!tcmd->bufflen || cmd->request_buffer) {
-               err = __scsi_tgt_transfer_response(cmd);
-               goto done;
-       }
+       if (cmd->result == SAM_STAT_CHECK_CONDITION)
+               scsi_tgt_copy_sense(cmd, sense_uaddr, sense_len);
 
-       /*
-        * TODO: Do we need to handle case where request does not
-        * align with LLD.
-        */
-       err = scsi_map_user_pages(rq->end_io_data, cmd, rw);
-       if (err) {
-               eprintk("%p %d\n", cmd, err);
-               err = -EAGAIN;
-               goto done;
-       }
+       if (len) {
+               err = scsi_map_user_pages(rq->end_io_data, cmd, uaddr, len, rw);
+               if (err) {
+                       /*
+                        * user-space daemon bugs or OOM
+                        * TODO: we can do better for OOM.
+                        */
+                       struct scsi_tgt_queuedata *qdata;
+                       struct list_head *head;
+                       unsigned long flags;
 
-       /* userspace failure */
-       if (cmd->result) {
-               if (status_byte(cmd->result) == CHECK_CONDITION)
-                       scsi_tgt_copy_sense(cmd, uaddr, len);
-               err = __scsi_tgt_transfer_response(cmd);
-               goto done;
-       }
-       /* ask the target LLD to transfer the data to the buffer */
-       err = scsi_tgt_transfer_data(cmd);
+                       eprintk("cmd %p ret %d uaddr %lx len %d rw %d\n",
+                               cmd, err, uaddr, len, rw);
+
+                       qdata = shost->uspace_req_q->queuedata;
+                       head = &qdata->cmd_hash[cmd_hashfn(tcmd->tag)];
+
+                       spin_lock_irqsave(&qdata->cmd_hash_lock, flags);
+                       list_add(&tcmd->hash_list, head);
+                       spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags);
 
+                       goto done;
+               }
+       }
+       err = scsi_tgt_transfer_response(cmd);
 done:
        scsi_host_put(shost);
        return err;
index 84488c5..e9e6db1 100644 (file)
@@ -18,8 +18,9 @@ extern int scsi_tgt_if_init(void);
 extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun,
                                    u64 tag);
 extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag);
-extern int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len,
-                               unsigned long uaddr, u8 rw);
+extern int scsi_tgt_kspace_exec(int host_no, int result, u64 tag,
+                               unsigned long uaddr, u32 len, unsigned long sense_uaddr,
+                               u32 sense_len, u8 rw);
 extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag,
                                         struct scsi_lun *scsilun, void *data);
 extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result);
index 58afdb4..14c4f06 100644 (file)
@@ -200,6 +200,8 @@ static const struct {
        { FC_PORTSPEED_2GBIT,           "2 Gbit" },
        { FC_PORTSPEED_4GBIT,           "4 Gbit" },
        { FC_PORTSPEED_10GBIT,          "10 Gbit" },
+       { FC_PORTSPEED_8GBIT,           "8 Gbit" },
+       { FC_PORTSPEED_16GBIT,          "16 Gbit" },
        { FC_PORTSPEED_NOT_NEGOTIATED,  "Not Negotiated" },
 };
 fc_bitfield_name_search(port_speed, fc_port_speed_names)
index aabaa05..caf1836 100644 (file)
@@ -49,7 +49,7 @@ struct iscsi_internal {
        struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
 };
 
-static int iscsi_session_nr;   /* sysfs session id for next new session */
+static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
 
 /*
  * list of registered transports and lock that must
@@ -300,7 +300,7 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
        int err;
 
        ihost = shost->shost_data;
-       session->sid = iscsi_session_nr++;
+       session->sid = atomic_add_return(1, &iscsi_session_nr);
        session->target_id = target_id;
 
        snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",
@@ -1419,6 +1419,8 @@ static __init int iscsi_transport_init(void)
        printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
                ISCSI_TRANSPORT_VERSION);
 
+       atomic_set(&iscsi_session_nr, 0);
+
        err = class_register(&iscsi_transport_class);
        if (err)
                return err;
index 5a8f55f..00e4666 100644 (file)
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
 #include <scsi/scsicam.h>
+#include <scsi/sd.h>
 
 #include "scsi_logging.h"
 
-/*
- * More than enough for everybody ;)  The huge number of majors
- * is a leftover from 16bit dev_t days, we don't really need that
- * much numberspace.
- */
-#define SD_MAJORS      16
-
 MODULE_AUTHOR("Eric Youngdale");
 MODULE_DESCRIPTION("SCSI disk (sd) driver");
 MODULE_LICENSE("GPL");
@@ -88,45 +82,9 @@ MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK12_MAJOR);
 MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK13_MAJOR);
 MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK14_MAJOR);
 MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK15_MAJOR);
-
-/*
- * This is limited by the naming scheme enforced in sd_probe,
- * add another character to it if you really need more disks.
- */
-#define SD_MAX_DISKS   (((26 * 26) + 26 + 1) * 26)
-
-/*
- * Time out in seconds for disks and Magneto-opticals (which are slower).
- */
-#define SD_TIMEOUT             (30 * HZ)
-#define SD_MOD_TIMEOUT         (75 * HZ)
-
-/*
- * Number of allowed retries
- */
-#define SD_MAX_RETRIES         5
-#define SD_PASSTHROUGH_RETRIES 1
-
-/*
- * Size of the initial data buffer for mode and read capacity data
- */
-#define SD_BUF_SIZE            512
-
-struct scsi_disk {
-       struct scsi_driver *driver;     /* always &sd_template */
-       struct scsi_device *device;
-       struct class_device cdev;
-       struct gendisk  *disk;
-       unsigned int    openers;        /* protected by BKL for now, yuck */
-       sector_t        capacity;       /* size in 512-byte sectors */
-       u32             index;
-       u8              media_present;
-       u8              write_prot;
-       unsigned        WCE : 1;        /* state of disk WCE bit */
-       unsigned        RCD : 1;        /* state of disk RCD bit, unused */
-       unsigned        DPOFUA : 1;     /* state of disk DPOFUA bit */
-};
-#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,cdev)
+MODULE_ALIAS_SCSI_DEVICE(TYPE_DISK);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
 
 static DEFINE_IDR(sd_index_idr);
 static DEFINE_SPINLOCK(sd_index_lock);
@@ -136,20 +94,6 @@ static DEFINE_SPINLOCK(sd_index_lock);
  * object after last put) */
 static DEFINE_MUTEX(sd_ref_mutex);
 
-static int sd_revalidate_disk(struct gendisk *disk);
-static void sd_rw_intr(struct scsi_cmnd * SCpnt);
-
-static int sd_probe(struct device *);
-static int sd_remove(struct device *);
-static void sd_shutdown(struct device *dev);
-static void sd_rescan(struct device *);
-static int sd_init_command(struct scsi_cmnd *);
-static int sd_issue_flush(struct device *, sector_t *);
-static void sd_prepare_flush(request_queue_t *, struct request *);
-static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
-                            unsigned char *buffer);
-static void scsi_disk_release(struct class_device *cdev);
-
 static const char *sd_cache_types[] = {
        "write through", "none", "write back",
        "write back, no read (daft)"
@@ -199,13 +143,27 @@ static ssize_t sd_store_cache_type(struct class_device *cdev, const char *buf,
        if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT,
                             SD_MAX_RETRIES, &data, &sshdr)) {
                if (scsi_sense_valid(&sshdr))
-                       scsi_print_sense_hdr(sdkp->disk->disk_name, &sshdr);
+                       sd_print_sense_hdr(sdkp, &sshdr);
                return -EINVAL;
        }
        sd_revalidate_disk(sdkp->disk);
        return count;
 }
 
+static ssize_t sd_store_manage_start_stop(struct class_device *cdev,
+                                         const char *buf, size_t count)
+{
+       struct scsi_disk *sdkp = to_scsi_disk(cdev);
+       struct scsi_device *sdp = sdkp->device;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EACCES;
+
+       sdp->manage_start_stop = simple_strtoul(buf, NULL, 10);
+
+       return count;
+}
+
 static ssize_t sd_store_allow_restart(struct class_device *cdev, const char *buf,
                                      size_t count)
 {
@@ -238,6 +196,14 @@ static ssize_t sd_show_fua(struct class_device *cdev, char *buf)
        return snprintf(buf, 20, "%u\n", sdkp->DPOFUA);
 }
 
+static ssize_t sd_show_manage_start_stop(struct class_device *cdev, char *buf)
+{
+       struct scsi_disk *sdkp = to_scsi_disk(cdev);
+       struct scsi_device *sdp = sdkp->device;
+
+       return snprintf(buf, 20, "%u\n", sdp->manage_start_stop);
+}
+
 static ssize_t sd_show_allow_restart(struct class_device *cdev, char *buf)
 {
        struct scsi_disk *sdkp = to_scsi_disk(cdev);
@@ -251,6 +217,8 @@ static struct class_device_attribute sd_disk_attrs[] = {
        __ATTR(FUA, S_IRUGO, sd_show_fua, NULL),
        __ATTR(allow_restart, S_IRUGO|S_IWUSR, sd_show_allow_restart,
               sd_store_allow_restart),
+       __ATTR(manage_start_stop, S_IRUGO|S_IWUSR, sd_show_manage_start_stop,
+              sd_store_manage_start_stop),
        __ATTR_NULL,
 };
 
@@ -267,6 +235,8 @@ static struct scsi_driver sd_template = {
                .name           = "sd",
                .probe          = sd_probe,
                .remove         = sd_remove,
+               .suspend        = sd_suspend,
+               .resume         = sd_resume,
                .shutdown       = sd_shutdown,
        },
        .rescan                 = sd_rescan,
@@ -371,15 +341,19 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
        unsigned int this_count = SCpnt->request_bufflen >> 9;
        unsigned int timeout = sdp->timeout;
 
-       SCSI_LOG_HLQUEUE(1, printk("sd_init_command: disk=%s, block=%llu, "
-                           "count=%d\n", disk->disk_name,
-                        (unsigned long long)block, this_count));
+       SCSI_LOG_HLQUEUE(1, scmd_printk(KERN_INFO, SCpnt,
+                                       "sd_init_command: block=%llu, "
+                                       "count=%d\n",
+                                       (unsigned long long)block,
+                                       this_count));
 
        if (!sdp || !scsi_device_online(sdp) ||
            block + rq->nr_sectors > get_capacity(disk)) {
-               SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", 
-                                rq->nr_sectors));
-               SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt));
+               SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
+                                               "Finishing %ld sectors\n",
+                                               rq->nr_sectors));
+               SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
+                                               "Retry with 0x%p\n", SCpnt));
                return 0;
        }
 
@@ -391,8 +365,8 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
                /* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */
                return 0;
        }
-       SCSI_LOG_HLQUEUE(2, printk("%s : block=%llu\n",
-                                  disk->disk_name, (unsigned long long)block));
+       SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n",
+                                       (unsigned long long)block));
 
        /*
         * If we have a 1K hardware sectorsize, prevent access to single
@@ -407,7 +381,8 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
         */
        if (sdp->sector_size == 1024) {
                if ((block & 1) || (rq->nr_sectors & 1)) {
-                       printk(KERN_ERR "sd: Bad block number requested");
+                       scmd_printk(KERN_ERR, SCpnt,
+                                   "Bad block number requested\n");
                        return 0;
                } else {
                        block = block >> 1;
@@ -416,7 +391,8 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
        }
        if (sdp->sector_size == 2048) {
                if ((block & 3) || (rq->nr_sectors & 3)) {
-                       printk(KERN_ERR "sd: Bad block number requested");
+                       scmd_printk(KERN_ERR, SCpnt,
+                                   "Bad block number requested\n");
                        return 0;
                } else {
                        block = block >> 2;
@@ -425,7 +401,8 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
        }
        if (sdp->sector_size == 4096) {
                if ((block & 7) || (rq->nr_sectors & 7)) {
-                       printk(KERN_ERR "sd: Bad block number requested");
+                       scmd_printk(KERN_ERR, SCpnt,
+                                   "Bad block number requested\n");
                        return 0;
                } else {
                        block = block >> 3;
@@ -442,13 +419,15 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
                SCpnt->cmnd[0] = READ_6;
                SCpnt->sc_data_direction = DMA_FROM_DEVICE;
        } else {
-               printk(KERN_ERR "sd: Unknown command %x\n", rq->cmd_flags);
+               scmd_printk(KERN_ERR, SCpnt, "Unknown command %x\n", rq->cmd_flags);
                return 0;
        }
 
-       SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n", 
-               disk->disk_name, (rq_data_dir(rq) == WRITE) ? 
-               "writing" : "reading", this_count, rq->nr_sectors));
+       SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
+                                       "%s %d/%ld 512 byte blocks.\n",
+                                       (rq_data_dir(rq) == WRITE) ?
+                                       "writing" : "reading", this_count,
+                                       rq->nr_sectors));
 
        SCpnt->cmnd[1] = 0;
        
@@ -490,7 +469,8 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
                         * during operation and thus turned off
                         * use_10_for_rw.
                         */
-                       printk(KERN_ERR "sd: FUA write on READ/WRITE(6) drive\n");
+                       scmd_printk(KERN_ERR, SCpnt,
+                                   "FUA write on READ/WRITE(6) drive\n");
                        return 0;
                }
 
@@ -549,7 +529,7 @@ static int sd_open(struct inode *inode, struct file *filp)
                return -ENXIO;
 
 
-       SCSI_LOG_HLQUEUE(3, printk("sd_open: disk=%s\n", disk->disk_name));
+       SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_open\n"));
 
        sdev = sdkp->device;
 
@@ -619,7 +599,7 @@ static int sd_release(struct inode *inode, struct file *filp)
        struct scsi_disk *sdkp = scsi_disk(disk);
        struct scsi_device *sdev = sdkp->device;
 
-       SCSI_LOG_HLQUEUE(3, printk("sd_release: disk=%s\n", disk->disk_name));
+       SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_release\n"));
 
        if (!--sdkp->openers && sdev->removable) {
                if (scsi_block_when_processing_errors(sdev))
@@ -732,8 +712,7 @@ static int sd_media_changed(struct gendisk *disk)
        struct scsi_device *sdp = sdkp->device;
        int retval;
 
-       SCSI_LOG_HLQUEUE(3, printk("sd_media_changed: disk=%s\n",
-                                               disk->disk_name));
+       SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_media_changed\n"));
 
        if (!sdp->removable)
                return 0;
@@ -786,9 +765,10 @@ not_present:
        return 1;
 }
 
-static int sd_sync_cache(struct scsi_device *sdp)
+static int sd_sync_cache(struct scsi_disk *sdkp)
 {
        int retries, res;
+       struct scsi_device *sdp = sdkp->device;
        struct scsi_sense_hdr sshdr;
 
        if (!scsi_device_online(sdp))
@@ -809,28 +789,27 @@ static int sd_sync_cache(struct scsi_device *sdp)
                        break;
        }
 
-       if (res) {              printk(KERN_WARNING "FAILED\n  status = %x, message = %02x, "
-                                   "host = %d, driver = %02x\n  ",
-                                   status_byte(res), msg_byte(res),
-                                   host_byte(res), driver_byte(res));
-                       if (driver_byte(res) & DRIVER_SENSE)
-                               scsi_print_sense_hdr("sd", &sshdr);
+       if (res) {
+               sd_print_result(sdkp, res);
+               if (driver_byte(res) & DRIVER_SENSE)
+                       sd_print_sense_hdr(sdkp, &sshdr);
        }
 
-       return res;
+       if (res)
+               return -EIO;
+       return 0;
 }
 
 static int sd_issue_flush(struct device *dev, sector_t *error_sector)
 {
        int ret = 0;
-       struct scsi_device *sdp = to_scsi_device(dev);
        struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
 
        if (!sdkp)
                return -ENODEV;
 
        if (sdkp->WCE)
-               ret = sd_sync_cache(sdp);
+               ret = sd_sync_cache(sdkp);
        scsi_disk_put(sdkp);
        return ret;
 }
@@ -928,12 +907,14 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt)
                        sense_deferred = scsi_sense_is_deferred(&sshdr);
        }
 #ifdef CONFIG_SCSI_LOGGING
-       SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: %s: res=0x%x\n", 
-                               SCpnt->request->rq_disk->disk_name, result));
+       SCSI_LOG_HLCOMPLETE(1, scsi_print_result(SCpnt));
        if (sense_valid) {
-               SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: sb[respc,sk,asc,"
-                               "ascq]=%x,%x,%x,%x\n", sshdr.response_code,
-                               sshdr.sense_key, sshdr.asc, sshdr.ascq));
+               SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, SCpnt,
+                                                  "sd_rw_intr: sb[respc,sk,asc,"
+                                                  "ascq]=%x,%x,%x,%x\n",
+                                                  sshdr.response_code,
+                                                  sshdr.sense_key, sshdr.asc,
+                                                  sshdr.ascq));
        }
 #endif
        if (driver_byte(result) != DRIVER_SENSE &&
@@ -1025,7 +1006,7 @@ static int media_not_present(struct scsi_disk *sdkp,
  * spinup disk - called only in sd_revalidate_disk()
  */
 static void
-sd_spinup_disk(struct scsi_disk *sdkp, char *diskname)
+sd_spinup_disk(struct scsi_disk *sdkp)
 {
        unsigned char cmd[10];
        unsigned long spintime_expire = 0;
@@ -1069,9 +1050,10 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname)
                if ((driver_byte(the_result) & DRIVER_SENSE) == 0) {
                        /* no sense, TUR either succeeded or failed
                         * with a status error */
-                       if(!spintime && !scsi_status_is_good(the_result))
-                               printk(KERN_NOTICE "%s: Unit Not Ready, "
-                                      "error = 0x%x\n", diskname, the_result);
+                       if(!spintime && !scsi_status_is_good(the_result)) {
+                               sd_printk(KERN_NOTICE, sdkp, "Unit Not Ready\n");
+                               sd_print_result(sdkp, the_result);
+                       }
                        break;
                }
                                        
@@ -1096,8 +1078,7 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname)
                 */
                } else if (sense_valid && sshdr.sense_key == NOT_READY) {
                        if (!spintime) {
-                               printk(KERN_NOTICE "%s: Spinning up disk...",
-                                      diskname);
+                               sd_printk(KERN_NOTICE, sdkp, "Spinning up disk...");
                                cmd[0] = START_STOP;
                                cmd[1] = 1;     /* Return immediately */
                                memset((void *) &cmd[2], 0, 8);
@@ -1130,9 +1111,8 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname)
                        /* we don't understand the sense code, so it's
                         * probably pointless to loop */
                        if(!spintime) {
-                               printk(KERN_NOTICE "%s: Unit Not Ready, "
-                                       "sense:\n", diskname);
-                               scsi_print_sense_hdr("", &sshdr);
+                               sd_printk(KERN_NOTICE, sdkp, "Unit Not Ready\n");
+                               sd_print_sense_hdr(sdkp, &sshdr);
                        }
                        break;
                }
@@ -1151,8 +1131,7 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname)
  * read disk capacity
  */
 static void
-sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
-                unsigned char *buffer)
+sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer)
 {
        unsigned char cmd[16];
        int the_result, retries;
@@ -1191,18 +1170,12 @@ repeat:
        } while (the_result && retries);
 
        if (the_result && !longrc) {
-               printk(KERN_NOTICE "%s : READ CAPACITY failed.\n"
-                      "%s : status=%x, message=%02x, host=%d, driver=%02x \n",
-                      diskname, diskname,
-                      status_byte(the_result),
-                      msg_byte(the_result),
-                      host_byte(the_result),
-                      driver_byte(the_result));
-
+               sd_printk(KERN_NOTICE, sdkp, "READ CAPACITY failed\n");
+               sd_print_result(sdkp, the_result);
                if (driver_byte(the_result) & DRIVER_SENSE)
-                       scsi_print_sense_hdr("sd", &sshdr);
+                       sd_print_sense_hdr(sdkp, &sshdr);
                else
-                       printk("%s : sense not available. \n", diskname);
+                       sd_printk(KERN_NOTICE, sdkp, "Sense not available.\n");
 
                /* Set dirty bit for removable devices if not ready -
                 * sometimes drives will not report this properly. */
@@ -1218,16 +1191,10 @@ repeat:
                return;
        } else if (the_result && longrc) {
                /* READ CAPACITY(16) has been failed */
-               printk(KERN_NOTICE "%s : READ CAPACITY(16) failed.\n"
-                      "%s : status=%x, message=%02x, host=%d, driver=%02x \n",
-                      diskname, diskname,
-                      status_byte(the_result),
-                      msg_byte(the_result),
-                      host_byte(the_result),
-                      driver_byte(the_result));
-               printk(KERN_NOTICE "%s : use 0xffffffff as device size\n",
-                      diskname);
-               
+               sd_printk(KERN_NOTICE, sdkp, "READ CAPACITY(16) failed\n");
+               sd_print_result(sdkp, the_result);
+               sd_printk(KERN_NOTICE, sdkp, "Use 0xffffffff as device size\n");
+
                sdkp->capacity = 1 + (sector_t) 0xffffffff;             
                goto got_data;
        }       
@@ -1238,14 +1205,14 @@ repeat:
                if (buffer[0] == 0xff && buffer[1] == 0xff &&
                    buffer[2] == 0xff && buffer[3] == 0xff) {
                        if(sizeof(sdkp->capacity) > 4) {
-                               printk(KERN_NOTICE "%s : very big device. try to use"
-                                      " READ CAPACITY(16).\n", diskname);
+                               sd_printk(KERN_NOTICE, sdkp, "Very big device. "
+                                         "Trying to use READ CAPACITY(16).\n");
                                longrc = 1;
                                goto repeat;
                        }
-                       printk(KERN_ERR "%s: too big for this kernel.  Use a "
-                              "kernel compiled with support for large block "
-                              "devices.\n", diskname);
+                       sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use "
+                                 "a kernel compiled with support for large "
+                                 "block devices.\n");
                        sdkp->capacity = 0;
                        goto got_data;
                }
@@ -1284,8 +1251,8 @@ repeat:
 got_data:
        if (sector_size == 0) {
                sector_size = 512;
-               printk(KERN_NOTICE "%s : sector size 0 reported, "
-                      "assuming 512.\n", diskname);
+               sd_printk(KERN_NOTICE, sdkp, "Sector size 0 reported, "
+                         "assuming 512.\n");
        }
 
        if (sector_size != 512 &&
@@ -1293,8 +1260,8 @@ got_data:
            sector_size != 2048 &&
            sector_size != 4096 &&
            sector_size != 256) {
-               printk(KERN_NOTICE "%s : unsupported sector size "
-                      "%d.\n", diskname, sector_size);
+               sd_printk(KERN_NOTICE, sdkp, "Unsupported sector size %d.\n",
+                         sector_size);
                /*
                 * The user might want to re-format the drive with
                 * a supported sectorsize.  Once this happens, it
@@ -1327,10 +1294,10 @@ got_data:
                mb -= sz - 974;
                sector_div(mb, 1950);
 
-               printk(KERN_NOTICE "SCSI device %s: "
-                      "%llu %d-byte hdwr sectors (%llu MB)\n",
-                      diskname, (unsigned long long)sdkp->capacity,
-                      hard_sector, (unsigned long long)mb);
+               sd_printk(KERN_NOTICE, sdkp,
+                         "%llu %d-byte hardware sectors (%llu MB)\n",
+                         (unsigned long long)sdkp->capacity,
+                         hard_sector, (unsigned long long)mb);
        }
 
        /* Rescale capacity to 512-byte units */
@@ -1362,8 +1329,7 @@ sd_do_mode_sense(struct scsi_device *sdp, int dbd, int modepage,
  * called with buffer of length SD_BUF_SIZE
  */
 static void
-sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
-                          unsigned char *buffer)
+sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer)
 {
        int res;
        struct scsi_device *sdp = sdkp->device;
@@ -1371,7 +1337,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
 
        set_disk_ro(sdkp->disk, 0);
        if (sdp->skip_ms_page_3f) {
-               printk(KERN_NOTICE "%s: assuming Write Enabled\n", diskname);
+               sd_printk(KERN_NOTICE, sdkp, "Assuming Write Enabled\n");
                return;
        }
 
@@ -1403,15 +1369,16 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
        }
 
        if (!scsi_status_is_good(res)) {
-               printk(KERN_WARNING
-                      "%s: test WP failed, assume Write Enabled\n", diskname);
+               sd_printk(KERN_WARNING, sdkp,
+                         "Test WP failed, assume Write Enabled\n");
        } else {
                sdkp->write_prot = ((data.device_specific & 0x80) != 0);
                set_disk_ro(sdkp->disk, sdkp->write_prot);
-               printk(KERN_NOTICE "%s: Write Protect is %s\n", diskname,
-                      sdkp->write_prot ? "on" : "off");
-               printk(KERN_DEBUG "%s: Mode Sense: %02x %02x %02x %02x\n",
-                      diskname, buffer[0], buffer[1], buffer[2], buffer[3]);
+               sd_printk(KERN_NOTICE, sdkp, "Write Protect is %s\n",
+                         sdkp->write_prot ? "on" : "off");
+               sd_printk(KERN_DEBUG, sdkp,
+                         "Mode Sense: %02x %02x %02x %02x\n",
+                         buffer[0], buffer[1], buffer[2], buffer[3]);
        }
 }
 
@@ -1420,8 +1387,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
  * called with buffer of length SD_BUF_SIZE
  */
 static void
-sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
-                  unsigned char *buffer)
+sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
 {
        int len = 0, res;
        struct scsi_device *sdp = sdkp->device;
@@ -1450,8 +1416,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
 
        if (!data.header_length) {
                modepage = 6;
-               printk(KERN_ERR "%s: missing header in MODE_SENSE response\n",
-                      diskname);
+               sd_printk(KERN_ERR, sdkp, "Missing header in MODE_SENSE response\n");
        }
 
        /* that went OK, now ask for the proper length */
@@ -1478,13 +1443,12 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
                int offset = data.header_length + data.block_descriptor_length;
 
                if (offset >= SD_BUF_SIZE - 2) {
-                       printk(KERN_ERR "%s: malformed MODE SENSE response",
-                               diskname);
+                       sd_printk(KERN_ERR, sdkp, "Malformed MODE SENSE response\n");
                        goto defaults;
                }
 
                if ((buffer[offset] & 0x3f) != modepage) {
-                       printk(KERN_ERR "%s: got wrong page\n", diskname);
+                       sd_printk(KERN_ERR, sdkp, "Got wrong page\n");
                        goto defaults;
                }
 
@@ -1498,14 +1462,13 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
 
                sdkp->DPOFUA = (data.device_specific & 0x10) != 0;
                if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) {
-                       printk(KERN_NOTICE "SCSI device %s: uses "
-                              "READ/WRITE(6), disabling FUA\n", diskname);
+                       sd_printk(KERN_NOTICE, sdkp,
+                                 "Uses READ/WRITE(6), disabling FUA\n");
                        sdkp->DPOFUA = 0;
                }
 
-               printk(KERN_NOTICE "SCSI device %s: "
-                      "write cache: %s, read cache: %s, %s\n",
-                      diskname,
+               sd_printk(KERN_NOTICE, sdkp,
+                      "Write cache: %s, read cache: %s, %s\n",
                       sdkp->WCE ? "enabled" : "disabled",
                       sdkp->RCD ? "disabled" : "enabled",
                       sdkp->DPOFUA ? "supports DPO and FUA"
@@ -1518,15 +1481,13 @@ bad_sense:
        if (scsi_sense_valid(&sshdr) &&
            sshdr.sense_key == ILLEGAL_REQUEST &&
            sshdr.asc == 0x24 && sshdr.ascq == 0x0)
-               printk(KERN_NOTICE "%s: cache data unavailable\n",
-                      diskname);       /* Invalid field in CDB */
+               /* Invalid field in CDB */
+               sd_printk(KERN_NOTICE, sdkp, "Cache data unavailable\n");
        else
-               printk(KERN_ERR "%s: asking for cache data failed\n",
-                      diskname);
+               sd_printk(KERN_ERR, sdkp, "Asking for cache data failed\n");
 
 defaults:
-       printk(KERN_ERR "%s: assuming drive cache: write through\n",
-              diskname);
+       sd_printk(KERN_ERR, sdkp, "Assuming drive cache: write through\n");
        sdkp->WCE = 0;
        sdkp->RCD = 0;
        sdkp->DPOFUA = 0;
@@ -1544,7 +1505,8 @@ static int sd_revalidate_disk(struct gendisk *disk)
        unsigned char *buffer;
        unsigned ordered;
 
-       SCSI_LOG_HLQUEUE(3, printk("sd_revalidate_disk: disk=%s\n", disk->disk_name));
+       SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp,
+                                     "sd_revalidate_disk\n"));
 
        /*
         * If the device is offline, don't try and read capacity or any
@@ -1555,8 +1517,8 @@ static int sd_revalidate_disk(struct gendisk *disk)
 
        buffer = kmalloc(SD_BUF_SIZE, GFP_KERNEL | __GFP_DMA);
        if (!buffer) {
-               printk(KERN_WARNING "(sd_revalidate_disk:) Memory allocation "
-                      "failure.\n");
+               sd_printk(KERN_WARNING, sdkp, "sd_revalidate_disk: Memory "
+                         "allocation failure.\n");
                goto out;
        }
 
@@ -1568,16 +1530,16 @@ static int sd_revalidate_disk(struct gendisk *disk)
        sdkp->WCE = 0;
        sdkp->RCD = 0;
 
-       sd_spinup_disk(sdkp, disk->disk_name);
+       sd_spinup_disk(sdkp);
 
        /*
         * Without media there is no reason to ask; moreover, some devices
         * react badly if we do.
         */
        if (sdkp->media_present) {
-               sd_read_capacity(sdkp, disk->disk_name, buffer);
-               sd_read_write_protect_flag(sdkp, disk->disk_name, buffer);
-               sd_read_cache_type(sdkp, disk->disk_name, buffer);
+               sd_read_capacity(sdkp, buffer);
+               sd_read_write_protect_flag(sdkp, buffer);
+               sd_read_cache_type(sdkp, buffer);
        }
 
        /*
@@ -1709,8 +1671,8 @@ static int sd_probe(struct device *dev)
        dev_set_drvdata(dev, sdkp);
        add_disk(gd);
 
-       sdev_printk(KERN_NOTICE, sdp, "Attached scsi %sdisk %s\n",
-                   sdp->removable ? "removable " : "", gd->disk_name);
+       sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
+                 sdp->removable ? "removable " : "");
 
        return 0;
 
@@ -1774,6 +1736,31 @@ static void scsi_disk_release(struct class_device *cdev)
        kfree(sdkp);
 }
 
+static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
+{
+       unsigned char cmd[6] = { START_STOP };  /* START_VALID */
+       struct scsi_sense_hdr sshdr;
+       struct scsi_device *sdp = sdkp->device;
+       int res;
+
+       if (start)
+               cmd[4] |= 1;    /* START */
+
+       if (!scsi_device_online(sdp))
+               return -ENODEV;
+
+       res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
+                              SD_TIMEOUT, SD_MAX_RETRIES);
+       if (res) {
+               sd_printk(KERN_WARNING, sdkp, "START_STOP FAILED\n");
+               sd_print_result(sdkp, res);
+               if (driver_byte(res) & DRIVER_SENSE)
+                       sd_print_sense_hdr(sdkp, &sshdr);
+       }
+
+       return res;
+}
+
 /*
  * Send a SYNCHRONIZE CACHE instruction down to the device through
  * the normal SCSI command structure.  Wait for the command to
@@ -1781,20 +1768,62 @@ static void scsi_disk_release(struct class_device *cdev)
  */
 static void sd_shutdown(struct device *dev)
 {
-       struct scsi_device *sdp = to_scsi_device(dev);
        struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
 
        if (!sdkp)
                return;         /* this can happen */
 
        if (sdkp->WCE) {
-               printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: \n",
-                               sdkp->disk->disk_name);
-               sd_sync_cache(sdp);
+               sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
+               sd_sync_cache(sdkp);
+       }
+
+       if (system_state != SYSTEM_RESTART && sdkp->device->manage_start_stop) {
+               sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
+               sd_start_stop_device(sdkp, 0);
        }
+
        scsi_disk_put(sdkp);
 }
 
+static int sd_suspend(struct device *dev, pm_message_t mesg)
+{
+       struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
+       int ret;
+
+       if (!sdkp)
+               return 0;       /* this can happen */
+
+       if (sdkp->WCE) {
+               sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
+               ret = sd_sync_cache(sdkp);
+               if (ret)
+                       return ret;
+       }
+
+       if (mesg.event == PM_EVENT_SUSPEND &&
+           sdkp->device->manage_start_stop) {
+               sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
+               ret = sd_start_stop_device(sdkp, 0);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int sd_resume(struct device *dev)
+{
+       struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
+
+       if (!sdkp->device->manage_start_stop)
+               return 0;
+
+       sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
+
+       return sd_start_stop_device(sdkp, 1);
+}
+
 /**
  *     init_sd - entry point for this driver (both when built in or when
  *     a module).
@@ -1852,3 +1881,19 @@ static void __exit exit_sd(void)
 
 module_init(init_sd);
 module_exit(exit_sd);
+
+static void sd_print_sense_hdr(struct scsi_disk *sdkp,
+                              struct scsi_sense_hdr *sshdr)
+{
+       sd_printk(KERN_INFO, sdkp, "");
+       scsi_show_sense_hdr(sshdr);
+       sd_printk(KERN_INFO, sdkp, "");
+       scsi_show_extd_sense(sshdr->asc, sshdr->ascq);
+}
+
+static void sd_print_result(struct scsi_disk *sdkp, int result)
+{
+       sd_printk(KERN_INFO, sdkp, "");
+       scsi_show_result(result);
+}
+
index 81e3bc7..570977c 100644 (file)
@@ -917,6 +917,8 @@ sg_ioctl(struct inode *inode, struct file *filp,
                        return result;
                 if (val < 0)
                         return -EINVAL;
+               val = min_t(int, val,
+                               sdp->device->request_queue->max_sectors * 512);
                if (val != sfp->reserve.bufflen) {
                        if (sg_res_in_use(sfp) || sfp->mmap_called)
                                return -EBUSY;
@@ -925,7 +927,8 @@ sg_ioctl(struct inode *inode, struct file *filp,
                }
                return 0;
        case SG_GET_RESERVED_SIZE:
-               val = (int) sfp->reserve.bufflen;
+               val = min_t(int, sfp->reserve.bufflen,
+                               sdp->device->request_queue->max_sectors * 512);
                return put_user(val, ip);
        case SG_SET_COMMAND_Q:
                result = get_user(val, ip);
@@ -1061,6 +1064,9 @@ sg_ioctl(struct inode *inode, struct file *filp,
                if (sdp->detached)
                        return -ENODEV;
                return scsi_ioctl(sdp->device, cmd_in, p);
+       case BLKSECTGET:
+               return put_user(sdp->device->request_queue->max_sectors * 512,
+                               ip);
        default:
                if (read_only)
                        return -EPERM;  /* don't know so take safe approach */
@@ -2339,6 +2345,7 @@ sg_add_sfp(Sg_device * sdp, int dev)
 {
        Sg_fd *sfp;
        unsigned long iflags;
+       int bufflen;
 
        sfp = kzalloc(sizeof(*sfp), GFP_ATOMIC | __GFP_NOWARN);
        if (!sfp)
@@ -2369,7 +2376,9 @@ sg_add_sfp(Sg_device * sdp, int dev)
        if (unlikely(sg_big_buff != def_reserved_size))
                sg_big_buff = def_reserved_size;
 
-       sg_build_reserve(sfp, sg_big_buff);
+       bufflen = min_t(int, sg_big_buff,
+                       sdp->device->request_queue->max_sectors * 512);
+       sg_build_reserve(sfp, bufflen);
        SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp:   bufflen=%d, k_use_sg=%d\n",
                           sfp->reserve.bufflen, sfp->reserve.k_use_sg));
        return sfp;
index 1857d68..f9a52af 100644 (file)
@@ -62,6 +62,8 @@
 MODULE_DESCRIPTION("SCSI cdrom (sr) driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_CDROM_MAJOR);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_ROM);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_WORM);
 
 #define SR_DISKS       256
 
index 98d8411..55bfecc 100644 (file)
@@ -89,6 +89,7 @@ MODULE_AUTHOR("Kai Makisara");
 MODULE_DESCRIPTION("SCSI tape (st) driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_CHARDEV_MAJOR(SCSI_TAPE_MAJOR);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
 
 /* Set 'perm' (4th argument) to 0 to disable module_param's definition
  * of sysfs parameters (which module_param doesn't yet support).
index a583e89..3158949 100644 (file)
@@ -2680,7 +2680,7 @@ static int __init dc390_module_init(void)
                printk (KERN_INFO "DC390: Using safe settings.\n");
        }
 
-       return pci_module_init(&dc390_driver);
+       return pci_register_driver(&dc390_driver);
 }
 
 static void __exit dc390_module_exit(void)
index 9bf420e..284a073 100644 (file)
@@ -10,9 +10,6 @@ obj-$(CONFIG_USB_ATI_REMOTE)  += ati_remote.o
 obj-$(CONFIG_USB_ATI_REMOTE2)  += ati_remote2.o
 obj-$(CONFIG_USB_KBTAB)                += kbtab.o
 obj-$(CONFIG_USB_KEYSPAN_REMOTE)       += keyspan_remote.o
-obj-$(CONFIG_USB_MTOUCH)       += mtouchusb.o
-obj-$(CONFIG_USB_ITMTOUCH)     += itmtouch.o
-obj-$(CONFIG_USB_EGALAX)       += touchkitusb.o
 obj-$(CONFIG_USB_TOUCHSCREEN)  += usbtouchscreen.o
 obj-$(CONFIG_USB_POWERMATE)    += powermate.o
 obj-$(CONFIG_USB_WACOM)                += wacom.o
@@ -20,7 +17,7 @@ obj-$(CONFIG_USB_ACECAD)      += acecad.o
 obj-$(CONFIG_USB_YEALINK)      += yealink.o
 obj-$(CONFIG_USB_XPAD)         += xpad.o
 obj-$(CONFIG_USB_APPLETOUCH)   += appletouch.o
-obj-$(CONFIG_USB_GTCO)         += gtco.o
+obj-$(CONFIG_USB_GTCO)         += gtco.o
 
 ifeq ($(CONFIG_USB_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
index 909138e..be8e924 100644 (file)
@@ -111,7 +111,7 @@ resubmit:
 
 static int usb_acecad_open(struct input_dev *dev)
 {
-       struct usb_acecad *acecad = dev->private;
+       struct usb_acecad *acecad = input_get_drvdata(dev);
 
        acecad->irq->dev = acecad->usbdev;
        if (usb_submit_urb(acecad->irq, GFP_KERNEL))
@@ -122,7 +122,7 @@ static int usb_acecad_open(struct input_dev *dev)
 
 static void usb_acecad_close(struct input_dev *dev)
 {
-       struct usb_acecad *acecad = dev->private;
+       struct usb_acecad *acecad = input_get_drvdata(dev);
 
        usb_kill_urb(acecad->irq);
 }
@@ -135,6 +135,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
        struct usb_acecad *acecad;
        struct input_dev *input_dev;
        int pipe, maxp;
+       int err = -ENOMEM;
 
        if (interface->desc.bNumEndpoints != 1)
                return -ENODEV;
@@ -149,16 +150,22 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
 
        acecad = kzalloc(sizeof(struct usb_acecad), GFP_KERNEL);
        input_dev = input_allocate_device();
-       if (!acecad || !input_dev)
+       if (!acecad || !input_dev) {
+               err = -ENOMEM;
                goto fail1;
+       }
 
        acecad->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &acecad->data_dma);
-       if (!acecad->data)
+       if (!acecad->data) {
+               err= -ENOMEM;
                goto fail1;
+       }
 
        acecad->irq = usb_alloc_urb(0, GFP_KERNEL);
-       if (!acecad->irq)
+       if (!acecad->irq) {
+               err = -ENOMEM;
                goto fail2;
+       }
 
        acecad->usbdev = dev;
        acecad->input = input_dev;
@@ -178,8 +185,9 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
        input_dev->name = acecad->name;
        input_dev->phys = acecad->phys;
        usb_to_input_id(dev, &input_dev->id);
-       input_dev->cdev.dev = &intf->dev;
-       input_dev->private = acecad;
+       input_dev->dev.parent = &intf->dev;
+
+       input_set_drvdata(input_dev, acecad);
 
        input_dev->open = usb_acecad_open;
        input_dev->close = usb_acecad_close;
@@ -221,7 +229,9 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
        acecad->irq->transfer_dma = acecad->data_dma;
        acecad->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-       input_register_device(acecad->input);
+       err = input_register_device(acecad->input);
+       if (err)
+               goto fail2;
 
        usb_set_intfdata(intf, acecad);
 
@@ -230,7 +240,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
  fail2:        usb_buffer_free(dev, 8, acecad->data, acecad->data_dma);
  fail1: input_free_device(input_dev);
        kfree(acecad);
-       return -ENOMEM;
+       return err;
 }
 
 static void usb_acecad_disconnect(struct usb_interface *intf)
index f857935..cc0a498 100644 (file)
@@ -798,7 +798,7 @@ MODULE_DEVICE_TABLE(usb, aiptek_ids);
  */
 static int aiptek_open(struct input_dev *inputdev)
 {
-       struct aiptek *aiptek = inputdev->private;
+       struct aiptek *aiptek = input_get_drvdata(inputdev);
 
        aiptek->urb->dev = aiptek->usbdev;
        if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0)
@@ -812,7 +812,7 @@ static int aiptek_open(struct input_dev *inputdev)
  */
 static void aiptek_close(struct input_dev *inputdev)
 {
-       struct aiptek *aiptek = inputdev->private;
+       struct aiptek *aiptek = input_get_drvdata(inputdev);
 
        usb_kill_urb(aiptek->urb);
 }
@@ -1972,6 +1972,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
                AIPTEK_PROGRAMMABLE_DELAY_200,
                AIPTEK_PROGRAMMABLE_DELAY_300
        };
+       int err = -ENOMEM;
 
        /* programmableDelay is where the command-line specified
         * delay is kept. We make it the first element of speeds[],
@@ -2043,8 +2044,10 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
        inputdev->name = "Aiptek";
        inputdev->phys = aiptek->features.usbPath;
        usb_to_input_id(usbdev, &inputdev->id);
-       inputdev->cdev.dev = &intf->dev;
-       inputdev->private = aiptek;
+       inputdev->dev.parent = &intf->dev;
+
+       input_set_drvdata(inputdev, aiptek);
+
        inputdev->open = aiptek_open;
        inputdev->close = aiptek_close;
 
@@ -2133,7 +2136,9 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
 
        /* Register the tablet as an Input Device
         */
-       input_register_device(aiptek->inputdev);
+       err = input_register_device(aiptek->inputdev);
+       if (err)
+               goto fail2;
 
        /* We now will look for the evdev device which is mapped to
         * the tablet. The partial name is kept in the link list of
@@ -2165,23 +2170,13 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
 
        return 0;
 
-fail2: usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
+ fail2:        usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
                        aiptek->data_dma);
-fail1: input_free_device(inputdev);
+ fail1:        input_free_device(inputdev);
        kfree(aiptek);
-       return -ENOMEM;
+       return err;
 }
 
-/* Forward declaration */
-static void aiptek_disconnect(struct usb_interface *intf);
-
-static struct usb_driver aiptek_driver = {
-       .name = "aiptek",
-       .probe = aiptek_probe,
-       .disconnect = aiptek_disconnect,
-       .id_table = aiptek_ids,
-};
-
 /***********************************************************************
  * Deal with tablet disconnecting from the system.
  */
@@ -2206,6 +2201,13 @@ static void aiptek_disconnect(struct usb_interface *intf)
        }
 }
 
+static struct usb_driver aiptek_driver = {
+       .name = "aiptek",
+       .probe = aiptek_probe,
+       .disconnect = aiptek_disconnect,
+       .id_table = aiptek_ids,
+};
+
 static int __init aiptek_init(void)
 {
        int result = usb_register(&aiptek_driver);
index c77291d..e321526 100644 (file)
@@ -466,7 +466,7 @@ exit:
 
 static int atp_open(struct input_dev *input)
 {
-       struct atp *dev = input->private;
+       struct atp *dev = input_get_drvdata(input);
 
        if (usb_submit_urb(dev->urb, GFP_ATOMIC))
                return -EIO;
@@ -477,7 +477,7 @@ static int atp_open(struct input_dev *input)
 
 static void atp_close(struct input_dev *input)
 {
-       struct atp *dev = input->private;
+       struct atp *dev = input_get_drvdata(input);
 
        usb_kill_urb(dev->urb);
        dev->open = 0;
@@ -491,8 +491,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
        struct usb_host_interface *iface_desc;
        struct usb_endpoint_descriptor *endpoint;
        int int_in_endpointAddr = 0;
-       int i, retval = -ENOMEM;
-
+       int i, error = -ENOMEM;
 
        /* set up the endpoint information */
        /* use only the first interrupt-in endpoint */
@@ -567,17 +566,13 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
        }
 
        dev->urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!dev->urb) {
-               retval = -ENOMEM;
+       if (!dev->urb)
                goto err_free_devs;
-       }
 
        dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL,
                                     &dev->urb->transfer_dma);
-       if (!dev->data) {
-               retval = -ENOMEM;
+       if (!dev->data)
                goto err_free_urb;
-       }
 
        usb_fill_int_urb(dev->urb, udev,
                         usb_rcvintpipe(udev, int_in_endpointAddr),
@@ -589,9 +584,10 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
        input_dev->name = "appletouch";
        input_dev->phys = dev->phys;
        usb_to_input_id(dev->udev, &input_dev->id);
-       input_dev->cdev.dev = &iface->dev;
+       input_dev->dev.parent = &iface->dev;
+
+       input_set_drvdata(input_dev, dev);
 
-       input_dev->private = dev;
        input_dev->open = atp_open;
        input_dev->close = atp_close;
 
@@ -633,20 +629,25 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
        set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
        set_bit(BTN_LEFT, input_dev->keybit);
 
-       input_register_device(dev->input);
+       error = input_register_device(dev->input);
+       if (error)
+               goto err_free_buffer;
 
        /* save our data pointer in this interface device */
        usb_set_intfdata(iface, dev);
 
        return 0;
 
+ err_free_buffer:
+       usb_buffer_free(dev->udev, dev->datalen,
+                       dev->data, dev->urb->transfer_dma);
  err_free_urb:
        usb_free_urb(dev->urb);
  err_free_devs:
        usb_set_intfdata(iface, NULL);
        kfree(dev);
        input_free_device(input_dev);
-       return retval;
+       return error;
 }
 
 static void atp_disconnect(struct usb_interface *iface)
index b724e36..471aab2 100644 (file)
  * behaviour.
  */
 #define FILTER_TIME    60 /* msec */
+#define REPEAT_DELAY   500 /* msec */
 
 static unsigned long channel_mask;
 module_param(channel_mask, ulong, 0644);
@@ -133,6 +134,10 @@ static int repeat_filter = FILTER_TIME;
 module_param(repeat_filter, int, 0644);
 MODULE_PARM_DESC(repeat_filter, "Repeat filter time, default = 60 msec");
 
+static int repeat_delay = REPEAT_DELAY;
+module_param(repeat_delay, int, 0644);
+MODULE_PARM_DESC(repeat_delay, "Delay before sending repeats, default = 500 msec");
+
 #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0)
 #undef err
 #define err(format, arg...) printk(KERN_ERR format , ## arg)
@@ -174,6 +179,8 @@ struct ati_remote {
        unsigned char old_data[2];  /* Detect duplicate events */
        unsigned long old_jiffies;
        unsigned long acc_jiffies;  /* handle acceleration */
+       unsigned long first_jiffies;
+
        unsigned int repeat_count;
 
        char name[NAME_BUFSIZE];
@@ -318,7 +325,7 @@ static void ati_remote_dump(unsigned char *data, unsigned int len)
  */
 static int ati_remote_open(struct input_dev *inputdev)
 {
-       struct ati_remote *ati_remote = inputdev->private;
+       struct ati_remote *ati_remote = input_get_drvdata(inputdev);
 
        /* On first open, submit the read urb which was set up previously. */
        ati_remote->irq_urb->dev = ati_remote->udev;
@@ -336,7 +343,7 @@ static int ati_remote_open(struct input_dev *inputdev)
  */
 static void ati_remote_close(struct input_dev *inputdev)
 {
-       struct ati_remote *ati_remote = inputdev->private;
+       struct ati_remote *ati_remote = input_get_drvdata(inputdev);
 
        usb_kill_urb(ati_remote->irq_urb);
 }
@@ -501,21 +508,31 @@ static void ati_remote_input_report(struct urb *urb)
        }
 
        if (ati_remote_tbl[index].kind == KIND_FILTERED) {
+               unsigned long now = jiffies;
+
                /* Filter duplicate events which happen "too close" together. */
                if (ati_remote->old_data[0] == data[1] &&
                    ati_remote->old_data[1] == data[2] &&
-                   time_before(jiffies, ati_remote->old_jiffies + msecs_to_jiffies(repeat_filter))) {
+                   time_before(now, ati_remote->old_jiffies +
+                                    msecs_to_jiffies(repeat_filter))) {
                        ati_remote->repeat_count++;
                } else {
                        ati_remote->repeat_count = 0;
+                       ati_remote->first_jiffies = now;
                }
 
                ati_remote->old_data[0] = data[1];
                ati_remote->old_data[1] = data[2];
-               ati_remote->old_jiffies = jiffies;
+               ati_remote->old_jiffies = now;
 
+               /* Ensure we skip at least the 4 first duplicate events (generated
+                * by a single keypress), and continue skipping until repeat_delay
+                * msecs have passed
+                */
                if (ati_remote->repeat_count > 0 &&
-                   ati_remote->repeat_count < 5)
+                   (ati_remote->repeat_count < 5 ||
+                    time_before(now, ati_remote->first_jiffies +
+                                     msecs_to_jiffies(repeat_delay))))
                        return;
 
 
@@ -653,7 +670,8 @@ static void ati_remote_input_init(struct ati_remote *ati_remote)
                if (ati_remote_tbl[i].type == EV_KEY)
                        set_bit(ati_remote_tbl[i].code, idev->keybit);
 
-       idev->private = ati_remote;
+       input_set_drvdata(idev, ati_remote);
+
        idev->open = ati_remote_open;
        idev->close = ati_remote_close;
 
@@ -661,7 +679,7 @@ static void ati_remote_input_init(struct ati_remote *ati_remote)
        idev->phys = ati_remote->phys;
 
        usb_to_input_id(ati_remote->udev, &idev->id);
-       idev->cdev.dev = &ati_remote->udev->dev;
+       idev->dev.parent = &ati_remote->udev->dev;
 }
 
 static int ati_remote_initialize(struct ati_remote *ati_remote)
@@ -772,15 +790,17 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de
                goto fail3;
 
        /* Set up and register input device */
-       input_register_device(ati_remote->idev);
+       err = input_register_device(ati_remote->idev);
+       if (err)
+               goto fail3;
 
        usb_set_intfdata(interface, ati_remote);
        return 0;
 
-fail3: usb_kill_urb(ati_remote->irq_urb);
+ fail3:        usb_kill_urb(ati_remote->irq_urb);
        usb_kill_urb(ati_remote->out_urb);
-fail2: ati_remote_free_buffers(ati_remote);
-fail1: input_free_device(input_dev);
+ fail2:        ati_remote_free_buffers(ati_remote);
+ fail1:        input_free_device(input_dev);
        kfree(ati_remote);
        return err;
 }
index 6459be9..a9032aa 100644 (file)
@@ -131,7 +131,7 @@ static struct usb_driver ati_remote2_driver = {
 
 static int ati_remote2_open(struct input_dev *idev)
 {
-       struct ati_remote2 *ar2 = idev->private;
+       struct ati_remote2 *ar2 = input_get_drvdata(idev);
        int r;
 
        r = usb_submit_urb(ar2->urb[0], GFP_KERNEL);
@@ -153,7 +153,7 @@ static int ati_remote2_open(struct input_dev *idev)
 
 static void ati_remote2_close(struct input_dev *idev)
 {
-       struct ati_remote2 *ar2 = idev->private;
+       struct ati_remote2 *ar2 = input_get_drvdata(idev);
 
        usb_kill_urb(ar2->urb[0]);
        usb_kill_urb(ar2->urb[1]);
@@ -337,14 +337,14 @@ static void ati_remote2_complete_key(struct urb *urb)
 static int ati_remote2_input_init(struct ati_remote2 *ar2)
 {
        struct input_dev *idev;
-       int i;
+       int i, retval;
 
        idev = input_allocate_device();
        if (!idev)
                return -ENOMEM;
 
        ar2->idev = idev;
-       idev->private = ar2;
+       input_set_drvdata(idev, ar2);
 
        idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL);
        idev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
@@ -362,13 +362,13 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2)
        idev->phys = ar2->phys;
 
        usb_to_input_id(ar2->udev, &idev->id);
-       idev->cdev.dev = &ar2->udev->dev;
+       idev->dev.parent = &ar2->udev->dev;
 
-       i = input_register_device(idev);
-       if (i)
+       retval = input_register_device(idev);
+       if (retval)
                input_free_device(idev);
 
-       return i;
+       return retval;
 }
 
 static int ati_remote2_urb_init(struct ati_remote2 *ar2)
index ae756e0..b2ca10f 100644 (file)
@@ -187,7 +187,6 @@ struct hid_descriptor
 
 
 /*
- *
  *   This is an abbreviated parser for the HID Report Descriptor.  We
  *   know what devices we are talking to, so this is by no means meant
  *   to be generic.  We can make some safe assumptions:
@@ -204,7 +203,7 @@ struct hid_descriptor
 static void parse_hid_report_descriptor(struct gtco *device, char * report,
                                        int length)
 {
-       int   x,i=0;
+       int   x, i = 0;
 
        /* Tag primitive vars */
        __u8   prefix;
@@ -215,7 +214,6 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
        __u16  data16 = 0;
        __u32  data32 = 0;
 
-
        /* For parsing logic */
        int   inputnum = 0;
        __u32 usage = 0;
@@ -225,46 +223,46 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
        __u32 oldval[TAG_GLOB_MAX];
 
        /* Debug stuff */
-       char  maintype='x';
+       char  maintype = 'x';
        char  globtype[12];
-       int   indent=0;
-       char  indentstr[10]="";
-
+       int   indent = 0;
+       char  indentstr[10] = "";
 
 
        dbg("======>>>>>>PARSE<<<<<<======");
 
        /* Walk  this report and pull out the info we need */
-       while (i<length){
-               prefix=report[i];
+       while (i < length) {
+               prefix = report[i];
 
                /* Skip over prefix */
                i++;
 
                /* Determine data size and save the data in the proper variable */
                size = PREF_SIZE(prefix);
-               switch(size){
+               switch (size) {
                case 1:
                        data = report[i];
                        break;
                case 2:
-                       data16 = le16_to_cpu(get_unaligned((__le16*)(&(report[i]))));
+                       data16 = le16_to_cpu(get_unaligned((__le16 *)&report[i]));
                        break;
                case 3:
                        size = 4;
-                       data32 = le32_to_cpu(get_unaligned((__le32*)(&(report[i]))));
+                       data32 = le32_to_cpu(get_unaligned((__le32 *)&report[i]));
+                       break;
                }
 
                /* Skip size of data */
-               i+=size;
+               i += size;
 
                /* What we do depends on the tag type */
                tag  = PREF_TAG(prefix);
                type = PREF_TYPE(prefix);
-               switch(type){
+               switch (type) {
                case TYPE_MAIN:
-                       strcpy(globtype,"");
-                       switch(tag){
+                       strcpy(globtype, "");
+                       switch (tag) {
 
                        case TAG_MAIN_INPUT:
                                /*
@@ -274,19 +272,17 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
                                 * min/max values
                                 */
 
-                               maintype='I';
-                               if (data==2){
-                                       strcpy(globtype,"Variable");
-                               }
-                               if (data==3){
-                                       strcpy(globtype,"Var|Const");
-                               }
+                               maintype = 'I';
+                               if (data == 2)
+                                       strcpy(globtype, "Variable");
+                               else if (data == 3)
+                                       strcpy(globtype, "Var|Const");
 
                                dbg("::::: Saving Report: %d input #%d Max: 0x%X(%d) Min:0x%X(%d) of %d bits",
-                                   globalval[TAG_GLOB_REPORT_ID],inputnum,
-                                   globalval[TAG_GLOB_LOG_MAX],globalval[TAG_GLOB_LOG_MAX],
-                                   globalval[TAG_GLOB_LOG_MIN],globalval[TAG_GLOB_LOG_MIN],
-                                   (globalval[TAG_GLOB_REPORT_SZ] * globalval[TAG_GLOB_REPORT_CNT]));
+                                   globalval[TAG_GLOB_REPORT_ID], inputnum,
+                                   globalval[TAG_GLOB_LOG_MAX], globalval[TAG_GLOB_LOG_MAX],
+                                   globalval[TAG_GLOB_LOG_MIN], globalval[TAG_GLOB_LOG_MIN],
+                                   globalval[TAG_GLOB_REPORT_SZ] * globalval[TAG_GLOB_REPORT_CNT]);
 
 
                                /*
@@ -295,43 +291,43 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
                                  that, we look for everything else by
                                  local usage value
                                 */
-                               switch (inputnum){
+                               switch (inputnum) {
                                case 0:  /* X coord */
-                                       dbg("GER: X Usage: 0x%x",usage);
-                                       if (device->max_X == 0){
+                                       dbg("GER: X Usage: 0x%x", usage);
+                                       if (device->max_X == 0) {
                                                device->max_X = globalval[TAG_GLOB_LOG_MAX];
                                                device->min_X = globalval[TAG_GLOB_LOG_MIN];
                                        }
-
                                        break;
+
                                case 1:  /* Y coord */
-                                       dbg("GER: Y Usage: 0x%x",usage);
-                                       if (device->max_Y == 0){
+                                       dbg("GER: Y Usage: 0x%x", usage);
+                                       if (device->max_Y == 0) {
                                                device->max_Y = globalval[TAG_GLOB_LOG_MAX];
                                                device->min_Y = globalval[TAG_GLOB_LOG_MIN];
                                        }
                                        break;
+
                                default:
                                        /* Tilt X */
-                                       if (usage == DIGITIZER_USAGE_TILT_X){
-                                               if (device->maxtilt_X == 0){
+                                       if (usage == DIGITIZER_USAGE_TILT_X) {
+                                               if (device->maxtilt_X == 0) {
                                                        device->maxtilt_X = globalval[TAG_GLOB_LOG_MAX];
                                                        device->mintilt_X = globalval[TAG_GLOB_LOG_MIN];
                                                }
                                        }
 
                                        /* Tilt Y */
-                                       if (usage == DIGITIZER_USAGE_TILT_Y){
-                                               if (device->maxtilt_Y == 0){
+                                       if (usage == DIGITIZER_USAGE_TILT_Y) {
+                                               if (device->maxtilt_Y == 0) {
                                                        device->maxtilt_Y = globalval[TAG_GLOB_LOG_MAX];
                                                        device->mintilt_Y = globalval[TAG_GLOB_LOG_MIN];
                                                }
                                        }
 
-
                                        /* Pressure */
-                                       if (usage == DIGITIZER_USAGE_TIP_PRESSURE){
-                                               if (device->maxpressure == 0){
+                                       if (usage == DIGITIZER_USAGE_TIP_PRESSURE) {
+                                               if (device->maxpressure == 0) {
                                                        device->maxpressure = globalval[TAG_GLOB_LOG_MAX];
                                                        device->minpressure = globalval[TAG_GLOB_LOG_MIN];
                                                }
@@ -341,214 +337,226 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
                                }
 
                                inputnum++;
-
-
                                break;
+
                        case TAG_MAIN_OUTPUT:
-                               maintype='O';
+                               maintype = 'O';
                                break;
+
                        case TAG_MAIN_FEATURE:
-                               maintype='F';
+                               maintype = 'F';
                                break;
+
                        case TAG_MAIN_COL_START:
-                               maintype='S';
+                               maintype = 'S';
 
-                               if (data==0){
+                               if (data == 0) {
                                        dbg("======>>>>>> Physical");
-                                       strcpy(globtype,"Physical");
-                               }else{
+                                       strcpy(globtype, "Physical");
+                               } else
                                        dbg("======>>>>>>");
-                               }
 
                                /* Indent the debug output */
                                indent++;
-                               for (x=0;x<indent;x++){
-                                       indentstr[x]='-';
-                               }
-                               indentstr[x]=0;
+                               for (x = 0; x < indent; x++)
+                                       indentstr[x] = '-';
+                               indentstr[x] = 0;
 
                                /* Save global tags */
-                               for (x=0;x<TAG_GLOB_MAX;x++){
+                               for (x = 0; x < TAG_GLOB_MAX; x++)
                                        oldval[x] = globalval[x];
-                               }
 
                                break;
+
                        case TAG_MAIN_COL_END:
                                dbg("<<<<<<======");
-                               maintype='E';
+                               maintype = 'E';
                                indent--;
-                               for (x=0;x<indent;x++){
-                                       indentstr[x]='-';
-                               }
-                               indentstr[x]=0;
+                               for (x = 0; x < indent; x++)
+                                       indentstr[x] = '-';
+                               indentstr[x] = 0;
 
                                /* Copy global tags back */
-                               for (x=0;x<TAG_GLOB_MAX;x++){
+                               for (x = 0; x < TAG_GLOB_MAX; x++)
                                        globalval[x] = oldval[x];
-                               }
 
                                break;
                        }
 
-                       switch (size){
+                       switch (size) {
                        case 1:
                                dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x",
-                                   indentstr,tag,maintype,size,globtype,data);
+                                   indentstr, tag, maintype, size, globtype, data);
                                break;
+
                        case 2:
                                dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x",
-                                   indentstr,tag,maintype,size,globtype, data16);
+                                   indentstr, tag, maintype, size, globtype, data16);
                                break;
+
                        case 4:
                                dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x",
-                                   indentstr,tag,maintype,size,globtype,data32);
+                                   indentstr, tag, maintype, size, globtype, data32);
                                break;
                        }
                        break;
+
                case TYPE_GLOBAL:
-                       switch(tag){
+                       switch (tag) {
                        case TAG_GLOB_USAGE:
                                /*
                                 * First time we hit the global usage tag,
                                 * it should tell us the type of device
                                 */
-                               if (device->usage == 0){
+                               if (device->usage == 0)
                                        device->usage = data;
-                               }
-                               strcpy(globtype,"USAGE");
+
+                               strcpy(globtype, "USAGE");
                                break;
-                       case TAG_GLOB_LOG_MIN   :
-                               strcpy(globtype,"LOG_MIN");
+
+                       case TAG_GLOB_LOG_MIN:
+                               strcpy(globtype, "LOG_MIN");
                                break;
-                       case TAG_GLOB_LOG_MAX   :
-                               strcpy(globtype,"LOG_MAX");
+
+                       case TAG_GLOB_LOG_MAX:
+                               strcpy(globtype, "LOG_MAX");
                                break;
-                       case TAG_GLOB_PHYS_MIN  :
-                               strcpy(globtype,"PHYS_MIN");
+
+                       case TAG_GLOB_PHYS_MIN:
+                               strcpy(globtype, "PHYS_MIN");
                                break;
-                       case TAG_GLOB_PHYS_MAX  :
-                               strcpy(globtype,"PHYS_MAX");
+
+                       case TAG_GLOB_PHYS_MAX:
+                               strcpy(globtype, "PHYS_MAX");
                                break;
-                       case TAG_GLOB_UNIT_EXP  :
-                               strcpy(globtype,"EXP");
+
+                       case TAG_GLOB_UNIT_EXP:
+                               strcpy(globtype, "EXP");
                                break;
-                       case TAG_GLOB_UNIT      :
-                               strcpy(globtype,"UNIT");
+
+                       case TAG_GLOB_UNIT:
+                               strcpy(globtype, "UNIT");
                                break;
-                       case TAG_GLOB_REPORT_SZ :
-                               strcpy(globtype,"REPORT_SZ");
+
+                       case TAG_GLOB_REPORT_SZ:
+                               strcpy(globtype, "REPORT_SZ");
                                break;
-                       case TAG_GLOB_REPORT_ID :
-                               strcpy(globtype,"REPORT_ID");
+
+                       case TAG_GLOB_REPORT_ID:
+                               strcpy(globtype, "REPORT_ID");
                                /* New report, restart numbering */
-                               inputnum=0;
+                               inputnum = 0;
                                break;
+
                        case TAG_GLOB_REPORT_CNT:
-                               strcpy(globtype,"REPORT_CNT");
+                               strcpy(globtype, "REPORT_CNT");
                                break;
-                       case TAG_GLOB_PUSH :
-                               strcpy(globtype,"PUSH");
+
+                       case TAG_GLOB_PUSH:
+                               strcpy(globtype, "PUSH");
                                break;
+
                        case TAG_GLOB_POP:
-                               strcpy(globtype,"POP");
+                               strcpy(globtype, "POP");
                                break;
                        }
 
-
                        /* Check to make sure we have a good tag number
                           so we don't overflow array */
-                       if (tag < TAG_GLOB_MAX){
-                               switch (size){
+                       if (tag < TAG_GLOB_MAX) {
+                               switch (size) {
                                case 1:
-                                       dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",indentstr,globtype,tag,size,data);
-                                       globalval[tag]=data;
+                                       dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",
+                                           indentstr, globtype, tag, size, data);
+                                       globalval[tag] = data;
                                        break;
+
                                case 2:
-                                       dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",indentstr,globtype,tag,size,data16);
-                                       globalval[tag]=data16;
+                                       dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",
+                                           indentstr, globtype, tag, size, data16);
+                                       globalval[tag] = data16;
                                        break;
+
                                case 4:
-                                       dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",indentstr,globtype,tag,size,data32);
-                                       globalval[tag]=data32;
+                                       dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",
+                                           indentstr, globtype, tag, size, data32);
+                                       globalval[tag] = data32;
                                        break;
                                }
-                       }else{
+                       } else {
                                dbg("%sGLOBALTAG: ILLEGAL TAG:%d SIZE: %d ",
-                                   indentstr,tag,size);
+                                   indentstr, tag, size);
                        }
-
-
                        break;
 
                case TYPE_LOCAL:
-                       switch(tag){
+                       switch (tag) {
                        case TAG_GLOB_USAGE:
-                               strcpy(globtype,"USAGE");
+                               strcpy(globtype, "USAGE");
                                /* Always 1 byte */
                                usage = data;
                                break;
-                       case TAG_GLOB_LOG_MIN   :
-                               strcpy(globtype,"MIN");
+
+                       case TAG_GLOB_LOG_MIN:
+                               strcpy(globtype, "MIN");
                                break;
-                       case TAG_GLOB_LOG_MAX   :
-                               strcpy(globtype,"MAX");
+
+                       case TAG_GLOB_LOG_MAX:
+                               strcpy(globtype, "MAX");
                                break;
+
                        default:
-                               strcpy(globtype,"UNKNOWN");
+                               strcpy(globtype, "UNKNOWN");
+                               break;
                        }
 
-                       switch (size){
+                       switch (size) {
                        case 1:
                                dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x",
-                                   indentstr,tag,globtype,size,data);
+                                   indentstr, tag, globtype, size, data);
                                break;
+
                        case 2:
                                dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x",
-                                   indentstr,tag,globtype,size,data16);
+                                   indentstr, tag, globtype, size, data16);
                                break;
+
                        case 4:
                                dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x",
-                                   indentstr,tag,globtype,size,data32);
+                                   indentstr, tag, globtype, size, data32);
                                break;
                        }
 
                        break;
                }
-
        }
-
 }
 
-
-
 /*   INPUT DRIVER Routines                               */
 
-
 /*
- *    Called when opening the input device.  This will submit the URB to
- *    the usb system so we start getting reports
+ * Called when opening the input device.  This will submit the URB to
+ * the usb system so we start getting reports
  */
 static int gtco_input_open(struct input_dev *inputdev)
 {
-       struct gtco *device;
-       device = inputdev->private;
+       struct gtco *device = input_get_drvdata(inputdev);
 
        device->urbinfo->dev = device->usbdev;
-       if (usb_submit_urb(device->urbinfo, GFP_KERNEL)) {
+       if (usb_submit_urb(device->urbinfo, GFP_KERNEL))
                return -EIO;
-       }
+
        return 0;
 }
 
-/**
   Called when closing the input device.  This will unlink the URB
-*/
+/*
* Called when closing the input device.  This will unlink the URB
+ */
 static void gtco_input_close(struct input_dev *inputdev)
 {
-       struct gtco *device = inputdev->private;
+       struct gtco *device = input_get_drvdata(inputdev);
 
        usb_kill_urb(device->urbinfo);
-
 }
 
 
@@ -560,19 +568,16 @@ static void gtco_input_close(struct input_dev *inputdev)
  *  placed in the struct gtco structure
  *
  */
-static void  gtco_setup_caps(struct input_dev  *inputdev)
+static void gtco_setup_caps(struct input_dev *inputdev)
 {
-       struct gtco *device = inputdev->private;
-
+       struct gtco *device = input_get_drvdata(inputdev);
 
        /* Which events */
        inputdev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC);
 
-
        /* Misc event menu block */
        inputdev->mscbit[0] = BIT(MSC_SCAN)|BIT(MSC_SERIAL)|BIT(MSC_RAW) ;
 
-
        /* Absolute values based on HID report info */
        input_set_abs_params(inputdev, ABS_X, device->min_X, device->max_X,
                             0, 0);
@@ -590,17 +595,12 @@ static void  gtco_setup_caps(struct input_dev  *inputdev)
        input_set_abs_params(inputdev, ABS_PRESSURE, device->minpressure,
                             device->maxpressure, 0, 0);
 
-
        /* Transducer */
-       input_set_abs_params(inputdev, ABS_MISC, 0,0xFF, 0, 0);
-
+       input_set_abs_params(inputdev, ABS_MISC, 0, 0xFF, 0, 0);
 }
 
-
-
 /*   USB Routines  */
 
-
 /*
  * URB callback routine.  Called when we get IRQ reports from the
  *  digitizer.
@@ -610,9 +610,7 @@ static void  gtco_setup_caps(struct input_dev  *inputdev)
  */
 static void gtco_urb_callback(struct urb *urbinfo)
 {
-
-
-       struct gtco     *device = urbinfo->context;
+       struct gtco *device = urbinfo->context;
        struct input_dev  *inputdev;
        int               rc;
        u32               val = 0;
@@ -621,19 +619,20 @@ static void gtco_urb_callback(struct urb *urbinfo)
 
        inputdev = device->inputdevice;
 
-
        /* Was callback OK? */
-       if ((urbinfo->status == -ECONNRESET ) ||
-           (urbinfo->status == -ENOENT ) ||
-           (urbinfo->status == -ESHUTDOWN )){
+       if (urbinfo->status == -ECONNRESET ||
+           urbinfo->status == -ENOENT ||
+           urbinfo->status == -ESHUTDOWN) {
 
                /* Shutdown is occurring. Return and don't queue up any more */
                return;
        }
 
-       if (urbinfo->status != 0 ) {
-               /* Some unknown error.  Hopefully temporary.  Just go and */
-               /* requeue an URB */
+       if (urbinfo->status != 0) {
+               /*
+                * Some unknown error.  Hopefully temporary. Just go and
+                * requeue an URB
+                */
                goto resubmit;
        }
 
@@ -642,10 +641,9 @@ static void gtco_urb_callback(struct urb *urbinfo)
         */
 
        /* PID dependent when we interpret the report */
-       if ((inputdev->id.product == PID_1000 )||
-           (inputdev->id.product == PID_1001 )||
-           (inputdev->id.product == PID_1002 ))
-       {
+       if (inputdev->id.product == PID_1000 ||
+           inputdev->id.product == PID_1001 ||
+           inputdev->id.product == PID_1002) {
 
                /*
                 * Switch on the report ID
@@ -653,10 +651,10 @@ static void gtco_urb_callback(struct urb *urbinfo)
                 * the report number.  We can just fall through the case
                 * statements if we start with the highest number report
                 */
-               switch(device->buffer[0]){
+               switch (device->buffer[0]) {
                case 5:
                        /* Pressure is 9 bits */
-                       val =  ((u16)(device->buffer[8]) << 1);
+                       val = ((u16)(device->buffer[8]) << 1);
                        val |= (u16)(device->buffer[7] >> 7);
                        input_report_abs(inputdev, ABS_PRESSURE,
                                         device->buffer[8]);
@@ -664,7 +662,6 @@ static void gtco_urb_callback(struct urb *urbinfo)
                        /* Mask out the Y tilt value used for pressure */
                        device->buffer[7] = (u8)((device->buffer[7]) & 0x7F);
 
-
                        /* Fall thru */
                case 4:
                        /* Tilt */
@@ -684,11 +681,10 @@ static void gtco_urb_callback(struct urb *urbinfo)
                        input_report_abs(inputdev, ABS_TILT_Y, (s32)valsigned);
 
                        /* Fall thru */
-
                case 2:
                case 3:
                        /* Convert buttons, only 5 bits possible */
-                       val = (device->buffer[5])&MASK_BUTTON;
+                       val = (device->buffer[5]) & MASK_BUTTON;
 
                        /* We don't apply any meaning to the bitmask,
                           just report */
@@ -696,132 +692,109 @@ static void gtco_urb_callback(struct urb *urbinfo)
 
                        /*  Fall thru */
                case 1:
-
                        /* All reports have X and Y coords in the same place */
-                       val = le16_to_cpu(get_unaligned((__le16 *) &(device->buffer[1])));
+                       val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[1]));
                        input_report_abs(inputdev, ABS_X, val);
 
-                       val = le16_to_cpu(get_unaligned((__le16 *) &(device->buffer[3])));
+                       val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[3]));
                        input_report_abs(inputdev, ABS_Y, val);
 
-
                        /* Ditto for proximity bit */
-                       if (device->buffer[5]& MASK_INRANGE){
-                               val = 1;
-                       }else{
-                               val=0;
-                       }
+                       val = device->buffer[5] & MASK_INRANGE ? 1 : 0;
                        input_report_abs(inputdev, ABS_DISTANCE, val);
 
-
                        /* Report 1 is an exception to how we handle buttons */
                        /* Buttons are an index, not a bitmask */
-                       if (device->buffer[0] == 1){
+                       if (device->buffer[0] == 1) {
 
-                               /* Convert buttons, 5 bit index */
-                               /* Report value of index set as one,
-                                  the rest as 0 */
-                               val = device->buffer[5]& MASK_BUTTON;
+                               /*
+                                * Convert buttons, 5 bit index
+                                * Report value of index set as one,
+                                * the rest as 0
+                                */
+                               val = device->buffer[5] & MASK_BUTTON;
                                dbg("======>>>>>>REPORT 1: val 0x%X(%d)",
-                                   val,val);
+                                   val, val);
 
                                /*
                                 * We don't apply any meaning to the button
                                 * index, just report it
                                 */
                                input_event(inputdev, EV_MSC, MSC_SERIAL, val);
-
-
                        }
-
                        break;
+
                case 7:
                        /* Menu blocks */
                        input_event(inputdev, EV_MSC, MSC_SCAN,
                                    device->buffer[1]);
-
-
                        break;
-
                }
-
-
        }
+
        /* Other pid class */
-       if ((inputdev->id.product == PID_400 )||
-           (inputdev->id.product == PID_401 ))
-       {
+       if (inputdev->id.product == PID_400 ||
+           inputdev->id.product == PID_401) {
 
                /* Report 2 */
-               if (device->buffer[0] == 2){
+               if (device->buffer[0] == 2) {
                        /* Menu blocks */
-                       input_event(inputdev, EV_MSC, MSC_SCAN,
-                                   device->buffer[1]);
+                       input_event(inputdev, EV_MSC, MSC_SCAN, device->buffer[1]);
                }
 
                /*  Report 1 */
-               if (device->buffer[0] == 1){
+               if (device->buffer[0] == 1) {
                        char buttonbyte;
 
-
                        /*  IF X max > 64K, we still a bit from the y report */
-                       if (device->max_X > 0x10000){
+                       if (device->max_X > 0x10000) {
 
-                               val = (u16)(((u16)(device->buffer[2]<<8))|((u8)(device->buffer[1])));
-                               val |= (u32)(((u8)device->buffer[3]&0x1)<< 16);
+                               val = (u16)(((u16)(device->buffer[2] << 8)) | (u8)device->buffer[1]);
+                               val |= (u32)(((u8)device->buffer[3] & 0x1) << 16);
 
                                input_report_abs(inputdev, ABS_X, val);
 
-                               le_buffer[0]  = (u8)((u8)(device->buffer[3])>>1);
-                               le_buffer[0] |= (u8)((device->buffer[3]&0x1)<<7);
-
-                               le_buffer[1]  = (u8)(device->buffer[4]>>1);
-                               le_buffer[1] |= (u8)((device->buffer[5]&0x1)<<7);
+                               le_buffer[0]  = (u8)((u8)(device->buffer[3]) >> 1);
+                               le_buffer[0] |= (u8)((device->buffer[3] & 0x1) << 7);
 
-                               val = le16_to_cpu(get_unaligned((__le16 *)(le_buffer)));
+                               le_buffer[1]  = (u8)(device->buffer[4] >> 1);
+                               le_buffer[1] |= (u8)((device->buffer[5] & 0x1) << 7);
 
+                               val = le16_to_cpu(get_unaligned((__le16 *)le_buffer));
                                input_report_abs(inputdev, ABS_Y, val);
 
-
                                /*
                                 * Shift the button byte right by one to
                                 * make it look like the standard report
                                 */
-                               buttonbyte = (device->buffer[5])>>1;
-                       }else{
+                               buttonbyte = device->buffer[5] >> 1;
+                       } else {
 
-                               val = le16_to_cpu(get_unaligned((__le16 *) (&(device->buffer[1]))));
+                               val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[1]));
                                input_report_abs(inputdev, ABS_X, val);
 
-                               val = le16_to_cpu(get_unaligned((__le16 *) (&(device->buffer[3]))));
+                               val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[3]));
                                input_report_abs(inputdev, ABS_Y, val);
 
                                buttonbyte = device->buffer[5];
-
                        }
 
-
                        /* BUTTONS and PROXIMITY */
-                       if (buttonbyte& MASK_INRANGE){
-                               val = 1;
-                       }else{
-                               val=0;
-                       }
+                       val = buttonbyte & MASK_INRANGE ? 1 : 0;
                        input_report_abs(inputdev, ABS_DISTANCE, val);
 
                        /* Convert buttons, only 4 bits possible */
-                       val = buttonbyte&0x0F;
+                       val = buttonbyte & 0x0F;
 #ifdef USE_BUTTONS
-                       for ( i=0;i<5;i++){
-                               input_report_key(inputdev, BTN_DIGI+i,val&(1<<i));
-                       }
+                       for (i = 0; i < 5; i++)
+                               input_report_key(inputdev, BTN_DIGI + i, val & (1 << i));
 #else
                        /* We don't apply any meaning to the bitmask, just report */
                        input_event(inputdev, EV_MSC, MSC_SERIAL, val);
 #endif
+
                        /* TRANSDUCER */
                        input_report_abs(inputdev, ABS_MISC, device->buffer[6]);
-
                }
        }
 
@@ -833,10 +806,8 @@ static void gtco_urb_callback(struct urb *urbinfo)
 
  resubmit:
        rc = usb_submit_urb(urbinfo, GFP_ATOMIC);
-       if (rc != 0) {
-               err("usb_submit_urb failed rc=0x%x",rc);
-       }
-
+       if (rc != 0)
+               err("usb_submit_urb failed rc=0x%x", rc);
 }
 
 /*
@@ -854,58 +825,46 @@ static int gtco_probe(struct usb_interface *usbinterface,
                      const struct usb_device_id *id)
 {
 
-       struct gtco             *device = NULL;
-       char                    path[PATHLENGTH];
-       struct input_dev        *inputdev;
+       struct gtco             *gtco;
+       struct input_dev        *input_dev;
        struct hid_descriptor   *hid_desc;
-       char                    *report;
-       int                     result=0, retry;
+       char                    *report = NULL;
+       int                     result = 0, retry;
+       int                     error;
        struct usb_endpoint_descriptor *endpoint;
 
        /* Allocate memory for device structure */
-       device = kzalloc(sizeof(struct gtco), GFP_KERNEL);
-       if (device == NULL) {
+       gtco = kzalloc(sizeof(struct gtco), GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!gtco || !input_dev) {
                err("No more memory");
-               return -ENOMEM;
+               error = -ENOMEM;
+               goto err_free_devs;
        }
 
-
-       device->inputdevice = input_allocate_device();
-       if (!device->inputdevice){
-               kfree(device);
-               err("No more memory");
-               return -ENOMEM;
-       }
-
-       /* Get pointer to the input device */
-       inputdev = device->inputdevice;
+       /* Set pointer to the input device */
+       gtco->inputdevice = input_dev;
 
        /* Save interface information */
-       device->usbdev     = usb_get_dev(interface_to_usbdev(usbinterface));
-
+       gtco->usbdev = usb_get_dev(interface_to_usbdev(usbinterface));
 
        /* Allocate some data for incoming reports */
-       device->buffer = usb_buffer_alloc(device->usbdev, REPORT_MAX_SIZE,
-                                          GFP_KERNEL, &(device->buf_dma));
-       if (!device->buffer){
-               input_free_device(device->inputdevice);
-               kfree(device);
-               err("No more memory");
-               return -ENOMEM;
+       gtco->buffer = usb_buffer_alloc(gtco->usbdev, REPORT_MAX_SIZE,
+                                       GFP_KERNEL, &gtco->buf_dma);
+       if (!gtco->buffer) {
+               err("No more memory for us buffers");
+               error = -ENOMEM;
+               goto err_free_devs;
        }
 
        /* Allocate URB for reports */
-       device->urbinfo = usb_alloc_urb(0, GFP_KERNEL);
-       if (!device->urbinfo) {
-               usb_buffer_free(device->usbdev, REPORT_MAX_SIZE,
-                               device->buffer, device->buf_dma);
-               input_free_device(device->inputdevice);
-               kfree(device);
-               err("No more memory");
+       gtco->urbinfo = usb_alloc_urb(0, GFP_KERNEL);
+       if (!gtco->urbinfo) {
+               err("Failed to allocate URB");
                return -ENOMEM;
+               goto err_free_buf;
        }
 
-
        /*
         * The endpoint is always altsetting 0, we know this since we know
         * this device only has one interrupt endpoint
@@ -913,51 +872,43 @@ static int gtco_probe(struct usb_interface *usbinterface,
        endpoint = &usbinterface->altsetting[0].endpoint[0].desc;
 
        /* Some debug */
-       dbg("gtco # interfaces: %d",usbinterface->num_altsetting);
-       dbg("num endpoints:     %d",usbinterface->cur_altsetting->desc.bNumEndpoints);
-       dbg("interface class:   %d",usbinterface->cur_altsetting->desc.bInterfaceClass);
-       dbg("endpoint: attribute:0x%x type:0x%x",endpoint->bmAttributes,endpoint->bDescriptorType);
+       dbg("gtco # interfaces: %d", usbinterface->num_altsetting);
+       dbg("num endpoints:     %d", usbinterface->cur_altsetting->desc.bNumEndpoints);
+       dbg("interface class:   %d", usbinterface->cur_altsetting->desc.bInterfaceClass);
+       dbg("endpoint: attribute:0x%x type:0x%x", endpoint->bmAttributes, endpoint->bDescriptorType);
        if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
                dbg("endpoint: we have interrupt endpoint\n");
 
-       dbg("endpoint extra len:%d ",usbinterface->altsetting[0].extralen);
-
-
+       dbg("endpoint extra len:%d ", usbinterface->altsetting[0].extralen);
 
        /*
         * Find the HID descriptor so we can find out the size of the
         * HID report descriptor
         */
        if (usb_get_extra_descriptor(usbinterface->cur_altsetting,
-                                    HID_DEVICE_TYPE,&hid_desc) != 0){
+                                    HID_DEVICE_TYPE, &hid_desc) != 0){
                err("Can't retrieve exta USB descriptor to get hid report descriptor length");
-               usb_buffer_free(device->usbdev, REPORT_MAX_SIZE,
-                               device->buffer, device->buf_dma);
-               input_free_device(device->inputdevice);
-               kfree(device);
-               return -EIO;
+               error = -EIO;
+               goto err_free_urb;
        }
 
        dbg("Extra descriptor success: type:%d  len:%d",
            hid_desc->bDescriptorType,  hid_desc->wDescriptorLength);
 
-       if (!(report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL))) {
-               usb_buffer_free(device->usbdev, REPORT_MAX_SIZE,
-                               device->buffer, device->buf_dma);
-
-               input_free_device(device->inputdevice);
-               kfree(device);
-               err("No more memory");
-               return -ENOMEM;
+       report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL);
+       if (!report) {
+               err("No more memory for report");
+               error = -ENOMEM;
+               goto err_free_urb;
        }
 
        /* Couple of tries to get reply */
-       for (retry=0;retry<3;retry++) {
-               result = usb_control_msg(device->usbdev,
-                                        usb_rcvctrlpipe(device->usbdev, 0),
+       for (retry = 0; retry < 3; retry++) {
+               result = usb_control_msg(gtco->usbdev,
+                                        usb_rcvctrlpipe(gtco->usbdev, 0),
                                         USB_REQ_GET_DESCRIPTOR,
                                         USB_RECIP_INTERFACE | USB_DIR_IN,
-                                        (REPORT_DEVICE_TYPE << 8),
+                                        REPORT_DEVICE_TYPE << 8,
                                         0, /* interface */
                                         report,
                                         hid_desc->wDescriptorLength,
@@ -969,72 +920,76 @@ static int gtco_probe(struct usb_interface *usbinterface,
 
        /* If we didn't get the report, fail */
        dbg("usb_control_msg result: :%d", result);
-       if (result != hid_desc->wDescriptorLength){
-               kfree(report);
-               usb_buffer_free(device->usbdev, REPORT_MAX_SIZE,
-                               device->buffer, device->buf_dma);
-               input_free_device(device->inputdevice);
-               kfree(device);
+       if (result != hid_desc->wDescriptorLength) {
                err("Failed to get HID Report Descriptor of size: %d",
                    hid_desc->wDescriptorLength);
-               return -EIO;
+               error = -EIO;
+               goto err_free_urb;
        }
 
-
        /* Now we parse the report */
-       parse_hid_report_descriptor(device,report,result);
+       parse_hid_report_descriptor(gtco, report, result);
 
        /* Now we delete it */
        kfree(report);
 
        /* Create a device file node */
-       usb_make_path(device->usbdev, path, PATHLENGTH);
-       sprintf(device->usbpath, "%s/input0", path);
-
+       usb_make_path(gtco->usbdev, gtco->usbpath, sizeof(gtco->usbpath));
+       strlcat(gtco->usbpath, "/input0", sizeof(gtco->usbpath));
 
        /* Set Input device functions */
-       inputdev->open     = gtco_input_open;
-       inputdev->close    = gtco_input_close;
+       input_dev->open = gtco_input_open;
+       input_dev->close = gtco_input_close;
 
        /* Set input device information */
-       inputdev->name     = "GTCO_CalComp";
-       inputdev->phys     = device->usbpath;
-       inputdev->private  = device;
+       input_dev->name = "GTCO_CalComp";
+       input_dev->phys = gtco->usbpath;
 
+       input_set_drvdata(input_dev, gtco);
 
        /* Now set up all the input device capabilities */
-       gtco_setup_caps(inputdev);
+       gtco_setup_caps(input_dev);
 
        /* Set input device required ID information */
-       usb_to_input_id(device->usbdev, &device->inputdevice->id);
-       inputdev->cdev.dev = &usbinterface->dev;
+       usb_to_input_id(gtco->usbdev, &input_dev->id);
+       input_dev->dev.parent = &usbinterface->dev;
 
        /* Setup the URB, it will be posted later on open of input device */
        endpoint = &usbinterface->altsetting[0].endpoint[0].desc;
 
-       usb_fill_int_urb(device->urbinfo,
-                        device->usbdev,
-                        usb_rcvintpipe(device->usbdev,
+       usb_fill_int_urb(gtco->urbinfo,
+                        gtco->usbdev,
+                        usb_rcvintpipe(gtco->usbdev,
                                        endpoint->bEndpointAddress),
-                        device->buffer,
+                        gtco->buffer,
                         REPORT_MAX_SIZE,
                         gtco_urb_callback,
-                        device,
+                        gtco,
                         endpoint->bInterval);
 
-       device->urbinfo->transfer_dma = device->buf_dma;
-       device->urbinfo->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
+       gtco->urbinfo->transfer_dma = gtco->buf_dma;
+       gtco->urbinfo->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-       /* Save device pointer in USB interface device */
-       usb_set_intfdata(usbinterface, device);
+       /* Save gtco pointer in USB interface gtco */
+       usb_set_intfdata(usbinterface, gtco);
 
        /* All done, now register the input device */
-       input_register_device(inputdev);
+       error = input_register_device(input_dev);
+       if (error)
+               goto err_free_urb;
 
-       info( "gtco driver created usb:  %s\n",  path);
        return 0;
 
+ err_free_urb:
+       usb_free_urb(gtco->urbinfo);
+ err_free_buf:
+       usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE,
+                       gtco->buffer, gtco->buf_dma);
+ err_free_devs:
+       kfree(report);
+       input_free_device(input_dev);
+       kfree(gtco);
+       return error;
 }
 
 /*
@@ -1044,47 +999,46 @@ static int gtco_probe(struct usb_interface *usbinterface,
  */
 static void gtco_disconnect(struct usb_interface *interface)
 {
-
        /* Grab private device ptr */
-       struct gtco    *device = usb_get_intfdata (interface);
+       struct gtco *gtco = usb_get_intfdata(interface);
 
        /* Now reverse all the registration stuff */
-       if (device) {
-               input_unregister_device(device->inputdevice);
-               usb_kill_urb(device->urbinfo);
-               usb_free_urb(device->urbinfo);
-               usb_buffer_free(device->usbdev, REPORT_MAX_SIZE,
-                               device->buffer, device->buf_dma);
-               kfree(device);
+       if (gtco) {
+               input_unregister_device(gtco->inputdevice);
+               usb_kill_urb(gtco->urbinfo);
+               usb_free_urb(gtco->urbinfo);
+               usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE,
+                               gtco->buffer, gtco->buf_dma);
+               kfree(gtco);
        }
 
        info("gtco driver disconnected");
 }
 
-
 /*   STANDARD MODULE LOAD ROUTINES  */
 
 static struct usb_driver gtco_driverinfo_table = {
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
-       .owner      = THIS_MODULE,
-#endif
-       .name       = "gtco",
-       .id_table   = gtco_usbid_table,
-       .probe      = gtco_probe,
-       .disconnect = gtco_disconnect,
+       .name           = "gtco",
+       .id_table       = gtco_usbid_table,
+       .probe          = gtco_probe,
+       .disconnect     = gtco_disconnect,
 };
+
 /*
  *  Register this module with the USB subsystem
  */
 static int __init gtco_init(void)
 {
-       int rc;
-       rc = usb_register(&gtco_driverinfo_table);
-       if (rc) {
-               err("usb_register() failed rc=0x%x", rc);
+       int error;
+
+       error = usb_register(&gtco_driverinfo_table);
+       if (error) {
+               err("usb_register() failed rc=0x%x", error);
+               return error;
        }
-       printk("GTCO usb driver version: %s",GTCO_VERSION);
-       return rc;
+
+       printk("GTCO usb driver version: %s", GTCO_VERSION);
+       return 0;
 }
 
 /*
@@ -1095,7 +1049,7 @@ static void __exit gtco_exit(void)
        usb_deregister(&gtco_driverinfo_table);
 }
 
-module_init (gtco_init);
-module_exit (gtco_exit);
+module_init(gtco_init);
+module_exit(gtco_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c
deleted file mode 100644 (file)
index aac968a..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-/******************************************************************************
- * itmtouch.c  --  Driver for ITM touchscreen panel
- *
- * 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.
- *
- * Based upon original work by Chris Collins <xfire-itmtouch@xware.cx>.
- *
- * Kudos to ITM for providing me with the datasheet for the panel,
- * even though it was a day later than I had finished writing this
- * driver.
- *
- * It has meant that I've been able to correct my interpretation of the
- * protocol packets however.
- *
- * CC -- 2003/9/29
- *
- * History
- * 1.0 & 1.1  2003 (CC) vojtech@suse.cz
- *   Original version for 2.4.x kernels
- *
- * 1.2  02/03/2005 (HCE) hc@mivu.no
- *   Complete rewrite to support Linux 2.6.10, thanks to mtouchusb.c for hints.
- *   Unfortunately no calibration support at this time.
- *
- * 1.2.1  09/03/2005 (HCE) hc@mivu.no
- *   Code cleanup and adjusting syntax to start matching kernel standards
- * 
- * 1.2.2  10/05/2006 (MJA) massad@gmail.com
- *   Flag for detecting if the screen was being touch was incorrectly 
- *   inverted, so no touch events were being detected.         
- *   
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/usb/input.h>
-
-/* only an 8 byte buffer necessary for a single packet */
-#define ITM_BUFSIZE                    8
-#define PATH_SIZE                      64
-
-#define USB_VENDOR_ID_ITMINC           0x0403
-#define USB_PRODUCT_ID_TOUCHPANEL      0xf9e9
-
-#define DRIVER_AUTHOR "Hans-Christian Egtvedt <hc@mivu.no>"
-#define DRIVER_VERSION "v1.2.2"
-#define DRIVER_DESC "USB ITM Inc Touch Panel Driver"
-#define DRIVER_LICENSE "GPL"
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE( DRIVER_LICENSE );
-
-struct itmtouch_dev {
-       struct usb_device       *usbdev; /* usb device */
-       struct input_dev        *inputdev; /* input device */
-       struct urb              *readurb; /* urb */
-       char                    rbuf[ITM_BUFSIZE]; /* data */
-       int                     users;
-       char name[128];
-       char phys[64];
-};
-
-static struct usb_device_id itmtouch_ids [] = {
-       { USB_DEVICE(USB_VENDOR_ID_ITMINC, USB_PRODUCT_ID_TOUCHPANEL) },
-       { }
-};
-
-static void itmtouch_irq(struct urb *urb)
-{
-       struct itmtouch_dev *itmtouch = urb->context;
-       unsigned char *data = urb->transfer_buffer;
-       struct input_dev *dev = itmtouch->inputdev;
-       int retval;
-
-       switch (urb->status) {
-       case 0:
-               /* success */
-               break;
-       case -ETIME:
-               /* this urb is timing out */
-               dbg("%s - urb timed out - was the device unplugged?",
-                   __FUNCTION__);
-               return;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d",
-                   __FUNCTION__, urb->status);
-               return;
-       default:
-               dbg("%s - nonzero urb status received: %d",
-                   __FUNCTION__, urb->status);
-               goto exit;
-       }
-
-       /* if pressure has been released, then don't report X/Y */
-       if (!(data[7] & 0x20)) {
-               input_report_abs(dev, ABS_X, (data[0] & 0x1F) << 7 | (data[3] & 0x7F));
-               input_report_abs(dev, ABS_Y, (data[1] & 0x1F) << 7 | (data[4] & 0x7F));
-       }
-
-       input_report_abs(dev, ABS_PRESSURE, (data[2] & 1) << 7 | (data[5] & 0x7F));
-       input_report_key(dev, BTN_TOUCH, ~data[7] & 0x20);
-       input_sync(dev);
-
-exit:
-       retval = usb_submit_urb (urb, GFP_ATOMIC);
-       if (retval)
-               printk(KERN_ERR "%s - usb_submit_urb failed with result: %d",
-                               __FUNCTION__, retval);
-}
-
-static int itmtouch_open(struct input_dev *input)
-{
-       struct itmtouch_dev *itmtouch = input->private;
-
-       itmtouch->readurb->dev = itmtouch->usbdev;
-
-       if (usb_submit_urb(itmtouch->readurb, GFP_KERNEL))
-               return -EIO;
-
-       return 0;
-}
-
-static void itmtouch_close(struct input_dev *input)
-{
-       struct itmtouch_dev *itmtouch = input->private;
-
-       usb_kill_urb(itmtouch->readurb);
-}
-
-static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-       struct itmtouch_dev *itmtouch;
-       struct input_dev *input_dev;
-       struct usb_host_interface *interface;
-       struct usb_endpoint_descriptor *endpoint;
-       struct usb_device *udev = interface_to_usbdev(intf);
-       unsigned int pipe;
-       unsigned int maxp;
-
-       interface = intf->cur_altsetting;
-       endpoint = &interface->endpoint[0].desc;
-
-       itmtouch = kzalloc(sizeof(struct itmtouch_dev), GFP_KERNEL);
-       input_dev = input_allocate_device();
-       if (!itmtouch || !input_dev) {
-               err("%s - Out of memory.", __FUNCTION__);
-               goto fail;
-       }
-
-       itmtouch->usbdev = udev;
-       itmtouch->inputdev = input_dev;
-
-       if (udev->manufacturer)
-               strlcpy(itmtouch->name, udev->manufacturer, sizeof(itmtouch->name));
-
-       if (udev->product) {
-               if (udev->manufacturer)
-                       strlcat(itmtouch->name, " ", sizeof(itmtouch->name));
-               strlcat(itmtouch->name, udev->product, sizeof(itmtouch->name));
-       }
-
-       if (!strlen(itmtouch->name))
-               sprintf(itmtouch->name, "USB ITM touchscreen");
-
-       usb_make_path(udev, itmtouch->phys, sizeof(itmtouch->phys));
-       strlcpy(itmtouch->phys, "/input0", sizeof(itmtouch->phys));
-
-       input_dev->name = itmtouch->name;
-       input_dev->phys = itmtouch->phys;
-       usb_to_input_id(udev, &input_dev->id);
-       input_dev->cdev.dev = &intf->dev;
-       input_dev->private = itmtouch;
-
-       input_dev->open = itmtouch_open;
-       input_dev->close = itmtouch_close;
-
-       input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-       input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
-       input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-
-       /* device limits */
-       /* as specified by the ITM datasheet, X and Y are 12bit,
-        * Z (pressure) is 8 bit. However, the fields are defined up
-        * to 14 bits for future possible expansion.
-        */
-       input_set_abs_params(input_dev, ABS_X, 0, 0x0FFF, 2, 0);
-       input_set_abs_params(input_dev, ABS_Y, 0, 0x0FFF, 2, 0);
-       input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xFF, 2, 0);
-
-       /* initialise the URB so we can read from the transport stream */
-       pipe = usb_rcvintpipe(itmtouch->usbdev, endpoint->bEndpointAddress);
-       maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
-
-       if (maxp > ITM_BUFSIZE)
-               maxp = ITM_BUFSIZE;
-
-       itmtouch->readurb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!itmtouch->readurb) {
-               dbg("%s - usb_alloc_urb failed: itmtouch->readurb", __FUNCTION__);
-               goto fail;
-       }
-
-       usb_fill_int_urb(itmtouch->readurb, itmtouch->usbdev, pipe, itmtouch->rbuf,
-                        maxp, itmtouch_irq, itmtouch, endpoint->bInterval);
-
-       input_register_device(itmtouch->inputdev);
-
-       usb_set_intfdata(intf, itmtouch);
-
-       return 0;
-
- fail: input_free_device(input_dev);
-       kfree(itmtouch);
-       return -ENOMEM;
-}
-
-static void itmtouch_disconnect(struct usb_interface *intf)
-{
-       struct itmtouch_dev *itmtouch = usb_get_intfdata(intf);
-
-       usb_set_intfdata(intf, NULL);
-
-       if (itmtouch) {
-               input_unregister_device(itmtouch->inputdev);
-               usb_kill_urb(itmtouch->readurb);
-               usb_free_urb(itmtouch->readurb);
-               kfree(itmtouch);
-       }
-}
-
-MODULE_DEVICE_TABLE(usb, itmtouch_ids);
-
-static struct usb_driver itmtouch_driver = {
-       .name =         "itmtouch",
-       .probe =        itmtouch_probe,
-       .disconnect =   itmtouch_disconnect,
-       .id_table =     itmtouch_ids,
-};
-
-static int __init itmtouch_init(void)
-{
-       info(DRIVER_DESC " " DRIVER_VERSION);
-       info(DRIVER_AUTHOR);
-       return usb_register(&itmtouch_driver);
-}
-
-static void __exit itmtouch_exit(void)
-{
-       usb_deregister(&itmtouch_driver);
-}
-
-module_init(itmtouch_init);
-module_exit(itmtouch_exit);
index fedbcb1..c4781b9 100644 (file)
@@ -100,7 +100,7 @@ MODULE_DEVICE_TABLE(usb, kbtab_ids);
 
 static int kbtab_open(struct input_dev *dev)
 {
-       struct kbtab *kbtab = dev->private;
+       struct kbtab *kbtab = input_get_drvdata(dev);
 
        kbtab->irq->dev = kbtab->usbdev;
        if (usb_submit_urb(kbtab->irq, GFP_KERNEL))
@@ -111,7 +111,7 @@ static int kbtab_open(struct input_dev *dev)
 
 static void kbtab_close(struct input_dev *dev)
 {
-       struct kbtab *kbtab = dev->private;
+       struct kbtab *kbtab = input_get_drvdata(dev);
 
        usb_kill_urb(kbtab->irq);
 }
@@ -122,6 +122,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
        struct usb_endpoint_descriptor *endpoint;
        struct kbtab *kbtab;
        struct input_dev *input_dev;
+       int error = -ENOMEM;
 
        kbtab = kzalloc(sizeof(struct kbtab), GFP_KERNEL);
        input_dev = input_allocate_device();
@@ -145,8 +146,9 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
        input_dev->name = "KB Gear Tablet";
        input_dev->phys = kbtab->phys;
        usb_to_input_id(dev, &input_dev->id);
-       input_dev->cdev.dev = &intf->dev;
-       input_dev->private = kbtab;
+       input_dev->dev.parent = &intf->dev;
+
+       input_set_drvdata(input_dev, kbtab);
 
        input_dev->open = kbtab_open;
        input_dev->close = kbtab_close;
@@ -168,15 +170,19 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
        kbtab->irq->transfer_dma = kbtab->data_dma;
        kbtab->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-       input_register_device(kbtab->dev);
+       error = input_register_device(kbtab->dev);
+       if (error)
+               goto fail3;
 
        usb_set_intfdata(intf, kbtab);
+
        return 0;
 
-fail2: usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma);
-fail1: input_free_device(input_dev);
+ fail3:        usb_free_urb(kbtab->irq);
+ fail2:        usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma);
+ fail1:        input_free_device(input_dev);
        kfree(kbtab);
-       return -ENOMEM;
+       return error;
 }
 
 static void kbtab_disconnect(struct usb_interface *intf)
index 98bd323..1bffc9f 100644 (file)
@@ -394,7 +394,7 @@ resubmit:
 
 static int keyspan_open(struct input_dev *dev)
 {
-       struct usb_keyspan *remote = dev->private;
+       struct usb_keyspan *remote = input_get_drvdata(dev);
 
        remote->irq_urb->dev = remote->udev;
        if (usb_submit_urb(remote->irq_urb, GFP_KERNEL))
@@ -405,7 +405,7 @@ static int keyspan_open(struct input_dev *dev)
 
 static void keyspan_close(struct input_dev *dev)
 {
-       struct usb_keyspan *remote = dev->private;
+       struct usb_keyspan *remote = input_get_drvdata(dev);
 
        usb_kill_urb(remote->irq_urb);
 }
@@ -437,7 +437,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
        struct usb_endpoint_descriptor *endpoint;
        struct usb_keyspan *remote;
        struct input_dev *input_dev;
-       int i, retval;
+       int i, error;
 
        endpoint = keyspan_get_in_endpoint(interface->cur_altsetting);
        if (!endpoint)
@@ -446,7 +446,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
        remote = kzalloc(sizeof(*remote), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!remote || !input_dev) {
-               retval = -ENOMEM;
+               error = -ENOMEM;
                goto fail1;
        }
 
@@ -458,19 +458,19 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
 
        remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma);
        if (!remote->in_buffer) {
-               retval = -ENOMEM;
+               error = -ENOMEM;
                goto fail1;
        }
 
        remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!remote->irq_urb) {
-               retval = -ENOMEM;
+               error = -ENOMEM;
                goto fail2;
        }
 
-       retval = keyspan_setup(udev);
-       if (retval) {
-               retval = -ENODEV;
+       error = keyspan_setup(udev);
+       if (error) {
+               error = -ENODEV;
                goto fail3;
        }
 
@@ -495,14 +495,15 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
        input_dev->name = remote->name;
        input_dev->phys = remote->phys;
        usb_to_input_id(udev, &input_dev->id);
-       input_dev->cdev.dev = &interface->dev;
+       input_dev->dev.parent = &interface->dev;
 
        input_dev->evbit[0] = BIT(EV_KEY);              /* We will only report KEY events. */
        for (i = 0; i < ARRAY_SIZE(keyspan_key_table); i++)
                if (keyspan_key_table[i] != KEY_RESERVED)
                        set_bit(keyspan_key_table[i], input_dev->keybit);
 
-       input_dev->private = remote;
+       input_set_drvdata(input_dev, remote);
+
        input_dev->open = keyspan_open;
        input_dev->close = keyspan_close;
 
@@ -517,7 +518,9 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
        remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
        /* we can register the device now, as it is ready */
-       input_register_device(remote->input);
+       error = input_register_device(remote->input);
+       if (error)
+               goto fail3;
 
        /* save our data pointer in this interface device */
        usb_set_intfdata(interface, remote);
@@ -529,7 +532,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
  fail1:        kfree(remote);
        input_free_device(input_dev);
 
-       return retval;
+       return error;
 }
 
 /*
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c
deleted file mode 100644 (file)
index 92c4e07..0000000
+++ /dev/null
@@ -1,332 +0,0 @@
-/******************************************************************************
- * mtouchusb.c  --  Driver for Microtouch (Now 3M) USB Touchscreens
- *
- * 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.
- *
- * Based upon original work by Radoslaw Garbacz (usb-support@ite.pl)
- *  (http://freshmeat.net/projects/3mtouchscreendriver)
- *
- * History
- *
- *  0.3 & 0.4  2002 (TEJ) tejohnson@yahoo.com
- *    Updated to 2.4.18, then 2.4.19
- *    Old version still relied on stealing a minor
- *
- *  0.5  02/26/2004 (TEJ) tejohnson@yahoo.com
- *    Complete rewrite using Linux Input in 2.6.3
- *    Unfortunately no calibration support at this time
- *
- *  1.4 04/25/2004 (TEJ) tejohnson@yahoo.com
- *    Changed reset from standard USB dev reset to vendor reset
- *    Changed data sent to host from compensated to raw coordinates
- *    Eliminated vendor/product module params
- *    Performed multiple successful tests with an EXII-5010UC
- *
- *  1.5 02/27/2005 ddstreet@ieee.org
- *    Added module parameter to select raw or hw-calibrated coordinate reporting
- *
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/usb/input.h>
-
-#define MTOUCHUSB_MIN_XC                0x0
-#define MTOUCHUSB_MAX_RAW_XC            0x4000
-#define MTOUCHUSB_MAX_CALIB_XC          0xffff
-#define MTOUCHUSB_XC_FUZZ               0x0
-#define MTOUCHUSB_XC_FLAT               0x0
-#define MTOUCHUSB_MIN_YC                0x0
-#define MTOUCHUSB_MAX_RAW_YC            0x4000
-#define MTOUCHUSB_MAX_CALIB_YC          0xffff
-#define MTOUCHUSB_YC_FUZZ               0x0
-#define MTOUCHUSB_YC_FLAT               0x0
-
-#define MTOUCHUSB_ASYNC_REPORT          1
-#define MTOUCHUSB_RESET                 7
-#define MTOUCHUSB_REPORT_DATA_SIZE      11
-#define MTOUCHUSB_REQ_CTRLLR_ID         10
-
-#define MTOUCHUSB_GET_RAW_XC(data)      (data[8]<<8 | data[7])
-#define MTOUCHUSB_GET_CALIB_XC(data)    (data[4]<<8 | data[3])
-#define MTOUCHUSB_GET_RAW_YC(data)      (data[10]<<8 | data[9])
-#define MTOUCHUSB_GET_CALIB_YC(data)    (data[6]<<8 | data[5])
-#define MTOUCHUSB_GET_XC(data)          (raw_coordinates ? \
-                                         MTOUCHUSB_GET_RAW_XC(data) : \
-                                         MTOUCHUSB_GET_CALIB_XC(data))
-#define MTOUCHUSB_GET_YC(data)          (raw_coordinates ? \
-                                         MTOUCHUSB_GET_RAW_YC(data) : \
-                                         MTOUCHUSB_GET_CALIB_YC(data))
-#define MTOUCHUSB_GET_TOUCHED(data)     ((data[2] & 0x40) ? 1:0)
-
-#define DRIVER_VERSION "v1.5"
-#define DRIVER_AUTHOR "Todd E. Johnson, tejohnson@yahoo.com"
-#define DRIVER_DESC "3M USB Touchscreen Driver"
-#define DRIVER_LICENSE "GPL"
-
-static int raw_coordinates = 1;
-
-module_param(raw_coordinates, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(raw_coordinates, "report raw coordinate values (y, default) or hardware-calibrated coordinate values (n)");
-
-struct mtouch_usb {
-       unsigned char *data;
-       dma_addr_t data_dma;
-       struct urb *irq;
-       struct usb_device *udev;
-       struct input_dev *input;
-       char name[128];
-       char phys[64];
-};
-
-static struct usb_device_id mtouchusb_devices[] = {
-       { USB_DEVICE(0x0596, 0x0001) },
-       { }
-};
-
-static void mtouchusb_irq(struct urb *urb)
-{
-       struct mtouch_usb *mtouch = urb->context;
-       int retval;
-
-       switch (urb->status) {
-       case 0:
-               /* success */
-               break;
-       case -ETIME:
-               /* this urb is timing out */
-               dbg("%s - urb timed out - was the device unplugged?",
-                   __FUNCTION__);
-               return;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d",
-                   __FUNCTION__, urb->status);
-               return;
-       default:
-               dbg("%s - nonzero urb status received: %d",
-                   __FUNCTION__, urb->status);
-               goto exit;
-       }
-
-       input_report_key(mtouch->input, BTN_TOUCH,
-                        MTOUCHUSB_GET_TOUCHED(mtouch->data));
-       input_report_abs(mtouch->input, ABS_X, MTOUCHUSB_GET_XC(mtouch->data));
-       input_report_abs(mtouch->input, ABS_Y,
-                        (raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC)
-                        - MTOUCHUSB_GET_YC(mtouch->data));
-       input_sync(mtouch->input);
-
-exit:
-       retval = usb_submit_urb(urb, GFP_ATOMIC);
-       if (retval)
-               err("%s - usb_submit_urb failed with result: %d",
-                   __FUNCTION__, retval);
-}
-
-static int mtouchusb_open(struct input_dev *input)
-{
-       struct mtouch_usb *mtouch = input->private;
-
-       mtouch->irq->dev = mtouch->udev;
-
-       if (usb_submit_urb(mtouch->irq, GFP_ATOMIC))
-               return -EIO;
-
-       return 0;
-}
-
-static void mtouchusb_close(struct input_dev *input)
-{
-       struct mtouch_usb *mtouch = input->private;
-
-       usb_kill_urb(mtouch->irq);
-}
-
-static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *mtouch)
-{
-       dbg("%s - called", __FUNCTION__);
-
-       mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_DATA_SIZE,
-                                       GFP_ATOMIC, &mtouch->data_dma);
-
-       if (!mtouch->data)
-               return -1;
-
-       return 0;
-}
-
-static void mtouchusb_free_buffers(struct usb_device *udev, struct mtouch_usb *mtouch)
-{
-       dbg("%s - called", __FUNCTION__);
-
-       if (mtouch->data)
-               usb_buffer_free(udev, MTOUCHUSB_REPORT_DATA_SIZE,
-                               mtouch->data, mtouch->data_dma);
-}
-
-static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-       struct mtouch_usb *mtouch;
-       struct input_dev *input_dev;
-       struct usb_host_interface *interface;
-       struct usb_endpoint_descriptor *endpoint;
-       struct usb_device *udev = interface_to_usbdev(intf);
-       int nRet;
-
-       dbg("%s - called", __FUNCTION__);
-
-       dbg("%s - setting interface", __FUNCTION__);
-       interface = intf->cur_altsetting;
-
-       dbg("%s - setting endpoint", __FUNCTION__);
-       endpoint = &interface->endpoint[0].desc;
-
-       mtouch = kzalloc(sizeof(struct mtouch_usb), GFP_KERNEL);
-       input_dev = input_allocate_device();
-       if (!mtouch || !input_dev) {
-               err("%s - Out of memory.", __FUNCTION__);
-               goto fail1;
-       }
-
-       dbg("%s - allocating buffers", __FUNCTION__);
-       if (mtouchusb_alloc_buffers(udev, mtouch))
-               goto fail2;
-
-       mtouch->udev = udev;
-       mtouch->input = input_dev;
-
-       if (udev->manufacturer)
-               strlcpy(mtouch->name, udev->manufacturer, sizeof(mtouch->name));
-
-       if (udev->product) {
-               if (udev->manufacturer)
-                       strlcat(mtouch->name, " ", sizeof(mtouch->name));
-               strlcat(mtouch->name, udev->product, sizeof(mtouch->name));
-       }
-
-       if (!strlen(mtouch->name))
-               snprintf(mtouch->name, sizeof(mtouch->name),
-                       "USB Touchscreen %04x:%04x",
-                       le16_to_cpu(udev->descriptor.idVendor),
-                       le16_to_cpu(udev->descriptor.idProduct));
-
-       usb_make_path(udev, mtouch->phys, sizeof(mtouch->phys));
-       strlcpy(mtouch->phys, "/input0", sizeof(mtouch->phys));
-
-       input_dev->name = mtouch->name;
-       input_dev->phys = mtouch->phys;
-       usb_to_input_id(udev, &input_dev->id);
-       input_dev->cdev.dev = &intf->dev;
-       input_dev->private = mtouch;
-
-       input_dev->open = mtouchusb_open;
-       input_dev->close = mtouchusb_close;
-
-       input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-       input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-       input_set_abs_params(input_dev, ABS_X, MTOUCHUSB_MIN_XC,
-               raw_coordinates ? MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC,
-                               MTOUCHUSB_XC_FUZZ, MTOUCHUSB_XC_FLAT);
-       input_set_abs_params(input_dev, ABS_Y, MTOUCHUSB_MIN_YC,
-               raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC,
-               MTOUCHUSB_YC_FUZZ, MTOUCHUSB_YC_FLAT);
-
-       nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0),
-                              MTOUCHUSB_RESET,
-                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                              1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
-       dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d",
-           __FUNCTION__, nRet);
-
-       dbg("%s - usb_alloc_urb: mtouch->irq", __FUNCTION__);
-       mtouch->irq = usb_alloc_urb(0, GFP_KERNEL);
-       if (!mtouch->irq) {
-               dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__);
-               goto fail2;
-       }
-
-       dbg("%s - usb_fill_int_urb", __FUNCTION__);
-       usb_fill_int_urb(mtouch->irq, mtouch->udev,
-                        usb_rcvintpipe(mtouch->udev, 0x81),
-                        mtouch->data, MTOUCHUSB_REPORT_DATA_SIZE,
-                        mtouchusb_irq, mtouch, endpoint->bInterval);
-
-       dbg("%s - input_register_device", __FUNCTION__);
-       input_register_device(mtouch->input);
-
-       nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0),
-                              MTOUCHUSB_ASYNC_REPORT,
-                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                              1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
-       dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
-           __FUNCTION__, nRet);
-
-       usb_set_intfdata(intf, mtouch);
-       return 0;
-
-fail2: mtouchusb_free_buffers(udev, mtouch);
-fail1: input_free_device(input_dev);
-       kfree(mtouch);
-       return -ENOMEM;
-}
-
-static void mtouchusb_disconnect(struct usb_interface *intf)
-{
-       struct mtouch_usb *mtouch = usb_get_intfdata(intf);
-
-       dbg("%s - called", __FUNCTION__);
-       usb_set_intfdata(intf, NULL);
-       if (mtouch) {
-               dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__);
-               usb_kill_urb(mtouch->irq);
-               input_unregister_device(mtouch->input);
-               usb_free_urb(mtouch->irq);
-               mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch);
-               kfree(mtouch);
-       }
-}
-
-MODULE_DEVICE_TABLE(usb, mtouchusb_devices);
-
-static struct usb_driver mtouchusb_driver = {
-       .name           = "mtouchusb",
-       .probe          = mtouchusb_probe,
-       .disconnect     = mtouchusb_disconnect,
-       .id_table       = mtouchusb_devices,
-};
-
-static int __init mtouchusb_init(void)
-{
-       dbg("%s - called", __FUNCTION__);
-       return usb_register(&mtouchusb_driver);
-}
-
-static void __exit mtouchusb_cleanup(void)
-{
-       dbg("%s - called", __FUNCTION__);
-       usb_deregister(&mtouchusb_driver);
-}
-
-module_init(mtouchusb_init);
-module_exit(mtouchusb_cleanup);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
index fea97e5..4f93a76 100644 (file)
@@ -252,7 +252,7 @@ static void powermate_pulse_led(struct powermate_device *pm, int static_brightne
 static int powermate_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int _value)
 {
        unsigned int command = (unsigned int)_value;
-       struct powermate_device *pm = dev->private;
+       struct powermate_device *pm = input_get_drvdata(dev);
 
        if (type == EV_MSC && code == MSC_PULSELED){
                /*
@@ -308,7 +308,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
        struct powermate_device *pm;
        struct input_dev *input_dev;
        int pipe, maxp;
-       int err = -ENOMEM;
+       int error = -ENOMEM;
 
        interface = intf->cur_altsetting;
        endpoint = &interface->endpoint[0].desc;
@@ -359,8 +359,9 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
 
        input_dev->phys = pm->phys;
        usb_to_input_id(udev, &input_dev->id);
-       input_dev->cdev.dev = &intf->dev;
-       input_dev->private = pm;
+       input_dev->dev.parent = &intf->dev;
+
+       input_set_drvdata(input_dev, pm);
 
        input_dev->event = powermate_input_event;
 
@@ -387,11 +388,14 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
 
        /* register our interrupt URB with the USB system */
        if (usb_submit_urb(pm->irq, GFP_KERNEL)) {
-               err = -EIO;
+               error = -EIO;
                goto fail4;
        }
 
-       input_register_device(pm->input);
+       error = input_register_device(pm->input);
+       if (error)
+               goto fail5;
+
 
        /* force an update of everything */
        pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS;
@@ -400,12 +404,13 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
        usb_set_intfdata(intf, pm);
        return 0;
 
-fail4: usb_free_urb(pm->config);
-fail3: usb_free_urb(pm->irq);
-fail2: powermate_free_buffers(udev, pm);
-fail1: input_free_device(input_dev);
+ fail5:        usb_kill_urb(pm->irq);
+ fail4:        usb_free_urb(pm->config);
+ fail3:        usb_free_urb(pm->irq);
+ fail2:        powermate_free_buffers(udev, pm);
+ fail1:        input_free_device(input_dev);
        kfree(pm);
-       return err;
+       return error;
 }
 
 /* Called when a USB device we've accepted ownership of is removed */
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c
deleted file mode 100644 (file)
index 2a314b0..0000000
+++ /dev/null
@@ -1,392 +0,0 @@
-/******************************************************************************
- * touchkitusb.c  --  Driver for eGalax TouchKit USB Touchscreens
- *
- * Copyright (C) 2004-2005 by Daniel Ritz <daniel.ritz@gmx.ch>
- * Copyright (C) by Todd E. Johnson (mtouchusb.c)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Based upon mtouchusb.c
- *
- *****************************************************************************/
-
-//#define DEBUG
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/usb/input.h>
-
-#define TOUCHKIT_MIN_XC                        0x0
-#define TOUCHKIT_MAX_XC                        0x07ff
-#define TOUCHKIT_XC_FUZZ               0x0
-#define TOUCHKIT_XC_FLAT               0x0
-#define TOUCHKIT_MIN_YC                        0x0
-#define TOUCHKIT_MAX_YC                        0x07ff
-#define TOUCHKIT_YC_FUZZ               0x0
-#define TOUCHKIT_YC_FLAT               0x0
-#define TOUCHKIT_REPORT_DATA_SIZE      16
-
-#define TOUCHKIT_DOWN                  0x01
-
-#define TOUCHKIT_PKT_TYPE_MASK         0xFE
-#define TOUCHKIT_PKT_TYPE_REPT         0x80
-#define TOUCHKIT_PKT_TYPE_DIAG         0x0A
-
-#define DRIVER_VERSION                 "v0.1"
-#define DRIVER_AUTHOR                  "Daniel Ritz <daniel.ritz@gmx.ch>"
-#define DRIVER_DESC                    "eGalax TouchKit USB HID Touchscreen Driver"
-
-static int swap_xy;
-module_param(swap_xy, bool, 0644);
-MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped.");
-
-struct touchkit_usb {
-       unsigned char *data;
-       dma_addr_t data_dma;
-       char buffer[TOUCHKIT_REPORT_DATA_SIZE];
-       int buf_len;
-       struct urb *irq;
-       struct usb_device *udev;
-       struct input_dev *input;
-       char name[128];
-       char phys[64];
-};
-
-static struct usb_device_id touchkit_devices[] = {
-       {USB_DEVICE(0x3823, 0x0001)},
-       {USB_DEVICE(0x0123, 0x0001)},
-       {USB_DEVICE(0x0eef, 0x0001)},
-       {USB_DEVICE(0x0eef, 0x0002)},
-       {}
-};
-
-/* helpers to read the data */
-static inline int touchkit_get_touched(char *data)
-{
-       return (data[0] & TOUCHKIT_DOWN) ? 1 : 0;
-}
-
-static inline int touchkit_get_x(char *data)
-{
-       return ((data[3] & 0x0F) << 7) | (data[4] & 0x7F);
-}
-
-static inline int touchkit_get_y(char *data)
-{
-       return ((data[1] & 0x0F) << 7) | (data[2] & 0x7F);
-}
-
-
-/* processes one input packet. */
-static void touchkit_process_pkt(struct touchkit_usb *touchkit, char *pkt)
-{
-       int x, y;
-
-       /* only process report packets */
-       if ((pkt[0] & TOUCHKIT_PKT_TYPE_MASK) != TOUCHKIT_PKT_TYPE_REPT)
-               return;
-
-       if (swap_xy) {
-               y = touchkit_get_x(pkt);
-               x = touchkit_get_y(pkt);
-       } else {
-               x = touchkit_get_x(pkt);
-               y = touchkit_get_y(pkt);
-       }
-
-       input_report_key(touchkit->input, BTN_TOUCH, touchkit_get_touched(pkt));
-       input_report_abs(touchkit->input, ABS_X, x);
-       input_report_abs(touchkit->input, ABS_Y, y);
-       input_sync(touchkit->input);
-}
-
-
-static int touchkit_get_pkt_len(char *buf)
-{
-       switch (buf[0] & TOUCHKIT_PKT_TYPE_MASK) {
-       case TOUCHKIT_PKT_TYPE_REPT:
-               return 5;
-
-       case TOUCHKIT_PKT_TYPE_DIAG:
-               return buf[1] + 2;
-       }
-
-       return 0;
-}
-
-static void touchkit_process(struct touchkit_usb *touchkit, int len)
-{
-       char *buffer;
-       int pkt_len, buf_len, pos;
-
-       /* if the buffer contains data, append */
-       if (unlikely(touchkit->buf_len)) {
-               int tmp;
-
-               /* if only 1 byte in buffer, add another one to get length */
-               if (touchkit->buf_len == 1)
-                       touchkit->buffer[1] = touchkit->data[0];
-
-               pkt_len = touchkit_get_pkt_len(touchkit->buffer);
-
-               /* unknown packet: drop everything */
-               if (!pkt_len)
-                       return;
-
-               /* append, process */
-               tmp = pkt_len - touchkit->buf_len;
-               memcpy(touchkit->buffer + touchkit->buf_len, touchkit->data, tmp);
-               touchkit_process_pkt(touchkit, touchkit->buffer);
-
-               buffer = touchkit->data + tmp;
-               buf_len = len - tmp;
-       } else {
-               buffer = touchkit->data;
-               buf_len = len;
-       }
-
-       /* only one byte left in buffer */
-       if (unlikely(buf_len == 1)) {
-               touchkit->buffer[0] = buffer[0];
-               touchkit->buf_len = 1;
-               return;
-       }
-
-       /* loop over the buffer */
-       pos = 0;
-       while (pos < buf_len) {
-               /* get packet len */
-               pkt_len = touchkit_get_pkt_len(buffer + pos);
-
-               /* unknown packet: drop everything */
-               if (unlikely(!pkt_len))
-                       return;
-
-               /* full packet: process */
-               if (likely(pkt_len <= buf_len)) {
-                       touchkit_process_pkt(touchkit, buffer + pos);
-               } else {
-                       /* incomplete packet: save in buffer */
-                       memcpy(touchkit->buffer, buffer + pos, buf_len - pos);
-                       touchkit->buf_len = buf_len - pos;
-               }
-               pos += pkt_len;
-       }
-}
-
-
-static void touchkit_irq(struct urb *urb)
-{
-       struct touchkit_usb *touchkit = urb->context;
-       int retval;
-
-       switch (urb->status) {
-       case 0:
-               /* success */
-               break;
-       case -ETIME:
-               /* this urb is timing out */
-               dbg("%s - urb timed out - was the device unplugged?",
-                   __FUNCTION__);
-               return;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d",
-                   __FUNCTION__, urb->status);
-               return;
-       default:
-               dbg("%s - nonzero urb status received: %d",
-                   __FUNCTION__, urb->status);
-               goto exit;
-       }
-
-       touchkit_process(touchkit, urb->actual_length);
-
-exit:
-       retval = usb_submit_urb(urb, GFP_ATOMIC);
-       if (retval)
-               err("%s - usb_submit_urb failed with result: %d",
-                   __FUNCTION__, retval);
-}
-
-static int touchkit_open(struct input_dev *input)
-{
-       struct touchkit_usb *touchkit = input->private;
-
-       touchkit->irq->dev = touchkit->udev;
-
-       if (usb_submit_urb(touchkit->irq, GFP_ATOMIC))
-               return -EIO;
-
-       return 0;
-}
-
-static void touchkit_close(struct input_dev *input)
-{
-       struct touchkit_usb *touchkit = input->private;
-
-       usb_kill_urb(touchkit->irq);
-}
-
-static int touchkit_alloc_buffers(struct usb_device *udev,
-                                 struct touchkit_usb *touchkit)
-{
-       touchkit->data = usb_buffer_alloc(udev, TOUCHKIT_REPORT_DATA_SIZE,
-                                         GFP_ATOMIC, &touchkit->data_dma);
-
-       if (!touchkit->data)
-               return -1;
-
-       return 0;
-}
-
-static void touchkit_free_buffers(struct usb_device *udev,
-                                 struct touchkit_usb *touchkit)
-{
-       if (touchkit->data)
-               usb_buffer_free(udev, TOUCHKIT_REPORT_DATA_SIZE,
-                               touchkit->data, touchkit->data_dma);
-}
-
-static int touchkit_probe(struct usb_interface *intf,
-                         const struct usb_device_id *id)
-{
-       struct touchkit_usb *touchkit;
-       struct input_dev *input_dev;
-       struct usb_host_interface *interface;
-       struct usb_endpoint_descriptor *endpoint;
-       struct usb_device *udev = interface_to_usbdev(intf);
-
-       interface = intf->cur_altsetting;
-       endpoint = &interface->endpoint[0].desc;
-
-       touchkit = kzalloc(sizeof(struct touchkit_usb), GFP_KERNEL);
-       input_dev = input_allocate_device();
-       if (!touchkit || !input_dev)
-               goto out_free;
-
-       if (touchkit_alloc_buffers(udev, touchkit))
-               goto out_free;
-
-       touchkit->irq = usb_alloc_urb(0, GFP_KERNEL);
-       if (!touchkit->irq) {
-               dbg("%s - usb_alloc_urb failed: touchkit->irq", __FUNCTION__);
-               goto out_free_buffers;
-       }
-
-       touchkit->udev = udev;
-       touchkit->input = input_dev;
-
-       if (udev->manufacturer)
-               strlcpy(touchkit->name, udev->manufacturer, sizeof(touchkit->name));
-
-       if (udev->product) {
-               if (udev->manufacturer)
-                       strlcat(touchkit->name, " ", sizeof(touchkit->name));
-               strlcat(touchkit->name, udev->product, sizeof(touchkit->name));
-       }
-
-       if (!strlen(touchkit->name))
-               snprintf(touchkit->name, sizeof(touchkit->name),
-                       "USB Touchscreen %04x:%04x",
-                        le16_to_cpu(udev->descriptor.idVendor),
-                        le16_to_cpu(udev->descriptor.idProduct));
-
-       usb_make_path(udev, touchkit->phys, sizeof(touchkit->phys));
-       strlcpy(touchkit->phys, "/input0", sizeof(touchkit->phys));
-
-       input_dev->name = touchkit->name;
-       input_dev->phys = touchkit->phys;
-       usb_to_input_id(udev, &input_dev->id);
-       input_dev->cdev.dev = &intf->dev;
-       input_dev->private = touchkit;
-       input_dev->open = touchkit_open;
-       input_dev->close = touchkit_close;
-
-       input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-       input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-       input_set_abs_params(input_dev, ABS_X, TOUCHKIT_MIN_XC, TOUCHKIT_MAX_XC,
-                               TOUCHKIT_XC_FUZZ, TOUCHKIT_XC_FLAT);
-       input_set_abs_params(input_dev, ABS_Y, TOUCHKIT_MIN_YC, TOUCHKIT_MAX_YC,
-                               TOUCHKIT_YC_FUZZ, TOUCHKIT_YC_FLAT);
-
-       usb_fill_int_urb(touchkit->irq, touchkit->udev,
-                        usb_rcvintpipe(touchkit->udev, 0x81),
-                        touchkit->data, TOUCHKIT_REPORT_DATA_SIZE,
-                        touchkit_irq, touchkit, endpoint->bInterval);
-
-       touchkit->irq->transfer_dma = touchkit->data_dma;
-       touchkit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-       input_register_device(touchkit->input);
-
-       usb_set_intfdata(intf, touchkit);
-       return 0;
-
-out_free_buffers:
-       touchkit_free_buffers(udev, touchkit);
-out_free:
-       input_free_device(input_dev);
-       kfree(touchkit);
-       return -ENOMEM;
-}
-
-static void touchkit_disconnect(struct usb_interface *intf)
-{
-       struct touchkit_usb *touchkit = usb_get_intfdata(intf);
-
-       dbg("%s - called", __FUNCTION__);
-
-       if (!touchkit)
-               return;
-
-       dbg("%s - touchkit is initialized, cleaning up", __FUNCTION__);
-       usb_set_intfdata(intf, NULL);
-       usb_kill_urb(touchkit->irq);
-       input_unregister_device(touchkit->input);
-       usb_free_urb(touchkit->irq);
-       touchkit_free_buffers(interface_to_usbdev(intf), touchkit);
-       kfree(touchkit);
-}
-
-MODULE_DEVICE_TABLE(usb, touchkit_devices);
-
-static struct usb_driver touchkit_driver = {
-       .name           = "touchkitusb",
-       .probe          = touchkit_probe,
-       .disconnect     = touchkit_disconnect,
-       .id_table       = touchkit_devices,
-};
-
-static int __init touchkit_init(void)
-{
-       return usb_register(&touchkit_driver);
-}
-
-static void __exit touchkit_cleanup(void)
-{
-       usb_deregister(&touchkit_driver);
-}
-
-module_init(touchkit_init);
-module_exit(touchkit_cleanup);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
index 86e37a2..e082941 100644 (file)
@@ -647,7 +647,7 @@ exit:
 
 static int usbtouch_open(struct input_dev *input)
 {
-       struct usbtouch_usb *usbtouch = input->private;
+       struct usbtouch_usb *usbtouch = input_get_drvdata(input);
 
        usbtouch->irq->dev = usbtouch->udev;
 
@@ -659,7 +659,7 @@ static int usbtouch_open(struct input_dev *input)
 
 static void usbtouch_close(struct input_dev *input)
 {
-       struct usbtouch_usb *usbtouch = input->private;
+       struct usbtouch_usb *usbtouch = input_get_drvdata(input);
 
        usb_kill_urb(usbtouch->irq);
 }
@@ -740,8 +740,10 @@ static int usbtouch_probe(struct usb_interface *intf,
        input_dev->name = usbtouch->name;
        input_dev->phys = usbtouch->phys;
        usb_to_input_id(udev, &input_dev->id);
-       input_dev->cdev.dev = &intf->dev;
-       input_dev->private = usbtouch;
+       input_dev->dev.parent = &intf->dev;
+
+       input_set_drvdata(input_dev, usbtouch);
+
        input_dev->open = usbtouch_open;
        input_dev->close = usbtouch_close;
 
index 12b4274..1fe4820 100644 (file)
@@ -122,7 +122,7 @@ void wacom_input_sync(void *wcombo)
 
 static int wacom_open(struct input_dev *dev)
 {
-       struct wacom *wacom = dev->private;
+       struct wacom *wacom = input_get_drvdata(dev);
 
        wacom->irq->dev = wacom->usbdev;
        if (usb_submit_urb(wacom->irq, GFP_KERNEL))
@@ -133,7 +133,7 @@ static int wacom_open(struct input_dev *dev)
 
 static void wacom_close(struct input_dev *dev)
 {
-       struct wacom *wacom = dev->private;
+       struct wacom *wacom = input_get_drvdata(dev);
 
        usb_kill_urb(wacom->irq);
 }
@@ -201,6 +201,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
        struct wacom *wacom;
        struct wacom_wac *wacom_wac;
        struct input_dev *input_dev;
+       int error = -ENOMEM;
        char rep_data[2], limit = 0;
 
        wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
@@ -229,8 +230,10 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
        wacom->wacom_wac = wacom_wac;
        usb_to_input_id(dev, &input_dev->id);
 
-       input_dev->cdev.dev = &intf->dev;
-       input_dev->private = wacom;
+       input_dev->dev.parent = &intf->dev;
+
+       input_set_drvdata(input_dev, wacom);
+
        input_dev->open = wacom_open;
        input_dev->close = wacom_close;
 
@@ -252,7 +255,9 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
        wacom->irq->transfer_dma = wacom->data_dma;
        wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-       input_register_device(wacom->dev);
+       error = input_register_device(wacom->dev);
+       if (error)
+               goto fail3;
 
        /* Ask the tablet to report tablet data. Repeat until it succeeds */
        do {
@@ -265,11 +270,12 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
        usb_set_intfdata(intf, wacom);
        return 0;
 
-fail2: usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma);
-fail1: input_free_device(input_dev);
+ fail3:        usb_free_urb(wacom->irq);
+ fail2:        usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma);
+ fail1:        input_free_device(input_dev);
        kfree(wacom);
        kfree(wacom_wac);
-       return -ENOMEM;
+       return error;
 }
 
 static void wacom_disconnect(struct usb_interface *intf)
index e4bc76e..7357239 100644 (file)
@@ -267,7 +267,7 @@ exit:
 
 static int xpad_open (struct input_dev *dev)
 {
-       struct usb_xpad *xpad = dev->private;
+       struct usb_xpad *xpad = input_get_drvdata(dev);
 
        xpad->irq_in->dev = xpad->udev;
        if (usb_submit_urb(xpad->irq_in, GFP_KERNEL))
@@ -278,7 +278,7 @@ static int xpad_open (struct input_dev *dev)
 
 static void xpad_close (struct input_dev *dev)
 {
-       struct usb_xpad *xpad = dev->private;
+       struct usb_xpad *xpad = input_get_drvdata(dev);
 
        usb_kill_urb(xpad->irq_in);
 }
@@ -312,6 +312,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
        struct input_dev *input_dev;
        struct usb_endpoint_descriptor *ep_irq_in;
        int i;
+       int error = -ENOMEM;
 
        for (i = 0; xpad_device[i].idVendor; i++) {
                if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) &&
@@ -344,8 +345,10 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
        input_dev->name = xpad_device[i].name;
        input_dev->phys = xpad->phys;
        usb_to_input_id(udev, &input_dev->id);
-       input_dev->cdev.dev = &intf->dev;
-       input_dev->private = xpad;
+       input_dev->dev.parent = &intf->dev;
+
+       input_set_drvdata(input_dev, xpad);
+
        input_dev->open = xpad_open;
        input_dev->close = xpad_close;
 
@@ -373,15 +376,18 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
        xpad->irq_in->transfer_dma = xpad->idata_dma;
        xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-       input_register_device(xpad->dev);
+       error = input_register_device(xpad->dev);
+       if (error)
+               goto fail3;
 
        usb_set_intfdata(intf, xpad);
        return 0;
 
-fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
-fail1: input_free_device(input_dev);
+ fail3:        usb_free_urb(xpad->irq_in);
+ fail2:        usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
+ fail1:        input_free_device(input_dev);
        kfree(xpad);
-       return -ENOMEM;
+       return error;
 
 }
 
index caff8e6..c54f1a5 100644 (file)
@@ -502,7 +502,7 @@ static int input_ev(struct input_dev *dev, unsigned int type,
 
 static int input_open(struct input_dev *dev)
 {
-       struct yealink_dev *yld = dev->private;
+       struct yealink_dev *yld = input_get_drvdata(dev);
        int i, ret;
 
        dbg("%s", __FUNCTION__);
@@ -529,7 +529,7 @@ static int input_open(struct input_dev *dev)
 
 static void input_close(struct input_dev *dev)
 {
-       struct yealink_dev *yld = dev->private;
+       struct yealink_dev *yld = input_get_drvdata(dev);
 
        usb_kill_urb(yld->urb_ctl);
        usb_kill_urb(yld->urb_irq);
@@ -937,9 +937,10 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
        input_dev->name = nfo->name;
        input_dev->phys = yld->phys;
        usb_to_input_id(udev, &input_dev->id);
-       input_dev->cdev.dev = &intf->dev;
+       input_dev->dev.parent = &intf->dev;
+
+       input_set_drvdata(input_dev, yld);
 
-       input_dev->private = yld;
        input_dev->open = input_open;
        input_dev->close = input_close;
        /* input_dev->event = input_ev; TODO */
@@ -955,7 +956,9 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
                }
        }
 
-       input_register_device(yld->idev);
+       ret = input_register_device(yld->idev);
+       if (ret)
+               return usb_cleanup(yld, ret);
 
        usb_set_intfdata(intf, yld);
 
index a0cc05d..60d2944 100644 (file)
@@ -55,7 +55,6 @@
 #include <linux/usb.h>
 #include <linux/types.h>
 #include <linux/ethtool.h>
-#include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/wait.h>
 #include <asm/uaccess.h>
index b1cb72c..d18b51f 100644 (file)
@@ -389,7 +389,10 @@ config FB_ARC
 
 config FB_ATARI
        bool "Atari native chipset support"
-       depends on (FB = y) && ATARI && BROKEN
+       depends on (FB = y) && ATARI
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
        help
          This is the frame buffer device driver for the builtin graphics
          chipset found in Ataris.
index 760305c..8693517 100644 (file)
@@ -63,7 +63,8 @@ obj-$(CONFIG_FB_TCX)              += tcx.o sbuslib.o
 obj-$(CONFIG_FB_LEO)              += leo.o sbuslib.o
 obj-$(CONFIG_FB_SGIVW)            += sgivwfb.o
 obj-$(CONFIG_FB_ACORN)            += acornfb.o
-obj-$(CONFIG_FB_ATARI)            += atafb.o
+obj-$(CONFIG_FB_ATARI)            += atafb.o c2p.o atafb_mfb.o \
+                                     atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o
 obj-$(CONFIG_FB_MAC)              += macfb.o
 obj-$(CONFIG_FB_HGA)              += hgafb.o
 obj-$(CONFIG_FB_IGA)              += igafb.o
index bffe2b9..0038a05 100644 (file)
@@ -2,7 +2,7 @@
  * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device
  *
  *  Copyright (C) 1994 Martin Schaller & Roman Hodek
- *  
+ *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file COPYING in the main directory of this archive
  * for more details.
 #include <linux/fb.h>
 #include <asm/atarikb.h>
 
-#include <video/fbcon.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-#include <video/fbcon-iplan2p2.h>
-#include <video/fbcon-iplan2p4.h>
-#include <video/fbcon-iplan2p8.h>
-#include <video/fbcon-mfb.h>
-
+#include "c2p.h"
+#include "atafb.h"
 
 #define SWITCH_ACIA 0x01               /* modes for switch on OverScan */
 #define SWITCH_SND6 0x40
 
 #define up(x, r) (((x) + (r) - 1) & ~((r)-1))
 
+       /*
+        * Interface to the world
+        */
+
+static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
+static int atafb_set_par(struct fb_info *info);
+static int atafb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
+                          unsigned int blue, unsigned int transp,
+                          struct fb_info *info);
+static int atafb_blank(int blank, struct fb_info *info);
+static int atafb_pan_display(struct fb_var_screeninfo *var,
+                            struct fb_info *info);
+static void atafb_fillrect(struct fb_info *info,
+                          const struct fb_fillrect *rect);
+static void atafb_copyarea(struct fb_info *info,
+                          const struct fb_copyarea *region);
+static void atafb_imageblit(struct fb_info *info, const struct fb_image *image);
+static int atafb_ioctl(struct fb_info *info, unsigned int cmd,
+                      unsigned long arg);
 
-static int default_par=0;      /* default resolution (0=none) */
 
-static unsigned long default_mem_req=0;
+static int default_par;                /* default resolution (0=none) */
 
-static int hwscroll=-1;
+static unsigned long default_mem_req;
+
+static int hwscroll = -1;
 
 static int use_hwscroll = 1;
 
-static int sttt_xres=640,st_yres=400,tt_yres=480;
-static int sttt_xres_virtual=640,sttt_yres_virtual=400;
-static int ovsc_offset=0, ovsc_addlen=0;
+static int sttt_xres = 640, st_yres = 400, tt_yres = 480;
+static int sttt_xres_virtual = 640, sttt_yres_virtual = 400;
+static int ovsc_offset, ovsc_addlen;
+
+       /*
+        * Hardware parameters for current mode
+        */
 
 static struct atafb_par {
        void *screen_base;
        int yres_virtual;
+       u_long next_line;
+       u_long next_plane;
 #if defined ATAFB_TT || defined ATAFB_STE
        union {
                struct {
@@ -138,7 +158,7 @@ static struct atafb_par {
 /* Don't calculate an own resolution, and thus don't change the one found when
  * booting (currently used for the Falcon to keep settings for internal video
  * hardware extensions (e.g. ScreenBlaster)  */
-static int DontCalcRes = 0; 
+static int DontCalcRes = 0;
 
 #ifdef ATAFB_FALCON
 #define HHT hw.falcon.hht
@@ -163,83 +183,84 @@ static int DontCalcRes = 0;
 #define VMO_PREMASK            0x0c
 #endif
 
-static struct fb_info fb_info;
+static struct fb_info fb_info = {
+       .fix = {
+               .id     = "Atari ",
+               .visual = FB_VISUAL_PSEUDOCOLOR,
+               .accel  = FB_ACCEL_NONE,
+       }
+};
 
 static void *screen_base;      /* base address of screen */
 static void *real_screen_base; /* (only for Overscan) */
 
 static int screen_len;
 
-static int current_par_valid=0; 
-
-static int mono_moni=0;
+static int current_par_valid;
 
-static struct display disp;
+static int mono_moni;
 
 
 #ifdef ATAFB_EXT
-/* external video handling */
 
-static unsigned                        external_xres;
-static unsigned                        external_xres_virtual;
-static unsigned                        external_yres;
-/* not needed - atafb will never support panning/hardwarescroll with external
- * static unsigned             external_yres_virtual;  
-*/
+/* external video handling */
+static unsigned int external_xres;
+static unsigned int external_xres_virtual;
+static unsigned int external_yres;
 
-static unsigned                        external_depth;
-static int                             external_pmode;
-static void *external_addr = 0;
-static unsigned long   external_len;
-static unsigned long   external_vgaiobase = 0;
-static unsigned int            external_bitspercol = 6;
-
-/* 
-JOE <joe@amber.dinoco.de>: 
-added card type for external driver, is only needed for
-colormap handling.
-*/
+/*
+ * not needed - atafb will never support panning/hardwarescroll with external
+ * static unsigned int external_yres_virtual;
+ */
+static unsigned int external_depth;
+static int external_pmode;
+static void *external_addr;
+static unsigned long external_len;
+static unsigned long external_vgaiobase;
+static unsigned int external_bitspercol = 6;
 
+/*
+ * JOE <joe@amber.dinoco.de>:
+ * added card type for external driver, is only needed for
+ * colormap handling.
+ */
 enum cardtype { IS_VGA, IS_MV300 };
 static enum cardtype external_card_type = IS_VGA;
 
 /*
-The MV300 mixes the color registers. So we need an array of munged
-indices in order to access the correct reg.
-*/
-static int MV300_reg_1bit[2]={0,1};
-static int MV300_reg_4bit[16]={
-0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 };
-static int MV300_reg_8bit[256]={
-0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, 
-8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, 
-4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, 
-12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, 
-2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, 
-10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, 
-6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, 
-14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, 
-1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, 
-9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, 
-5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, 
-13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, 
-3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, 
-11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, 
-7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, 
-15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 }; 
+ * The MV300 mixes the color registers. So we need an array of munged
+ * indices in order to access the correct reg.
+ */
+static int MV300_reg_1bit[2] = {
+       0, 1
+};
+static int MV300_reg_4bit[16] = {
+       0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
+};
+static int MV300_reg_8bit[256] = {
+       0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
+       8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
+       4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
+       12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
+       2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
+       10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
+       6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
+       14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
+       1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
+       9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
+       5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
+       13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
+       3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
+       11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
+       7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
+       15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
+};
 
 static int *MV300_reg = MV300_reg_8bit;
-
-/*
-And on the MV300 it's difficult to read out the hardware palette. So we
-just keep track of the set colors in our own array here, and use that!
-*/
-
-static struct { unsigned char red,green,blue,pad; } ext_color[256];
 #endif /* ATAFB_EXT */
 
 
-static int inverse=0;
+static int inverse;
 
 extern int fontheight_8x8;
 extern int fontwidth_8x8;
@@ -249,96 +270,154 @@ extern int fontheight_8x16;
 extern int fontwidth_8x16;
 extern unsigned char fontdata_8x16[];
 
+/*
+ * struct fb_ops {
+ *     * open/release and usage marking
+ *     struct module *owner;
+ *     int (*fb_open)(struct fb_info *info, int user);
+ *     int (*fb_release)(struct fb_info *info, int user);
+ *
+ *     * For framebuffers with strange non linear layouts or that do not
+ *     * work with normal memory mapped access
+ *     ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);
+ *     ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
+ *
+ *     * checks var and eventually tweaks it to something supported,
+ *     * DOES NOT MODIFY PAR *
+ *     int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
+ *
+ *     * set the video mode according to info->var *
+ *     int (*fb_set_par)(struct fb_info *info);
+ *
+ *     * set color register *
+ *     int (*fb_setcolreg)(unsigned int regno, unsigned int red, unsigned int green,
+ *                         unsigned int blue, unsigned int transp, struct fb_info *info);
+ *
+ *     * set color registers in batch *
+ *     int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
+ *
+ *     * blank display *
+ *     int (*fb_blank)(int blank, struct fb_info *info);
+ *
+ *     * pan display *
+ *     int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
+ *
+ *     *** The meat of the drawing engine ***
+ *     * Draws a rectangle *
+ *     void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
+ *     * Copy data from area to another *
+ *     void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
+ *     * Draws a image to the display *
+ *     void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
+ *
+ *     * Draws cursor *
+ *     int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
+ *
+ *     * Rotates the display *
+ *     void (*fb_rotate)(struct fb_info *info, int angle);
+ *
+ *     * wait for blit idle, optional *
+ *     int (*fb_sync)(struct fb_info *info);
+ *
+ *     * perform fb specific ioctl (optional) *
+ *     int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
+ *                     unsigned long arg);
+ *
+ *     * Handle 32bit compat ioctl (optional) *
+ *     int (*fb_compat_ioctl)(struct fb_info *info, unsigned int cmd,
+ *                     unsigned long arg);
+ *
+ *     * perform fb specific mmap *
+ *     int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
+ *
+ *     * save current hardware state *
+ *     void (*fb_save_state)(struct fb_info *info);
+ *
+ *     * restore saved state *
+ *     void (*fb_restore_state)(struct fb_info *info);
+ * } ;
+ */
+
+
 /* ++roman: This structure abstracts from the underlying hardware (ST(e),
  * TT, or Falcon.
  *
- * int (*detect)( void )
+ * int (*detect)(void)
  *   This function should detect the current video mode settings and
  *   store them in atafb_predefined[0] for later reference by the
  *   user. Return the index+1 of an equivalent predefined mode or 0
  *   if there is no such.
- * 
- * int (*encode_fix)( struct fb_fix_screeninfo *fix,
- *                    struct atafb_par *par )
+ *
+ * int (*encode_fix)(struct fb_fix_screeninfo *fix,
+ *                   struct atafb_par *par)
  *   This function should fill in the 'fix' structure based on the
  *   values in the 'par' structure.
- *   
- * int (*decode_var)( struct fb_var_screeninfo *var,
- *                    struct atafb_par *par )
+ * !!! Obsolete, perhaps !!!
+ *
+ * int (*decode_var)(struct fb_var_screeninfo *var,
+ *                   struct atafb_par *par)
  *   Get the video params out of 'var'. If a value doesn't fit, round
  *   it up, if it's too big, return EINVAL.
- *   Round up in the following order: bits_per_pixel, xres, yres, 
- *   xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, 
+ *   Round up in the following order: bits_per_pixel, xres, yres,
+ *   xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
  *   horizontal timing, vertical timing.
  *
- * int (*encode_var)( struct fb_var_screeninfo *var,
- *                    struct atafb_par *par );
+ * int (*encode_var)(struct fb_var_screeninfo *var,
+ *                   struct atafb_par *par);
  *   Fill the 'var' structure based on the values in 'par' and maybe
  *   other values read out of the hardware.
- *   
- * void (*get_par)( struct atafb_par *par )
+ *
+ * void (*get_par)(struct atafb_par *par)
  *   Fill the hardware's 'par' structure.
- *   
- * void (*set_par)( struct atafb_par *par )
+ *   !!! Used only by detect() !!!
+ *
+ * void (*set_par)(struct atafb_par *par)
  *   Set the hardware according to 'par'.
- *   
- * int (*getcolreg)( unsigned regno, unsigned *red,
- *                   unsigned *green, unsigned *blue,
- *                   unsigned *transp, struct fb_info *info )
- *   Read a single color register and split it into
- *   colors/transparent. Return != 0 for invalid regno.
  *
  * void (*set_screen_base)(void *s_base)
  *   Set the base address of the displayed frame buffer. Only called
  *   if yres_virtual > yres or xres_virtual > xres.
  *
- * int (*blank)( int blank_mode )
- *   Blank the screen if blank_mode!=0, else unblank. If blank==NULL then
+ * int (*blank)(int blank_mode)
+ *   Blank the screen if blank_mode != 0, else unblank. If blank == NULL then
  *   the caller blanks by setting the CLUT to all black. Return 0 if blanking
  *   succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
  *   doesn't support it. Implements VESA suspend and powerdown modes on
  *   hardware that supports disabling hsync/vsync:
- *       blank_mode==2: suspend vsync, 3:suspend hsync, 4: powerdown.
+ *       blank_mode == 2: suspend vsync, 3:suspend hsync, 4: powerdown.
  */
 
 static struct fb_hwswitch {
-       int  (*detect)( void );
-       int  (*encode_fix)( struct fb_fix_screeninfo *fix,
-                                               struct atafb_par *par );
-       int  (*decode_var)( struct fb_var_screeninfo *var,
-                                               struct atafb_par *par );
-       int  (*encode_var)( struct fb_var_screeninfo *var,
-                                               struct atafb_par *par );
-       void (*get_par)( struct atafb_par *par );
-       void (*set_par)( struct atafb_par *par );
-       int  (*getcolreg)( unsigned regno, unsigned *red,
-                                          unsigned *green, unsigned *blue,
-                                          unsigned *transp, struct fb_info *info );
+       int (*detect)(void);
+       int (*encode_fix)(struct fb_fix_screeninfo *fix,
+                         struct atafb_par *par);
+       int (*decode_var)(struct fb_var_screeninfo *var,
+                         struct atafb_par *par);
+       int (*encode_var)(struct fb_var_screeninfo *var,
+                         struct atafb_par *par);
+       void (*get_par)(struct atafb_par *par);
+       void (*set_par)(struct atafb_par *par);
        void (*set_screen_base)(void *s_base);
-       int  (*blank)( int blank_mode );
-       int  (*pan_display)( struct fb_var_screeninfo *var,
-                                                struct atafb_par *par);
+       int (*blank)(int blank_mode);
+       int (*pan_display)(struct fb_var_screeninfo *var,
+                          struct fb_info *info);
 } *fbhw;
 
-static char *autodetect_names[] = {"autodetect", NULL};
-static char *stlow_names[] = {"stlow", NULL};
-static char *stmid_names[] = {"stmid", "default5", NULL};
-static char *sthigh_names[] = {"sthigh", "default4", NULL};
-static char *ttlow_names[] = {"ttlow", NULL};
-static char *ttmid_names[]= {"ttmid", "default1", NULL};
-static char *tthigh_names[]= {"tthigh", "default2", NULL};
-static char *vga2_names[] = {"vga2", NULL};
-static char *vga4_names[] = {"vga4", NULL};
-static char *vga16_names[] = {"vga16", "default3", NULL};
-static char *vga256_names[] = {"vga256", NULL};
-static char *falh2_names[] = {"falh2", NULL};
-static char *falh16_names[] = {"falh16", NULL};
+static char *autodetect_names[] = { "autodetect", NULL };
+static char *stlow_names[] = { "stlow", NULL };
+static char *stmid_names[] = { "stmid", "default5", NULL };
+static char *sthigh_names[] = { "sthigh", "default4", NULL };
+static char *ttlow_names[] = { "ttlow", NULL };
+static char *ttmid_names[] = { "ttmid", "default1", NULL };
+static char *tthigh_names[] = { "tthigh", "default2", NULL };
+static char *vga2_names[] = { "vga2", NULL };
+static char *vga4_names[] = { "vga4", NULL };
+static char *vga16_names[] = { "vga16", "default3", NULL };
+static char *vga256_names[] = { "vga256", NULL };
+static char *falh2_names[] = { "falh2", NULL };
+static char *falh16_names[] = { "falh16", NULL };
 
 static char **fb_var_names[] = {
-       /* Writing the name arrays directly in this array (via "(char *[]){...}")
-        * crashes gcc 2.5.8 (sigsegv) if the inner array
-        * contains more than two items. I've also seen that all elements
-        * were identical to the last (my cross-gcc) :-(*/
        autodetect_names,
        stlow_names,
        stmid_names,
@@ -353,18 +432,17 @@ static char **fb_var_names[] = {
        falh2_names,
        falh16_names,
        NULL
-       /* ,NULL */ /* this causes a sigsegv on my gcc-2.5.8 */
 };
 
 static struct fb_var_screeninfo atafb_predefined[] = {
-       /*
-        * yres_virtual==0 means use hw-scrolling if possible, else yres
-        */
-       { /* autodetect */
-         0, 0, 0, 0, 0, 0, 0, 0,               /* xres-grayscale */
-         {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},   /* red green blue tran*/
+       /*
+        * yres_virtual == 0 means use hw-scrolling if possible, else yres
+        */
+       { /* autodetect */
+         0, 0, 0, 0, 0, 0, 0, 0,               /* xres-grayscale */
+         {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},   /* red green blue tran*/
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
-       { /* st low */
+       { /* st low */
          320, 200, 320, 0, 0, 0, 4, 0,
          {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
@@ -414,27 +492,100 @@ static struct fb_var_screeninfo atafb_predefined[] = {
          0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 };
 
-static int num_atafb_predefined=ARRAY_SIZE(atafb_predefined);
+static int num_atafb_predefined = ARRAY_SIZE(atafb_predefined);
 
+static struct fb_videomode atafb_modedb[] __initdata = {
+       /*
+        *  Atari Video Modes
+        *
+        *  If you change these, make sure to update DEFMODE_* as well!
+        */
 
-static int
-get_video_mode(char *vname)
+       /*
+        *  ST/TT Video Modes
+        */
+
+       {
+               /* 320x200, 15 kHz, 60 Hz (ST low) */
+               "st-low", 60, 320, 200, 32000, 32, 16, 31, 14, 96, 4,
+               0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+       }, {
+               /* 640x200, 15 kHz, 60 Hz (ST medium) */
+               "st-mid", 60, 640, 200, 32000, 32, 16, 31, 14, 96, 4,
+               0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+       }, {
+               /* 640x400, 30.25 kHz, 63.5 Hz (ST high) */
+               "st-high", 63, 640, 400, 32000, 128, 0, 40, 14, 128, 4,
+               0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+       }, {
+               /* 320x480, 15 kHz, 60 Hz (TT low) */
+               "tt-low", 60, 320, 480, 31041, 120, 100, 8, 16, 140, 30,
+               0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+       }, {
+               /* 640x480, 29 kHz, 57 Hz (TT medium) */
+               "tt-mid", 60, 640, 480, 31041, 120, 100, 8, 16, 140, 30,
+               0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+       }, {
+               /* 1280x960, 29 kHz, 60 Hz (TT high) */
+               "tt-high", 57, 640, 960, 31041, 120, 100, 8, 16, 140, 30,
+               0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+       },
+
+       /*
+        *  VGA Video Modes
+        */
+
+       {
+               /* 640x480, 31 kHz, 60 Hz (VGA) */
+               "vga", 63.5, 640, 480, 32000, 18, 42, 31, 11, 96, 3,
+               0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+       }, {
+               /* 640x400, 31 kHz, 70 Hz (VGA) */
+               "vga70", 70, 640, 400, 32000, 18, 42, 31, 11, 96, 3,
+               FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+       },
+
+       /*
+        *  Falcon HiRes Video Modes
+        */
+
+       {
+               /* 896x608, 31 kHz, 60 Hz (Falcon High) */
+               "falh", 60, 896, 608, 32000, 18, 42, 31, 1, 96,3,
+               0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
+       },
+};
+
+#define NUM_TOTAL_MODES  ARRAY_SIZE(atafb_modedb)
+
+static char *mode_option __initdata = NULL;
+
+ /* default modes */
+
+#define DEFMODE_TT     5               /* "tt-high" for TT */
+#define DEFMODE_F30    7               /* "vga70" for Falcon */
+#define DEFMODE_STE    2               /* "st-high" for ST/E */
+#define DEFMODE_EXT    6               /* "vga" for external */
+
+
+static int get_video_mode(char *vname)
 {
-    char ***name_list;
-    char **name;
-    int i;
-    name_list=fb_var_names;
-    for (i = 0 ; i < num_atafb_predefined ; i++) {
-       name=*(name_list++);
-       if (! name || ! *name)
-           break;
-       while (*name) {
-           if (! strcmp(vname, *name))
-               return i+1;
-           name++;
+       char ***name_list;
+       char **name;
+       int i;
+
+       name_list = fb_var_names;
+       for (i = 0; i < num_atafb_predefined; i++) {
+               name = *name_list++;
+               if (!name || !*name)
+                       break;
+               while (*name) {
+                       if (!strcmp(vname, *name))
+                               return i + 1;
+                       name++;
+               }
        }
-    }
-    return 0;
+       return 0;
 }
 
 
@@ -443,93 +594,84 @@ get_video_mode(char *vname)
 
 #ifdef ATAFB_TT
 
-static int tt_encode_fix( struct fb_fix_screeninfo *fix,
-                                                 struct atafb_par *par )
-
+static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
 {
        int mode;
 
-       strcpy(fix->id,"Atari Builtin");
+       strcpy(fix->id, "Atari Builtin");
        fix->smem_start = (unsigned long)real_screen_base;
        fix->smem_len = screen_len;
-       fix->type=FB_TYPE_INTERLEAVED_PLANES;
-       fix->type_aux=2;
-       fix->visual=FB_VISUAL_PSEUDOCOLOR;
+       fix->type = FB_TYPE_INTERLEAVED_PLANES;
+       fix->type_aux = 2;
+       fix->visual = FB_VISUAL_PSEUDOCOLOR;
        mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
        if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
-               fix->type=FB_TYPE_PACKED_PIXELS;
-               fix->type_aux=0;
+               fix->type = FB_TYPE_PACKED_PIXELS;
+               fix->type_aux = 0;
                if (mode == TT_SHIFTER_TTHIGH)
-                       fix->visual=FB_VISUAL_MONO01;
+                       fix->visual = FB_VISUAL_MONO01;
        }
-       fix->xpanstep=0;
-       fix->ypanstep=1;
-       fix->ywrapstep=0;
+       fix->xpanstep = 0;
+       fix->ypanstep = 1;
+       fix->ywrapstep = 0;
        fix->line_length = 0;
        fix->accel = FB_ACCEL_ATARIBLITT;
        return 0;
 }
 
-
-static int tt_decode_var( struct fb_var_screeninfo *var,
-                                                 struct atafb_par *par )
+static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
 {
-       int xres=var->xres;
-       int yres=var->yres;
-       int bpp=var->bits_per_pixel;
+       int xres = var->xres;
+       int yres = var->yres;
+       int bpp = var->bits_per_pixel;
        int linelen;
        int yres_virtual = var->yres_virtual;
 
        if (mono_moni) {
-               if (bpp > 1 || xres > sttt_xres*2 || yres >tt_yres*2)
+               if (bpp > 1 || xres > sttt_xres * 2 || yres > tt_yres * 2)
                        return -EINVAL;
-               par->hw.tt.mode=TT_SHIFTER_TTHIGH;
-               xres=sttt_xres*2;
-               yres=tt_yres*2;
-               bpp=1;
+               par->hw.tt.mode = TT_SHIFTER_TTHIGH;
+               xres = sttt_xres * 2;
+               yres = tt_yres * 2;
+               bpp = 1;
        } else {
                if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
                        return -EINVAL;
                if (bpp > 4) {
-                       if (xres > sttt_xres/2 || yres > tt_yres)
+                       if (xres > sttt_xres / 2 || yres > tt_yres)
                                return -EINVAL;
-                       par->hw.tt.mode=TT_SHIFTER_TTLOW;
-                       xres=sttt_xres/2;
-                       yres=tt_yres;
-                       bpp=8;
-               }
-               else if (bpp > 2) {
+                       par->hw.tt.mode = TT_SHIFTER_TTLOW;
+                       xres = sttt_xres / 2;
+                       yres = tt_yres;
+                       bpp = 8;
+               } else if (bpp > 2) {
                        if (xres > sttt_xres || yres > tt_yres)
                                return -EINVAL;
-                       if (xres > sttt_xres/2 || yres > st_yres/2) {
-                               par->hw.tt.mode=TT_SHIFTER_TTMID;
-                               xres=sttt_xres;
-                               yres=tt_yres;
-                               bpp=4;
+                       if (xres > sttt_xres / 2 || yres > st_yres / 2) {
+                               par->hw.tt.mode = TT_SHIFTER_TTMID;
+                               xres = sttt_xres;
+                               yres = tt_yres;
+                               bpp = 4;
+                       } else {
+                               par->hw.tt.mode = TT_SHIFTER_STLOW;
+                               xres = sttt_xres / 2;
+                               yres = st_yres / 2;
+                               bpp = 4;
                        }
-                       else {
-                               par->hw.tt.mode=TT_SHIFTER_STLOW;
-                               xres=sttt_xres/2;
-                               yres=st_yres/2;
-                               bpp=4;
-                       }
-               }
-               else if (bpp > 1) {
-                       if (xres > sttt_xres || yres > st_yres/2)
+               } else if (bpp > 1) {
+                       if (xres > sttt_xres || yres > st_yres / 2)
                                return -EINVAL;
-                       par->hw.tt.mode=TT_SHIFTER_STMID;
-                       xres=sttt_xres;
-                       yres=st_yres/2;
-                       bpp=2;
-               }
-               else if (var->xres > sttt_xres || var->yres > st_yres) {
+                       par->hw.tt.mode = TT_SHIFTER_STMID;
+                       xres = sttt_xres;
+                       yres = st_yres / 2;
+                       bpp = 2;
+               } else if (var->xres > sttt_xres || var->yres > st_yres) {
                        return -EINVAL;
-               }
-               else {
-                       par->hw.tt.mode=TT_SHIFTER_STHIGH;
-                       xres=sttt_xres;
-                       yres=st_yres;
-                       bpp=1;
+               } else {
+                       par->hw.tt.mode = TT_SHIFTER_STHIGH;
+                       xres = sttt_xres;
+                       yres = st_yres;
+                       bpp = 1;
                }
        }
        if (yres_virtual <= 0)
@@ -537,10 +679,10 @@ static int tt_decode_var( struct fb_var_screeninfo *var,
        else if (yres_virtual < yres)
                yres_virtual = yres;
        if (var->sync & FB_SYNC_EXT)
-               par->hw.tt.sync=0;
+               par->hw.tt.sync = 0;
        else
-               par->hw.tt.sync=1;
-       linelen=xres*bpp/8;
+               par->hw.tt.sync = 1;
+       linelen = xres * bpp / 8;
        if (yres_virtual * linelen > screen_len && screen_len)
                return -EINVAL;
        if (yres * linelen > screen_len && screen_len)
@@ -552,154 +694,123 @@ static int tt_decode_var( struct fb_var_screeninfo *var,
        return 0;
 }
 
-static int tt_encode_var( struct fb_var_screeninfo *var,
-                                                 struct atafb_par *par )
+static int tt_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
 {
        int linelen;
        memset(var, 0, sizeof(struct fb_var_screeninfo));
-       var->red.offset=0;
-       var->red.length=4;
-       var->red.msb_right=0;
-       var->grayscale=0;
-
-       var->pixclock=31041;
-       var->left_margin=120;           /* these may be incorrect       */
-       var->right_margin=100;
-       var->upper_margin=8;
-       var->lower_margin=16;
-       var->hsync_len=140;
-       var->vsync_len=30;
-
-       var->height=-1;
-       var->width=-1;
+       var->red.offset = 0;
+       var->red.length = 4;
+       var->red.msb_right = 0;
+       var->grayscale = 0;
+
+       var->pixclock = 31041;
+       var->left_margin = 120;         /* these may be incorrect */
+       var->right_margin = 100;
+       var->upper_margin = 8;
+       var->lower_margin = 16;
+       var->hsync_len = 140;
+       var->vsync_len = 30;
+
+       var->height = -1;
+       var->width = -1;
 
        if (par->hw.tt.sync & 1)
-               var->sync=0;
+               var->sync = 0;
        else
-               var->sync=FB_SYNC_EXT;
+               var->sync = FB_SYNC_EXT;
 
        switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
        case TT_SHIFTER_STLOW:
-               var->xres=sttt_xres/2;
-               var->xres_virtual=sttt_xres_virtual/2;
-               var->yres=st_yres/2;
-               var->bits_per_pixel=4;
+               var->xres = sttt_xres / 2;
+               var->xres_virtual = sttt_xres_virtual / 2;
+               var->yres = st_yres / 2;
+               var->bits_per_pixel = 4;
                break;
        case TT_SHIFTER_STMID:
-               var->xres=sttt_xres;
-               var->xres_virtual=sttt_xres_virtual;
-               var->yres=st_yres/2;
-               var->bits_per_pixel=2;
+               var->xres = sttt_xres;
+               var->xres_virtual = sttt_xres_virtual;
+               var->yres = st_yres / 2;
+               var->bits_per_pixel = 2;
                break;
        case TT_SHIFTER_STHIGH:
-               var->xres=sttt_xres;
-               var->xres_virtual=sttt_xres_virtual;
-               var->yres=st_yres;
-               var->bits_per_pixel=1;
+               var->xres = sttt_xres;
+               var->xres_virtual = sttt_xres_virtual;
+               var->yres = st_yres;
+               var->bits_per_pixel = 1;
                break;
        case TT_SHIFTER_TTLOW:
-               var->xres=sttt_xres/2;
-               var->xres_virtual=sttt_xres_virtual/2;
-               var->yres=tt_yres;
-               var->bits_per_pixel=8;
+               var->xres = sttt_xres / 2;
+               var->xres_virtual = sttt_xres_virtual / 2;
+               var->yres = tt_yres;
+               var->bits_per_pixel = 8;
                break;
        case TT_SHIFTER_TTMID:
-               var->xres=sttt_xres;
-               var->xres_virtual=sttt_xres_virtual;
-               var->yres=tt_yres;
-               var->bits_per_pixel=4;
+               var->xres = sttt_xres;
+               var->xres_virtual = sttt_xres_virtual;
+               var->yres = tt_yres;
+               var->bits_per_pixel = 4;
                break;
        case TT_SHIFTER_TTHIGH:
-               var->red.length=0;
-               var->xres=sttt_xres*2;
-               var->xres_virtual=sttt_xres_virtual*2;
-               var->yres=tt_yres*2;
-               var->bits_per_pixel=1;
+               var->red.length = 0;
+               var->xres = sttt_xres * 2;
+               var->xres_virtual = sttt_xres_virtual * 2;
+               var->yres = tt_yres * 2;
+               var->bits_per_pixel = 1;
                break;
-       }               
-       var->blue=var->green=var->red;
-       var->transp.offset=0;
-       var->transp.length=0;
-       var->transp.msb_right=0;
-       linelen=var->xres_virtual * var->bits_per_pixel / 8;
-       if (! use_hwscroll)
-               var->yres_virtual=var->yres;
+       }
+       var->blue = var->green = var->red;
+       var->transp.offset = 0;
+       var->transp.length = 0;
+       var->transp.msb_right = 0;
+       linelen = var->xres_virtual * var->bits_per_pixel / 8;
+       if (!use_hwscroll)
+               var->yres_virtual = var->yres;
        else if (screen_len) {
                if (par->yres_virtual)
                        var->yres_virtual = par->yres_virtual;
                else
-                       /* yres_virtual==0 means use maximum */
+                       /* yres_virtual == 0 means use maximum */
                        var->yres_virtual = screen_len / linelen;
        } else {
                if (hwscroll < 0)
                        var->yres_virtual = 2 * var->yres;
                else
-                       var->yres_virtual=var->yres+hwscroll * 16;
+                       var->yres_virtual = var->yres + hwscroll * 16;
        }
-       var->xoffset=0;
+       var->xoffset = 0;
        if (screen_base)
-               var->yoffset=(par->screen_base - screen_base)/linelen;
+               var->yoffset = (par->screen_base - screen_base) / linelen;
        else
-               var->yoffset=0;
-       var->nonstd=0;
-       var->activate=0;
-       var->vmode=FB_VMODE_NONINTERLACED;
+               var->yoffset = 0;
+       var->nonstd = 0;
+       var->activate = 0;
+       var->vmode = FB_VMODE_NONINTERLACED;
        return 0;
 }
 
-
-static void tt_get_par( struct atafb_par *par )
+static void tt_get_par(struct atafb_par *par)
 {
        unsigned long addr;
-       par->hw.tt.mode=shifter_tt.tt_shiftmode;
-       par->hw.tt.sync=shifter.syncmode;
+       par->hw.tt.mode = shifter_tt.tt_shiftmode;
+       par->hw.tt.sync = shifter.syncmode;
        addr = ((shifter.bas_hi & 0xff) << 16) |
               ((shifter.bas_md & 0xff) << 8)  |
               ((shifter.bas_lo & 0xff));
        par->screen_base = phys_to_virt(addr);
 }
 
-static void tt_set_par( struct atafb_par *par )
+static void tt_set_par(struct atafb_par *par)
 {
-       shifter_tt.tt_shiftmode=par->hw.tt.mode;
-       shifter.syncmode=par->hw.tt.sync;
+       shifter_tt.tt_shiftmode = par->hw.tt.mode;
+       shifter.syncmode = par->hw.tt.sync;
        /* only set screen_base if really necessary */
        if (current_par.screen_base != par->screen_base)
                fbhw->set_screen_base(par->screen_base);
 }
 
-
-static int tt_getcolreg(unsigned regno, unsigned *red,
-                       unsigned *green, unsigned *blue,
-                       unsigned *transp, struct fb_info *info)
-{
-       int t, col;
-
-       if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
-               regno += 254;
-       if (regno > 255)
-               return 1;
-       t = tt_palette[regno];
-       col = t & 15;
-       col |= col << 4;
-       col |= col << 8;
-       *blue = col;
-       col = (t >> 4) & 15;
-       col |= col << 4;
-       col |= col << 8;
-       *green = col;
-       col = (t >> 8) & 15;
-       col |= col << 4;
-       col |= col << 8;
-       *red = col;
-       *transp = 0;
-       return 0;
-}
-
-
-static int tt_setcolreg(unsigned regno, unsigned red,
-                       unsigned green, unsigned blue,
-                       unsigned transp, struct fb_info *info)
+static int tt_setcolreg(unsigned int regno, unsigned int red,
+                       unsigned int green, unsigned int blue,
+                       unsigned int transp, struct fb_info *info)
 {
        if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
                regno += 254;
@@ -708,15 +819,14 @@ static int tt_setcolreg(unsigned regno, unsigned red,
        tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
                             (blue >> 12));
        if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
-               TT_SHIFTER_STHIGH && regno == 254)
+           TT_SHIFTER_STHIGH && regno == 254)
                tt_palette[0] = 0;
        return 0;
 }
 
-                                                 
-static int tt_detect( void )
-
-{      struct atafb_par par;
+static int tt_detect(void)
+{
+       struct atafb_par par;
 
        /* Determine the connected monitor: The DMA sound must be
         * disabled before reading the MFP GPIP, because the Sound
@@ -726,9 +836,9 @@ static int tt_detect( void )
         * announced that the Eagle is TT compatible, but only the PCM is
         * missing...
         */
-       if (ATARIHW_PRESENT(PCM_8BIT)) { 
+       if (ATARIHW_PRESENT(PCM_8BIT)) {
                tt_dmasnd.ctrl = DMASND_CTRL_OFF;
-               udelay(20);     /* wait a while for things to settle down */
+               udelay(20);             /* wait a while for things to settle down */
        }
        mono_moni = (mfp.par_dt_reg & 0x80) == 0;
 
@@ -755,19 +865,24 @@ static struct pixel_clock {
        unsigned long f;        /* f/[Hz] */
        unsigned long t;        /* t/[ps] (=1/f) */
        int right, hsync, left; /* standard timing in clock cycles, not pixel */
-               /* hsync initialized in falcon_detect() */
+       /* hsync initialized in falcon_detect() */
        int sync_mask;          /* or-mask for hw.falcon.sync to set this clock */
        int control_mask;       /* ditto, for hw.falcon.vid_control */
-}
-f25  = {25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25},
-f32  = {32000000, 31250, 18, 0, 42, 0x0, 0},
-fext = {       0,     0, 18, 0, 42, 0x1, 0};
+} f25 = {
+       25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25
+}, f32 = {
+       32000000, 31250, 18, 0, 42, 0x0, 0
+}, fext = {
+       0, 0, 18, 0, 42, 0x1, 0
+};
 
 /* VIDEL-prescale values [mon_type][pixel_length from VCO] */
-static int vdl_prescale[4][3] = {{4,2,1}, {4,2,1}, {4,2,2}, {4,2,1}};
+static int vdl_prescale[4][3] = {
+       { 4,2,1 }, { 4,2,1 }, { 4,2,2 }, { 4,2,1 }
+};
 
 /* Default hsync timing [mon_type] in picoseconds */
-static long h_syncs[4] = {3000000, 4875000, 4000000, 4875000};
+static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 };
 
 #ifdef FBCON_HAS_CFB16
 static u16 fbcon_cfb16_cmap[16];
@@ -775,12 +890,12 @@ static u16 fbcon_cfb16_cmap[16];
 
 static inline int hxx_prescale(struct falcon_hw *hw)
 {
-       return hw->ste_mode ? 16 :
-                  vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
+       return hw->ste_mode ? 16
+                           : vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
 }
 
-static int falcon_encode_fix( struct fb_fix_screeninfo *fix,
-                                                         struct atafb_par *par )
+static int falcon_encode_fix(struct fb_fix_screeninfo *fix,
+                            struct atafb_par *par)
 {
        strcpy(fix->id, "Atari Builtin");
        fix->smem_start = (unsigned long)real_screen_base;
@@ -796,8 +911,7 @@ static int falcon_encode_fix( struct fb_fix_screeninfo *fix,
                fix->type_aux = 0;
                /* no smooth scrolling with longword aligned video mem */
                fix->xpanstep = 32;
-       }
-       else if (par->hw.falcon.f_shift & 0x100) {
+       } else if (par->hw.falcon.f_shift & 0x100) {
                fix->type = FB_TYPE_PACKED_PIXELS;
                fix->type_aux = 0;
                /* Is this ok or should it be DIRECTCOLOR? */
@@ -809,9 +923,8 @@ static int falcon_encode_fix( struct fb_fix_screeninfo *fix,
        return 0;
 }
 
-
-static int falcon_decode_var( struct fb_var_screeninfo *var,
-                                                         struct atafb_par *par )
+static int falcon_decode_var(struct fb_var_screeninfo *var,
+                            struct atafb_par *par)
 {
        int bpp = var->bits_per_pixel;
        int xres = var->xres;
@@ -823,17 +936,19 @@ static int falcon_decode_var( struct fb_var_screeninfo *var,
        int linelen;
        int interlace = 0, doubleline = 0;
        struct pixel_clock *pclock;
-       int plen; /* width of pixel in clock cycles */
+       int plen;                       /* width of pixel in clock cycles */
        int xstretch;
        int prescale;
        int longoffset = 0;
        int hfreq, vfreq;
+       int hdb_off, hde_off, base_off;
+       int gstart, gend1, gend2, align;
 
 /*
        Get the video params out of 'var'. If a value doesn't fit, round
        it up, if it's too big, return EINVAL.
-       Round up in the following order: bits_per_pixel, xres, yres, 
-       xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, 
+       Round up in the following order: bits_per_pixel, xres, yres,
+       xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
        horizontal timing, vertical timing.
 
        There is a maximum of screen resolution determined by pixelclock
@@ -843,11 +958,11 @@ static int falcon_decode_var( struct fb_var_screeninfo *var,
        Frequency range for multisync monitors is given via command line.
        For TV and SM124 both frequencies are fixed.
 
-       X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32==0)
+       X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0)
        Y % 16 == 0 to fit 8x16 font
        Y % 8 == 0 if Y<400
 
-       Currently interlace and doubleline mode in var are ignored. 
+       Currently interlace and doubleline mode in var are ignored.
        On SM124 and TV only the standard resolutions can be used.
 */
 
@@ -855,43 +970,38 @@ static int falcon_decode_var( struct fb_var_screeninfo *var,
        if (!xres || !yres || !bpp)
                return -EINVAL;
 
-       if (mon_type == F_MON_SM && bpp != 1) {
+       if (mon_type == F_MON_SM && bpp != 1)
                return -EINVAL;
-       }
-       else if (bpp <= 1) {
+
+       if (bpp <= 1) {
                bpp = 1;
                par->hw.falcon.f_shift = 0x400;
                par->hw.falcon.st_shift = 0x200;
-       }
-       else if (bpp <= 2) {
+       } else if (bpp <= 2) {
                bpp = 2;
                par->hw.falcon.f_shift = 0x000;
                par->hw.falcon.st_shift = 0x100;
-       }
-       else if (bpp <= 4) {
+       } else if (bpp <= 4) {
                bpp = 4;
                par->hw.falcon.f_shift = 0x000;
                par->hw.falcon.st_shift = 0x000;
-       }
-       else if (bpp <= 8) {
+       } else if (bpp <= 8) {
                bpp = 8;
                par->hw.falcon.f_shift = 0x010;
-       }
-       else if (bpp <= 16) {
-               bpp = 16; /* packed pixel mode */
-               par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */
-       }
-       else
+       } else if (bpp <= 16) {
+               bpp = 16;               /* packed pixel mode */
+               par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */
+       } else
                return -EINVAL;
        par->hw.falcon.bpp = bpp;
 
        if (mon_type == F_MON_SM || DontCalcRes) {
                /* Skip all calculations. VGA/TV/SC1224 only supported. */
                struct fb_var_screeninfo *myvar = &atafb_predefined[0];
-               
+
                if (bpp > myvar->bits_per_pixel ||
-                       var->xres > myvar->xres ||
-                       var->yres > myvar->yres)
+                   var->xres > myvar->xres ||
+                   var->yres > myvar->yres)
                        return -EINVAL;
                fbhw->get_par(par);     /* Current par will be new par */
                goto set_screen_base;   /* Don't forget this */
@@ -910,8 +1020,8 @@ static int falcon_decode_var( struct fb_var_screeninfo *var,
                yres = 400;
 
        /* 2 planes must use STE compatibility mode */
-       par->hw.falcon.ste_mode = bpp==2;
-       par->hw.falcon.mono = bpp==1;
+       par->hw.falcon.ste_mode = bpp == 2;
+       par->hw.falcon.mono = bpp == 1;
 
        /* Total and visible scanline length must be a multiple of one longword,
         * this and the console fontwidth yields the alignment for xres and
@@ -967,8 +1077,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var,
                left_margin = hsync_len = 128 / plen;
                right_margin = 0;
                /* TODO set all margins */
-       }
-       else
+       } else
 #endif
        if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
                plen = 2 * xstretch;
@@ -1002,26 +1111,24 @@ static int falcon_decode_var( struct fb_var_screeninfo *var,
                                vsync_len *= 2;
                        }
                }
-       }
-       else
-       {       /* F_MON_VGA */
+       } else {                        /* F_MON_VGA */
                if (bpp == 16)
-                       xstretch = 2; /* Double pixel width only for hicolor */
+                       xstretch = 2;   /* Double pixel width only for hicolor */
                /* Default values are used for vert./hor. timing if no pixelclock given. */
                if (var->pixclock == 0) {
                        int linesize;
 
                        /* Choose master pixelclock depending on hor. timing */
                        plen = 1 * xstretch;
-                       if ((plen * xres + f25.right+f25.hsync+f25.left) *
+                       if ((plen * xres + f25.right + f25.hsync + f25.left) *
                            fb_info.monspecs.hfmin < f25.f)
                                pclock = &f25;
-                       else if ((plen * xres + f32.right+f32.hsync+f32.left) * 
-                           fb_info.monspecs.hfmin < f32.f)
+                       else if ((plen * xres + f32.right + f32.hsync +
+                                 f32.left) * fb_info.monspecs.hfmin < f32.f)
                                pclock = &f32;
-                       else if ((plen * xres + fext.right+fext.hsync+fext.left) * 
-                           fb_info.monspecs.hfmin < fext.f
-                                && fext.f)
+                       else if ((plen * xres + fext.right + fext.hsync +
+                                 fext.left) * fb_info.monspecs.hfmin < fext.f &&
+                                fext.f)
                                pclock = &fext;
                        else
                                return -EINVAL;
@@ -1033,22 +1140,24 @@ static int falcon_decode_var( struct fb_var_screeninfo *var,
                        upper_margin = 31;
                        lower_margin = 11;
                        vsync_len = 3;
-               }
-               else {
+               } else {
                        /* Choose largest pixelclock <= wanted clock */
                        int i;
                        unsigned long pcl = ULONG_MAX;
                        pclock = 0;
-                       for (i=1; i <= 4; i *= 2) {
-                               if (f25.t*i >= var->pixclock && f25.t*i < pcl) {
+                       for (i = 1; i <= 4; i *= 2) {
+                               if (f25.t * i >= var->pixclock &&
+                                   f25.t * i < pcl) {
                                        pcl = f25.t * i;
                                        pclock = &f25;
                                }
-                               if (f32.t*i >= var->pixclock && f32.t*i < pcl) {
+                               if (f32.t * i >= var->pixclock &&
+                                   f32.t * i < pcl) {
                                        pcl = f32.t * i;
                                        pclock = &f32;
                                }
-                               if (fext.t && fext.t*i >= var->pixclock && fext.t*i < pcl) {
+                               if (fext.t && fext.t * i >= var->pixclock &&
+                                   fext.t * i < pcl) {
                                        pcl = fext.t * i;
                                        pclock = &fext;
                                }
@@ -1070,8 +1179,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var,
                                upper_margin = (upper_margin + 1) / 2;
                                lower_margin = (lower_margin + 1) / 2;
                                vsync_len = (vsync_len + 1) / 2;
-                       }
-                       else if (var->vmode & FB_VMODE_DOUBLE) {
+                       } else if (var->vmode & FB_VMODE_DOUBLE) {
                                /* External unit is [double lines per frame] */
                                upper_margin *= 2;
                                lower_margin *= 2;
@@ -1079,7 +1187,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var,
                        }
                }
                if (pclock == &fext)
-                       longoffset = 1; /* VIDEL doesn't synchronize on short offset */
+                       longoffset = 1; /* VIDEL doesn't synchronize on short offset */
        }
        /* Is video bus bandwidth (32MB/s) too low for this resolution? */
        /* this is definitely wrong if bus clock != 32MHz */
@@ -1098,7 +1206,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var,
         * between interlace and non-interlace without messing around
         * with these.
         */
-  again:
+again:
        /* Set base_offset 128 and video bus width */
        par->hw.falcon.vid_control = mon_type | f030_bus_width;
        if (!longoffset)
@@ -1112,37 +1220,34 @@ static int falcon_decode_var( struct fb_var_screeninfo *var,
        /* External or internal clock */
        par->hw.falcon.sync = pclock->sync_mask | 0x2;
        /* Pixellength and prescale */
-       par->hw.falcon.vid_mode = (2/plen) << 2;
+       par->hw.falcon.vid_mode = (2 / plen) << 2;
        if (doubleline)
                par->hw.falcon.vid_mode |= VMO_DOUBLE;
        if (interlace)
                par->hw.falcon.vid_mode |= VMO_INTER;
 
        /*********************
-       Horizontal timing: unit = [master clock cycles]
-       unit of hxx-registers: [master clock cycles * prescale]
-       Hxx-registers are 9 bit wide
-
-       1 line = ((hht + 2) * 2 * prescale) clock cycles
-
-       graphic output = hdb & 0x200 ?
-              ((hht+2)*2 - hdb + hde) * prescale - hdboff + hdeoff:
-              ( hht + 2  - hdb + hde) * prescale - hdboff + hdeoff
-       (this must be a multiple of plen*128/bpp, on VGA pixels
-        to the right may be cut off with a bigger right margin)
-
-       start of graphics relative to start of 1st halfline = hdb & 0x200 ?
-              (hdb - hht - 2) * prescale + hdboff :
-              hdb * prescale + hdboff
-
-       end of graphics relative to start of 1st halfline =
-              (hde + hht + 2) * prescale + hdeoff
-       *********************/
+        * Horizontal timing: unit = [master clock cycles]
+        * unit of hxx-registers: [master clock cycles * prescale]
+        * Hxx-registers are 9 bit wide
+        *
+        * 1 line = ((hht + 2) * 2 * prescale) clock cycles
+        *
+        * graphic output = hdb & 0x200 ?
+        *        ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff:
+        *        (hht + 2  - hdb + hde) * prescale - hdboff + hdeoff
+        * (this must be a multiple of plen*128/bpp, on VGA pixels
+        *  to the right may be cut off with a bigger right margin)
+        *
+        * start of graphics relative to start of 1st halfline = hdb & 0x200 ?
+        *        (hdb - hht - 2) * prescale + hdboff :
+        *        hdb * prescale + hdboff
+        *
+        * end of graphics relative to start of 1st halfline =
+        *        (hde + hht + 2) * prescale + hdeoff
+        *********************/
        /* Calculate VIDEL registers */
-       {
-       int hdb_off, hde_off, base_off;
-       int gstart, gend1, gend2, align;
-
+{
        prescale = hxx_prescale(&par->hw.falcon);
        base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
 
@@ -1154,8 +1259,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var,
                align = 1;
                hde_off = 0;
                hdb_off = (base_off + 16 * plen) + prescale;
-       }
-       else {
+       } else {
                align = 128 / bpp;
                hde_off = ((128 / bpp + 2) * plen);
                if (par->hw.falcon.ste_mode)
@@ -1164,23 +1268,24 @@ static int falcon_decode_var( struct fb_var_screeninfo *var,
                        hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
        }
 
-       gstart = (prescale/2 + plen * left_margin) / prescale;
+       gstart = (prescale / 2 + plen * left_margin) / prescale;
        /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
-       gend1 = gstart + ((xres + align-1) / align)*align * plen / prescale;
+       gend1 = gstart + ((xres + align - 1) / align) * align * plen / prescale;
        /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
        gend2 = gstart + xres * plen / prescale;
        par->HHT = plen * (left_margin + xres + right_margin) /
                           (2 * prescale) - 2;
 /*     par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
 
-       par->HDB = gstart - hdb_off/prescale;
+       par->HDB = gstart - hdb_off / prescale;
        par->HBE = gstart;
-       if (par->HDB < 0) par->HDB += par->HHT + 2 + 0x200;
-       par->HDE = gend1 - par->HHT - 2 - hde_off/prescale;
+       if (par->HDB < 0)
+               par->HDB += par->HHT + 2 + 0x200;
+       par->HDE = gend1 - par->HHT - 2 - hde_off / prescale;
        par->HBB = gend2 - par->HHT - 2;
 #if 0
        /* One more Videl constraint: data fetch of two lines must not overlap */
-       if ((par->HDB & 0x200)  &&  (par->HDB & ~0x200) - par->HDE <= 5) {
+       if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) {
                /* if this happens increase margins, decrease hfreq. */
        }
 #endif
@@ -1189,11 +1294,11 @@ static int falcon_decode_var( struct fb_var_screeninfo *var,
        par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
        if (par->HSS < par->HBB)
                par->HSS = par->HBB;
-       }
+}
 
        /*  check hor. frequency */
-       hfreq = pclock->f / ((par->HHT+2)*prescale*2);
-       if (hfreq > fb_info.monspecs.hfmax && mon_type!=F_MON_VGA) {
+       hfreq = pclock->f / ((par->HHT + 2) * prescale * 2);
+       if (hfreq > fb_info.monspecs.hfmax && mon_type != F_MON_VGA) {
                /* ++guenther:   ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
                /* Too high -> enlarge margin */
                left_margin += 1;
@@ -1213,12 +1318,14 @@ static int falcon_decode_var( struct fb_var_screeninfo *var,
        par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
        par->VDB = par->VBE;
        par->VDE = yres;
-       if (!interlace) par->VDE <<= 1;
-       if (doubleline) par->VDE <<= 1;  /* VDE now half lines per (half-)frame */
+       if (!interlace)
+               par->VDE <<= 1;
+       if (doubleline)
+               par->VDE <<= 1;         /* VDE now half lines per (half-)frame */
        par->VDE += par->VDB;
        par->VBB = par->VDE;
        par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
-       par->VSS = par->VFT+1 - (vsync_len * 2 - 1);
+       par->VSS = par->VFT + 1 - (vsync_len * 2 - 1);
        /* vbb,vss,vft must be even in interlace mode */
        if (interlace) {
                par->VBB++;
@@ -1229,55 +1336,53 @@ static int falcon_decode_var( struct fb_var_screeninfo *var,
        /* V-frequency check, hope I didn't create any loop here. */
        /* Interlace and doubleline are mutually exclusive. */
        vfreq = (hfreq * 2) / (par->VFT + 1);
-       if      (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
+       if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
                /* Too high -> try again with doubleline */
                doubleline = 1;
                goto again;
-       }
-       else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
+       } else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
                /* Too low -> try again with interlace */
                interlace = 1;
                goto again;
-       }
-       else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
+       } else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
                /* Doubleline too low -> clear doubleline and enlarge margins */
                int lines;
                doubleline = 0;
-               for (lines=0;
-                    (hfreq*2)/(par->VFT+1+4*lines-2*yres)>fb_info.monspecs.vfmax;
+               for (lines = 0;
+                    (hfreq * 2) / (par->VFT + 1 + 4 * lines - 2 * yres) >
+                    fb_info.monspecs.vfmax;
                     lines++)
                        ;
                upper_margin += lines;
                lower_margin += lines;
                goto again;
-       }
-       else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
+       } else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
                /* Doubleline too high -> enlarge margins */
                int lines;
-               for (lines=0;
-                    (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax;
-                    lines+=2)
+               for (lines = 0;
+                    (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
+                    fb_info.monspecs.vfmax;
+                    lines += 2)
                        ;
                upper_margin += lines;
                lower_margin += lines;
                goto again;
-       }
-       else if (vfreq > fb_info.monspecs.vfmax && interlace) {
+       } else if (vfreq > fb_info.monspecs.vfmax && interlace) {
                /* Interlace, too high -> enlarge margins */
                int lines;
-               for (lines=0;
-                    (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax;
+               for (lines = 0;
+                    (hfreq * 2) / (par->VFT + 1 + 4 * lines) >
+                    fb_info.monspecs.vfmax;
                     lines++)
                        ;
                upper_margin += lines;
                lower_margin += lines;
                goto again;
-       }
-       else if (vfreq < fb_info.monspecs.vfmin ||
-                vfreq > fb_info.monspecs.vfmax)
+       } else if (vfreq < fb_info.monspecs.vfmin ||
+                  vfreq > fb_info.monspecs.vfmax)
                return -EINVAL;
 
-  set_screen_base:
+set_screen_base:
        linelen = xres_virtual * bpp / 8;
        if (yres_virtual * linelen > screen_len && screen_len)
                return -EINVAL;
@@ -1289,11 +1394,20 @@ static int falcon_decode_var( struct fb_var_screeninfo *var,
        par->screen_base = screen_base + var->yoffset * linelen;
        par->hw.falcon.xoffset = 0;
 
+       // FIXME!!! sort of works, no crash
+       //par->next_line = linelen;
+       //par->next_plane = yres_virtual * linelen;
+       par->next_line = linelen;
+       par->next_plane = 2;
+       // crashes
+       //par->next_plane = linelen;
+       //par->next_line  = yres_virtual * linelen;
+
        return 0;
 }
 
-static int falcon_encode_var( struct fb_var_screeninfo *var,
-                                                         struct atafb_par *par )
+static int falcon_encode_var(struct fb_var_screeninfo *var,
+                            struct atafb_par *par)
 {
 /* !!! only for VGA !!! */
        int linelen;
@@ -1306,10 +1420,10 @@ static int falcon_encode_var( struct fb_var_screeninfo *var,
        var->pixclock = hw->sync & 0x1 ? fext.t :
                        hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
 
-       var->height=-1;
-       var->width=-1;
+       var->height = -1;
+       var->width = -1;
 
-       var->sync=0;
+       var->sync = 0;
        if (hw->vid_control & VCO_HSYPOS)
                var->sync |= FB_SYNC_HOR_HIGH_ACT;
        if (hw->vid_control & VCO_VSYPOS)
@@ -1320,7 +1434,7 @@ static int falcon_encode_var( struct fb_var_screeninfo *var,
                var->vmode |= FB_VMODE_INTERLACED;
        if (hw->vid_mode & VMO_DOUBLE)
                var->vmode |= FB_VMODE_DOUBLE;
-       
+
        /* visible y resolution:
         * Graphics display starts at line VDB and ends at line
         * VDE. If interlace mode off unit of VC-registers is
@@ -1332,14 +1446,15 @@ static int falcon_encode_var( struct fb_var_screeninfo *var,
        if (var->vmode & FB_VMODE_DOUBLE)
                var->yres >>= 1;
 
-       /* to get bpp, we must examine f_shift and st_shift.
+       /*
+        * to get bpp, we must examine f_shift and st_shift.
         * f_shift is valid if any of bits no. 10, 8 or 4
         * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
         * if bit 10 set then bit 8 and bit 4 don't care...
         * If all these bits are 0 get display depth from st_shift
         * (as for ST and STE)
         */
-       if (hw->f_shift & 0x400)                /* 2 colors */
+       if (hw->f_shift & 0x400)        /* 2 colors */
                var->bits_per_pixel = 1;
        else if (hw->f_shift & 0x100)   /* hicolor */
                var->bits_per_pixel = 16;
@@ -1349,7 +1464,7 @@ static int falcon_encode_var( struct fb_var_screeninfo *var,
                var->bits_per_pixel = 4;
        else if (hw->st_shift == 0x100)
                var->bits_per_pixel = 2;
-       else /* if (hw->st_shift == 0x200) */
+       else                            /* if (hw->st_shift == 0x200) */
                var->bits_per_pixel = 1;
 
        var->xres = hw->line_width * 16 / var->bits_per_pixel;
@@ -1358,42 +1473,42 @@ static int falcon_encode_var( struct fb_var_screeninfo *var,
                var->xres_virtual += 16;
 
        if (var->bits_per_pixel == 16) {
-               var->red.offset=11;
-               var->red.length=5;
-               var->red.msb_right=0;
-               var->green.offset=5;
-               var->green.length=6;
-               var->green.msb_right=0;
-               var->blue.offset=0;
-               var->blue.length=5;
-               var->blue.msb_right=0;
-       }
-       else {
-               var->red.offset=0;
+               var->red.offset = 11;
+               var->red.length = 5;
+               var->red.msb_right = 0;
+               var->green.offset = 5;
+               var->green.length = 6;
+               var->green.msb_right = 0;
+               var->blue.offset = 0;
+               var->blue.length = 5;
+               var->blue.msb_right = 0;
+       } else {
+               var->red.offset = 0;
                var->red.length = hw->ste_mode ? 4 : 6;
-               var->red.msb_right=0;
-               var->grayscale=0;
-               var->blue=var->green=var->red;
+               if (var->red.length > var->bits_per_pixel)
+                       var->red.length = var->bits_per_pixel;
+               var->red.msb_right = 0;
+               var->grayscale = 0;
+               var->blue = var->green = var->red;
        }
-       var->transp.offset=0;
-       var->transp.length=0;
-       var->transp.msb_right=0;
+       var->transp.offset = 0;
+       var->transp.length = 0;
+       var->transp.msb_right = 0;
 
        linelen = var->xres_virtual * var->bits_per_pixel / 8;
        if (screen_len) {
                if (par->yres_virtual)
                        var->yres_virtual = par->yres_virtual;
                else
-                       /* yres_virtual==0 means use maximum */
+                       /* yres_virtual == 0 means use maximum */
                        var->yres_virtual = screen_len / linelen;
-       }
-       else {
+       } else {
                if (hwscroll < 0)
                        var->yres_virtual = 2 * var->yres;
                else
-                       var->yres_virtual=var->yres+hwscroll * 16;
+                       var->yres_virtual = var->yres + hwscroll * 16;
        }
-       var->xoffset=0; /* TODO change this */
+       var->xoffset = 0;               /* TODO change this */
 
        /* hdX-offsets */
        prescale = hxx_prescale(hw);
@@ -1402,8 +1517,7 @@ static int falcon_encode_var( struct fb_var_screeninfo *var,
        if (hw->f_shift & 0x100) {
                hde_off = 0;
                hdb_off = (base_off + 16 * plen) + prescale;
-       }
-       else {
+       } else {
                hde_off = ((128 / var->bits_per_pixel + 2) * plen);
                if (hw->ste_mode)
                        hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
@@ -1415,8 +1529,8 @@ static int falcon_encode_var( struct fb_var_screeninfo *var,
 
        /* Right margin includes hsync */
        var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
-                                          (hw->hdb & 0x200 ? 2+hw->hht : 0));
-       if (hw->ste_mode || mon_type!=F_MON_VGA)
+                                          (hw->hdb & 0x200 ? 2 + hw->hht : 0));
+       if (hw->ste_mode || mon_type != F_MON_VGA)
                var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
        else
                /* can't use this in ste_mode, because hbb is +1 off */
@@ -1424,15 +1538,14 @@ static int falcon_encode_var( struct fb_var_screeninfo *var,
        var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
 
        /* Lower margin includes vsync */
-       var->upper_margin = hw->vdb / 2 ;  /* round down to full lines */
-       var->lower_margin = (hw->vft+1 - hw->vde + 1) / 2; /* round up */
-       var->vsync_len    = (hw->vft+1 - hw->vss + 1) / 2; /* round up */
+       var->upper_margin = hw->vdb / 2;        /* round down to full lines */
+       var->lower_margin = (hw->vft + 1 - hw->vde + 1) / 2;    /* round up */
+       var->vsync_len = (hw->vft + 1 - hw->vss + 1) / 2;       /* round up */
        if (var->vmode & FB_VMODE_INTERLACED) {
                var->upper_margin *= 2;
                var->lower_margin *= 2;
                var->vsync_len *= 2;
-       }
-       else if (var->vmode & FB_VMODE_DOUBLE) {
+       } else if (var->vmode & FB_VMODE_DOUBLE) {
                var->upper_margin = (var->upper_margin + 1) / 2;
                var->lower_margin = (var->lower_margin + 1) / 2;
                var->vsync_len = (var->vsync_len + 1) / 2;
@@ -1447,20 +1560,19 @@ static int falcon_encode_var( struct fb_var_screeninfo *var,
        var->lower_margin -= var->vsync_len;
 
        if (screen_base)
-               var->yoffset=(par->screen_base - screen_base)/linelen;
+               var->yoffset = (par->screen_base - screen_base) / linelen;
        else
-               var->yoffset=0;
-       var->nonstd=0;  /* what is this for? */
-       var->activate=0;
+               var->yoffset = 0;
+       var->nonstd = 0;                /* what is this for? */
+       var->activate = 0;
        return 0;
 }
 
-
-static int f_change_mode = 0;
+static int f_change_mode;
 static struct falcon_hw f_new_mode;
-static int f_pan_display = 0;
+static int f_pan_display;
 
-static void falcon_get_par( struct atafb_par *par )
+static void falcon_get_par(struct atafb_par *par)
 {
        unsigned long addr;
        struct falcon_hw *hw = &par->hw.falcon;
@@ -1492,12 +1604,12 @@ static void falcon_get_par( struct atafb_par *par )
        par->screen_base = phys_to_virt(addr);
 
        /* derived parameters */
-       hw->ste_mode = (hw->f_shift & 0x510)==0 && hw->st_shift==0x100;
+       hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100;
        hw->mono = (hw->f_shift & 0x400) ||
-                  ((hw->f_shift & 0x510)==0 && hw->st_shift==0x200);
+                  ((hw->f_shift & 0x510) == 0 && hw->st_shift == 0x200);
 }
 
-static void falcon_set_par( struct atafb_par *par )
+static void falcon_set_par(struct atafb_par *par)
 {
        f_change_mode = 0;
 
@@ -1519,8 +1631,7 @@ static void falcon_set_par( struct atafb_par *par )
        f_change_mode = 1;
 }
 
-
-static irqreturn_t falcon_vbl_switcher( int irq, void *dummy )
+static irqreturn_t falcon_vbl_switcher(int irq, void *dummy)
 {
        struct falcon_hw *hw = &f_new_mode;
 
@@ -1529,11 +1640,10 @@ static irqreturn_t falcon_vbl_switcher( int irq, void *dummy )
 
                if (hw->sync & 0x1) {
                        /* Enable external pixelclock. This code only for ScreenWonder */
-                       *(volatile unsigned short*)0xffff9202 = 0xffbf;
-               }
-               else {
+                       *(volatile unsigned short *)0xffff9202 = 0xffbf;
+               } else {
                        /* Turn off external clocks. Read sets all output bits to 1. */
-                       *(volatile unsigned short*)0xffff9202;
+                       *(volatile unsigned short *)0xffff9202;
                }
                shifter.syncmode = hw->sync;
 
@@ -1550,15 +1660,14 @@ static irqreturn_t falcon_vbl_switcher( int irq, void *dummy )
                videl.vde = hw->vde;
                videl.vss = hw->vss;
 
-               videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */
+               videl.f_shift = 0;      /* write enables Falcon palette, 0: 4 planes */
                if (hw->ste_mode) {
-                       videl.st_shift = hw->st_shift; /* write enables STE palette */
-               }
-               else {
+                       videl.st_shift = hw->st_shift;  /* write enables STE palette */
+               } else {
                        /* IMPORTANT:
-                        * set st_shift 0, so we can tell the screen-depth if f_shift==0.
+                        * set st_shift 0, so we can tell the screen-depth if f_shift == 0.
                         * Writing 0 to f_shift enables 4 plane Falcon mode but
-                        * doesn't set st_shift. st_shift!=0 (!=4planes) is impossible
+                        * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible
                         * with Falcon palette.
                         */
                        videl.st_shift = 0;
@@ -1580,12 +1689,13 @@ static irqreturn_t falcon_vbl_switcher( int irq, void *dummy )
        return IRQ_HANDLED;
 }
 
-
-static int falcon_pan_display( struct fb_var_screeninfo *var,
-                                                          struct atafb_par *par )
+static int falcon_pan_display(struct fb_var_screeninfo *var,
+                             struct fb_info *info)
 {
+       struct atafb_par *par = (struct atafb_par *)info->par;
+
        int xoffset;
-       int bpp = fb_display[fb_info.currcon].var.bits_per_pixel;
+       int bpp = info->var.bits_per_pixel;
 
        if (bpp == 1)
                var->xoffset = up(var->xoffset, 32);
@@ -1596,45 +1706,24 @@ static int falcon_pan_display( struct fb_var_screeninfo *var,
                var->xoffset = up(var->xoffset, 2);
        }
        par->hw.falcon.line_offset = bpp *
-               (fb_display[fb_info.currcon].var.xres_virtual - fb_display[fb_info.currcon].var.xres) / 16;
+               (info->var.xres_virtual - info->var.xres) / 16;
        if (par->hw.falcon.xoffset)
                par->hw.falcon.line_offset -= bpp;
        xoffset = var->xoffset - par->hw.falcon.xoffset;
 
        par->screen_base = screen_base +
-               (var->yoffset * fb_display[fb_info.currcon].var.xres_virtual + xoffset) * bpp / 8;
+               (var->yoffset * info->var.xres_virtual + xoffset) * bpp / 8;
        if (fbhw->set_screen_base)
-               fbhw->set_screen_base (par->screen_base);
+               fbhw->set_screen_base(par->screen_base);
        else
-               return -EINVAL; /* shouldn't happen */
+               return -EINVAL;         /* shouldn't happen */
        f_pan_display = 1;
        return 0;
 }
 
-
-static int falcon_getcolreg( unsigned regno, unsigned *red,
-                                unsigned *green, unsigned *blue,
-                                unsigned *transp, struct fb_info *info )
-{      unsigned long col;
-       
-       if (regno > 255)
-               return 1;
-       /* This works in STE-mode (with 4bit/color) since f030_col-registers
-        * hold up to 6bit/color.
-        * Even with hicolor r/g/b=5/6/5 bit!
-        */
-       col = f030_col[regno];
-       *red = (col >> 16) & 0xff00;
-       *green = (col >> 8) & 0xff00;
-       *blue = (col << 8) & 0xff00;
-       *transp = 0;
-       return 0;
-}
-
-
-static int falcon_setcolreg( unsigned regno, unsigned red,
-                                                        unsigned green, unsigned blue,
-                                                        unsigned transp, struct fb_info *info )
+static int falcon_setcolreg(unsigned int regno, unsigned int red,
+                           unsigned int green, unsigned int blue,
+                           unsigned int transp, struct fb_info *info)
 {
        if (regno > 255)
                return 1;
@@ -1655,13 +1744,12 @@ static int falcon_setcolreg( unsigned regno, unsigned red,
        return 0;
 }
 
-
-static int falcon_blank( int blank_mode )
+static int falcon_blank(int blank_mode)
 {
-/* ++guenther: we can switch off graphics by changing VDB and VDE,
- * so VIDEL doesn't hog the bus while saving.
- * (this may affect usleep()).
- */
+       /* ++guenther: we can switch off graphics by changing VDB and VDE,
       * so VIDEL doesn't hog the bus while saving.
       * (this may affect usleep()).
       */
        int vdb, vss, hbe, hss;
 
        if (mon_type == F_MON_SM)       /* this doesn't work on SM124 */
@@ -1694,14 +1782,13 @@ static int falcon_blank( int blank_mode )
        return 0;
 }
 
-static int falcon_detect( void )
+static int falcon_detect(void)
 {
        struct atafb_par par;
        unsigned char fhw;
 
        /* Determine connected monitor and set monitor parameters */
-       fhw = *(unsigned char*)0xffff8006;
+       fhw = *(unsigned char *)0xffff8006;
        mon_type = fhw >> 6 & 0x3;
        /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
        f030_bus_width = fhw << 6 & 0x80;
@@ -1715,7 +1802,7 @@ static int falcon_detect( void )
        case F_MON_SC:
        case F_MON_TV:
                /* PAL...NTSC */
-               fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */
+               fb_info.monspecs.vfmin = 49;    /* not 50, since TOS defaults to 49.9x Hz */
                fb_info.monspecs.vfmax = 60;
                fb_info.monspecs.hfmin = 15620;
                fb_info.monspecs.hfmax = 15755;
@@ -1740,13 +1827,12 @@ static int falcon_detect( void )
 
 #ifdef ATAFB_STE
 
-static int stste_encode_fix( struct fb_fix_screeninfo *fix,
-                                                        struct atafb_par *par )
-
+static int stste_encode_fix(struct fb_fix_screeninfo *fix,
+                           struct atafb_par *par)
 {
        int mode;
 
-       strcpy(fix->id,"Atari Builtin");
+       strcpy(fix->id, "Atari Builtin");
        fix->smem_start = (unsigned long)real_screen_base;
        fix->smem_len = screen_len;
        fix->type = FB_TYPE_INTERLEAVED_PLANES;
@@ -1771,43 +1857,40 @@ static int stste_encode_fix( struct fb_fix_screeninfo *fix,
        return 0;
 }
 
-
-static int stste_decode_var( struct fb_var_screeninfo *var,
-                                                 struct atafb_par *par )
+static int stste_decode_var(struct fb_var_screeninfo *var,
+                           struct atafb_par *par)
 {
-       int xres=var->xres;
-       int yres=var->yres;
-       int bpp=var->bits_per_pixel;
+       int xres = var->xres;
+       int yres = var->yres;
+       int bpp = var->bits_per_pixel;
        int linelen;
        int yres_virtual = var->yres_virtual;
 
        if (mono_moni) {
                if (bpp > 1 || xres > sttt_xres || yres > st_yres)
                        return -EINVAL;
-               par->hw.st.mode=ST_HIGH;
-               xres=sttt_xres;
-               yres=st_yres;
-               bpp=1;
+               par->hw.st.mode = ST_HIGH;
+               xres = sttt_xres;
+               yres = st_yres;
+               bpp = 1;
        } else {
                if (bpp > 4 || xres > sttt_xres || yres > st_yres)
                        return -EINVAL;
                if (bpp > 2) {
-                       if (xres > sttt_xres/2 || yres > st_yres/2)
+                       if (xres > sttt_xres / 2 || yres > st_yres / 2)
                                return -EINVAL;
-                       par->hw.st.mode=ST_LOW;
-                       xres=sttt_xres/2;
-                       yres=st_yres/2;
-                       bpp=4;
-               }
-               else if (bpp > 1) {
-                       if (xres > sttt_xres || yres > st_yres/2)
+                       par->hw.st.mode = ST_LOW;
+                       xres = sttt_xres / 2;
+                       yres = st_yres / 2;
+                       bpp = 4;
+               } else if (bpp > 1) {
+                       if (xres > sttt_xres || yres > st_yres / 2)
                                return -EINVAL;
-                       par->hw.st.mode=ST_MID;
-                       xres=sttt_xres;
-                       yres=st_yres/2;
-                       bpp=2;
-               }
-               else
+                       par->hw.st.mode = ST_MID;
+                       xres = sttt_xres;
+                       yres = st_yres / 2;
+                       bpp = 2;
+               } else
                        return -EINVAL;
        }
        if (yres_virtual <= 0)
@@ -1815,10 +1898,10 @@ static int stste_decode_var( struct fb_var_screeninfo *var,
        else if (yres_virtual < yres)
                yres_virtual = yres;
        if (var->sync & FB_SYNC_EXT)
-               par->hw.st.sync=(par->hw.st.sync & ~1) | 1;
+               par->hw.st.sync = (par->hw.st.sync & ~1) | 1;
        else
-               par->hw.st.sync=(par->hw.st.sync & ~1);
-       linelen=xres*bpp/8;
+               par->hw.st.sync = (par->hw.st.sync & ~1);
+       linelen = xres * bpp / 8;
        if (yres_virtual * linelen > screen_len && screen_len)
                return -EINVAL;
        if (yres * linelen > screen_len && screen_len)
@@ -1826,93 +1909,91 @@ static int stste_decode_var( struct fb_var_screeninfo *var,
        if (var->yoffset + yres > yres_virtual && yres_virtual)
                return -EINVAL;
        par->yres_virtual = yres_virtual;
-       par->screen_base=screen_base+ var->yoffset*linelen;
+       par->screen_base = screen_base + var->yoffset * linelen;
        return 0;
 }
 
-static int stste_encode_var( struct fb_var_screeninfo *var,
-                                                 struct atafb_par *par )
+static int stste_encode_var(struct fb_var_screeninfo *var,
+                           struct atafb_par *par)
 {
        int linelen;
        memset(var, 0, sizeof(struct fb_var_screeninfo));
-       var->red.offset=0;
+       var->red.offset = 0;
        var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
-       var->red.msb_right=0;
-       var->grayscale=0;
+       var->red.msb_right = 0;
+       var->grayscale = 0;
 
-       var->pixclock=31041;
-       var->left_margin=120;           /* these are incorrect */
-       var->right_margin=100;
-       var->upper_margin=8;
-       var->lower_margin=16;
-       var->hsync_len=140;
-       var->vsync_len=30;
+       var->pixclock = 31041;
+       var->left_margin = 120;         /* these are incorrect */
+       var->right_margin = 100;
+       var->upper_margin = 8;
+       var->lower_margin = 16;
+       var->hsync_len = 140;
+       var->vsync_len = 30;
 
-       var->height=-1;
-       var->width=-1;
+       var->height = -1;
+       var->width = -1;
 
        if (!(par->hw.st.sync & 1))
-               var->sync=0;
+               var->sync = 0;
        else
-               var->sync=FB_SYNC_EXT;
+               var->sync = FB_SYNC_EXT;
 
        switch (par->hw.st.mode & 3) {
        case ST_LOW:
-               var->xres=sttt_xres/2;
-               var->yres=st_yres/2;
-               var->bits_per_pixel=4;
+               var->xres = sttt_xres / 2;
+               var->yres = st_yres / 2;
+               var->bits_per_pixel = 4;
                break;
        case ST_MID:
-               var->xres=sttt_xres;
-               var->yres=st_yres/2;
-               var->bits_per_pixel=2;
+               var->xres = sttt_xres;
+               var->yres = st_yres / 2;
+               var->bits_per_pixel = 2;
                break;
        case ST_HIGH:
-               var->xres=sttt_xres;
-               var->yres=st_yres;
-               var->bits_per_pixel=1;
+               var->xres = sttt_xres;
+               var->yres = st_yres;
+               var->bits_per_pixel = 1;
                break;
-       }               
-       var->blue=var->green=var->red;
-       var->transp.offset=0;
-       var->transp.length=0;
-       var->transp.msb_right=0;
-       var->xres_virtual=sttt_xres_virtual;
-       linelen=var->xres_virtual * var->bits_per_pixel / 8;
-       ovsc_addlen=linelen*(sttt_yres_virtual - st_yres);
-       
-       if (! use_hwscroll)
-               var->yres_virtual=var->yres;
+       }
+       var->blue = var->green = var->red;
+       var->transp.offset = 0;
+       var->transp.length = 0;
+       var->transp.msb_right = 0;
+       var->xres_virtual = sttt_xres_virtual;
+       linelen = var->xres_virtual * var->bits_per_pixel / 8;
+       ovsc_addlen = linelen * (sttt_yres_virtual - st_yres);
+
+       if (!use_hwscroll)
+               var->yres_virtual = var->yres;
        else if (screen_len) {
                if (par->yres_virtual)
                        var->yres_virtual = par->yres_virtual;
                else
-                       /* yres_virtual==0 means use maximum */
+                       /* yres_virtual == 0 means use maximum */
                        var->yres_virtual = screen_len / linelen;
-       }
-       else {
+       } else {
                if (hwscroll < 0)
                        var->yres_virtual = 2 * var->yres;
                else
-                       var->yres_virtual=var->yres+hwscroll * 16;
+                       var->yres_virtual = var->yres + hwscroll * 16;
        }
-       var->xoffset=0;
+       var->xoffset = 0;
        if (screen_base)
-               var->yoffset=(par->screen_base - screen_base)/linelen;
+               var->yoffset = (par->screen_base - screen_base) / linelen;
        else
-               var->yoffset=0;
-       var->nonstd=0;
-       var->activate=0;
-       var->vmode=FB_VMODE_NONINTERLACED;
+               var->yoffset = 0;
+       var->nonstd = 0;
+       var->activate = 0;
+       var->vmode = FB_VMODE_NONINTERLACED;
        return 0;
 }
 
-
-static void stste_get_par( struct atafb_par *par )
+static void stste_get_par(struct atafb_par *par)
 {
        unsigned long addr;
-       par->hw.st.mode=shifter_tt.st_shiftmode;
-       par->hw.st.sync=shifter.syncmode;
+       par->hw.st.mode = shifter_tt.st_shiftmode;
+       par->hw.st.sync = shifter.syncmode;
        addr = ((shifter.bas_hi & 0xff) << 16) |
               ((shifter.bas_md & 0xff) << 8);
        if (ATARIHW_PRESENT(EXTD_SHIFTER))
@@ -1920,55 +2001,18 @@ static void stste_get_par( struct atafb_par *par )
        par->screen_base = phys_to_virt(addr);
 }
 
-static void stste_set_par( struct atafb_par *par )
+static void stste_set_par(struct atafb_par *par)
 {
-       shifter_tt.st_shiftmode=par->hw.st.mode;
-       shifter.syncmode=par->hw.st.sync;
+       shifter_tt.st_shiftmode = par->hw.st.mode;
+       shifter.syncmode = par->hw.st.sync;
        /* only set screen_base if really necessary */
        if (current_par.screen_base != par->screen_base)
                fbhw->set_screen_base(par->screen_base);
 }
 
-
-static int stste_getcolreg(unsigned regno, unsigned *red,
-                          unsigned *green, unsigned *blue,
-                          unsigned *transp, struct fb_info *info)
-{
-       unsigned col, t;
-       
-       if (regno > 15)
-               return 1;
-       col = shifter_tt.color_reg[regno];
-       if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
-               t = ((col >> 7) & 0xe) | ((col >> 11) & 1);
-               t |= t << 4;
-               *red = t | (t << 8);
-               t = ((col >> 3) & 0xe) | ((col >> 7) & 1);
-               t |= t << 4;
-               *green = t | (t << 8);
-               t = ((col << 1) & 0xe) | ((col >> 3) & 1);
-               t |= t << 4;
-               *blue = t | (t << 8);
-       }
-       else {
-               t = (col >> 7) & 0xe;
-               t |= t << 4;
-               *red = t | (t << 8);
-               t = (col >> 3) & 0xe;
-               t |= t << 4;
-               *green = t | (t << 8);
-               t = (col << 1) & 0xe;
-               t |= t << 4;
-               *blue = t | (t << 8);
-       }
-       *transp = 0;
-       return 0;
-}
-
-
-static int stste_setcolreg(unsigned regno, unsigned red,
-                          unsigned green, unsigned blue,
-                          unsigned transp, struct fb_info *info)
+static int stste_setcolreg(unsigned int regno, unsigned int red,
+                          unsigned int green, unsigned int blue,
+                          unsigned int transp, struct fb_info *info)
 {
        if (regno > 15)
                return 1;
@@ -1988,10 +2032,9 @@ static int stste_setcolreg(unsigned regno, unsigned red,
        return 0;
 }
 
-                                                 
-static int stste_detect( void )
-
-{      struct atafb_par par;
+static int stste_detect(void)
+{
+       struct atafb_par par;
 
        /* Determine the connected monitor: The DMA sound must be
         * disabled before reading the MFP GPIP, because the Sound
@@ -1999,7 +2042,7 @@ static int stste_detect( void )
         */
        if (ATARIHW_PRESENT(PCM_8BIT)) {
                tt_dmasnd.ctrl = DMASND_CTRL_OFF;
-               udelay(20);     /* wait a while for things to settle down */
+               udelay(20);             /* wait a while for things to settle down */
        }
        mono_moni = (mfp.par_dt_reg & 0x80) == 0;
 
@@ -2014,12 +2057,12 @@ static int stste_detect( void )
 static void stste_set_screen_base(void *s_base)
 {
        unsigned long addr;
-       addr= virt_to_phys(s_base);
+       addr = virt_to_phys(s_base);
        /* Setup Screen Memory */
-       shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
-       shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
+       shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
+       shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
        if (ATARIHW_PRESENT(EXTD_SHIFTER))
-               shifter.bas_lo=(unsigned char)  (addr & 0x0000ff);
+               shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
 }
 
 #endif /* ATAFB_STE */
@@ -2045,51 +2088,49 @@ static void stste_set_screen_base(void *s_base)
 /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
 static void st_ovsc_switch(void)
 {
-    unsigned long flags;
-    register unsigned char old, new;
+       unsigned long flags;
+       register unsigned char old, new;
 
-    if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
-       return;
-    local_irq_save(flags);
-
-    mfp.tim_ct_b = 0x10;
-    mfp.active_edge |= 8;
-    mfp.tim_ct_b = 0;
-    mfp.tim_dt_b = 0xf0;
-    mfp.tim_ct_b = 8;
-    while (mfp.tim_dt_b > 1)   /* TOS does it this way, don't ask why */
-       ;
-    new = mfp.tim_dt_b;
-    do {
-       udelay(LINE_DELAY);
-       old = new;
+       if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
+               return;
+       local_irq_save(flags);
+
+       mfp.tim_ct_b = 0x10;
+       mfp.active_edge |= 8;
+       mfp.tim_ct_b = 0;
+       mfp.tim_dt_b = 0xf0;
+       mfp.tim_ct_b = 8;
+       while (mfp.tim_dt_b > 1)        /* TOS does it this way, don't ask why */
+               ;
        new = mfp.tim_dt_b;
-    } while (old != new);
-    mfp.tim_ct_b = 0x10;
-    udelay(SYNC_DELAY);
-
-    if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
-       acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
-    if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
-       acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
-    if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
-       sound_ym.rd_data_reg_sel = 14;
-       sound_ym.wd_data = sound_ym.rd_data_reg_sel |
-                          ((atari_switches&ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
-                          ((atari_switches&ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
-    }
-    local_irq_restore(flags);
+       do {
+               udelay(LINE_DELAY);
+               old = new;
+               new = mfp.tim_dt_b;
+       } while (old != new);
+       mfp.tim_ct_b = 0x10;
+       udelay(SYNC_DELAY);
+
+       if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
+               acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
+       if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
+               acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
+       if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
+               sound_ym.rd_data_reg_sel = 14;
+               sound_ym.wd_data = sound_ym.rd_data_reg_sel |
+                                  ((atari_switches & ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
+                                  ((atari_switches & ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
+       }
+       local_irq_restore(flags);
 }
 
 /* ------------------- External Video ---------------------- */
 
 #ifdef ATAFB_EXT
 
-static int ext_encode_fix( struct fb_fix_screeninfo *fix,
-                                                  struct atafb_par *par )
-
+static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
 {
-       strcpy(fix->id,"Unknown Extern");
+       strcpy(fix->id, "Unknown Extern");
        fix->smem_start = (unsigned long)external_addr;
        fix->smem_len = PAGE_ALIGN(external_len);
        if (external_depth == 1) {
@@ -2099,31 +2140,29 @@ static int ext_encode_fix( struct fb_fix_screeninfo *fix,
                fix->visual =
                        (external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
                         external_pmode == FB_TYPE_PACKED_PIXELS) ?
-                               FB_VISUAL_MONO10 :
-                                       FB_VISUAL_MONO01;
-       }
-       else {
+                               FB_VISUAL_MONO10 : FB_VISUAL_MONO01;
+       } else {
                /* Use STATIC if we don't know how to access color registers */
                int visual = external_vgaiobase ?
                                         FB_VISUAL_PSEUDOCOLOR :
                                         FB_VISUAL_STATIC_PSEUDOCOLOR;
                switch (external_pmode) {
-                   case -1:              /* truecolor */
-                       fix->type=FB_TYPE_PACKED_PIXELS;
-                       fix->visual=FB_VISUAL_TRUECOLOR;
+               case -1:                /* truecolor */
+                       fix->type = FB_TYPE_PACKED_PIXELS;
+                       fix->visual = FB_VISUAL_TRUECOLOR;
                        break;
-                   case FB_TYPE_PACKED_PIXELS:
-                       fix->type=FB_TYPE_PACKED_PIXELS;
-                       fix->visual=visual;
+               case FB_TYPE_PACKED_PIXELS:
+                       fix->type = FB_TYPE_PACKED_PIXELS;
+                       fix->visual = visual;
                        break;
-                   case FB_TYPE_PLANES:
-                       fix->type=FB_TYPE_PLANES;
-                       fix->visual=visual;
+               case FB_TYPE_PLANES:
+                       fix->type = FB_TYPE_PLANES;
+                       fix->visual = visual;
                        break;
-                   case FB_TYPE_INTERLEAVED_PLANES:
-                       fix->type=FB_TYPE_INTERLEAVED_PLANES;
-                       fix->type_aux=2;
-                       fix->visual=visual;
+               case FB_TYPE_INTERLEAVED_PLANES:
+                       fix->type = FB_TYPE_INTERLEAVED_PLANES;
+                       fix->type_aux = 2;
+                       fix->visual = visual;
                        break;
                }
        }
@@ -2134,137 +2173,112 @@ static int ext_encode_fix( struct fb_fix_screeninfo *fix,
        return 0;
 }
 
-
-static int ext_decode_var( struct fb_var_screeninfo *var,
-                                                  struct atafb_par *par )
+static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
 {
        struct fb_var_screeninfo *myvar = &atafb_predefined[0];
-       
+
        if (var->bits_per_pixel > myvar->bits_per_pixel ||
-               var->xres > myvar->xres ||
-               var->xres_virtual > myvar->xres_virtual ||
-               var->yres > myvar->yres ||
-               var->xoffset > 0 ||
-               var->yoffset > 0)
+           var->xres > myvar->xres ||
+           var->xres_virtual > myvar->xres_virtual ||
+           var->yres > myvar->yres ||
+           var->xoffset > 0 ||
+           var->yoffset > 0)
                return -EINVAL;
        return 0;
 }
 
-
-static int ext_encode_var( struct fb_var_screeninfo *var,
-                                                  struct atafb_par *par )
+static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
 {
        memset(var, 0, sizeof(struct fb_var_screeninfo));
-       var->red.offset=0;
-       var->red.length=(external_pmode == -1) ? external_depth/3 : 
+       var->red.offset = 0;
+       var->red.length = (external_pmode == -1) ? external_depth / 3 :
                        (external_vgaiobase ? external_bitspercol : 0);
-       var->red.msb_right=0;
-       var->grayscale=0;
+       var->red.msb_right = 0;
+       var->grayscale = 0;
 
-       var->pixclock=31041;
-       var->left_margin=120;           /* these are surely incorrect   */
-       var->right_margin=100;
-       var->upper_margin=8;
-       var->lower_margin=16;
-       var->hsync_len=140;
-       var->vsync_len=30;
+       var->pixclock = 31041;
+       var->left_margin = 120;         /* these are surely incorrect */
+       var->right_margin = 100;
+       var->upper_margin = 8;
+       var->lower_margin = 16;
+       var->hsync_len = 140;
+       var->vsync_len = 30;
 
-       var->height=-1;
-       var->width=-1;
+       var->height = -1;
+       var->width = -1;
 
-       var->sync=0;
+       var->sync = 0;
 
        var->xres = external_xres;
        var->yres = external_yres;
        var->xres_virtual = external_xres_virtual;
        var->bits_per_pixel = external_depth;
-       
-       var->blue=var->green=var->red;
-       var->transp.offset=0;
-       var->transp.length=0;
-       var->transp.msb_right=0;
-       var->yres_virtual=var->yres;
-       var->xoffset=0;
-       var->yoffset=0;
-       var->nonstd=0;
-       var->activate=0;
-       var->vmode=FB_VMODE_NONINTERLACED;
+
+       var->blue = var->green = var->red;
+       var->transp.offset = 0;
+       var->transp.length = 0;
+       var->transp.msb_right = 0;
+       var->yres_virtual = var->yres;
+       var->xoffset = 0;
+       var->yoffset = 0;
+       var->nonstd = 0;
+       var->activate = 0;
+       var->vmode = FB_VMODE_NONINTERLACED;
        return 0;
 }
 
-
-static void ext_get_par( struct atafb_par *par )
+static void ext_get_par(struct atafb_par *par)
 {
        par->screen_base = external_addr;
 }
 
-static void ext_set_par( struct atafb_par *par )
+static void ext_set_par(struct atafb_par *par)
 {
 }
 
 #define OUTB(port,val) \
-       *((unsigned volatile char *) ((port)+external_vgaiobase))=(val)
+       *((unsigned volatile char *) ((port)+external_vgaiobase)) = (val)
 #define INB(port) \
        (*((unsigned volatile char *) ((port)+external_vgaiobase)))
-#define DACDelay                               \
+#define DACDelay                               \
        do {                                    \
-               unsigned char tmp=INB(0x3da);   \
-               tmp=INB(0x3da);                 \
+               unsigned char tmp = INB(0x3da); \
+               tmp = INB(0x3da);                       \
        } while (0)
 
-static int ext_getcolreg( unsigned regno, unsigned *red,
-                                                 unsigned *green, unsigned *blue,
-                                                 unsigned *transp, struct fb_info *info )
+static int ext_setcolreg(unsigned int regno, unsigned int red,
+                        unsigned int green, unsigned int blue,
+                        unsigned int transp, struct fb_info *info)
 {
-       if (! external_vgaiobase)
-               return 1;
-
-           *red   = ext_color[regno].red;
-           *green = ext_color[regno].green;
-           *blue  = ext_color[regno].blue;
-           *transp=0;
-           return 0;
-}
-       
-static int ext_setcolreg( unsigned regno, unsigned red,
-                                                 unsigned green, unsigned blue,
-                                                 unsigned transp, struct fb_info *info )
-
-{      unsigned char colmask = (1 << external_bitspercol) - 1;
+       unsigned char colmask = (1 << external_bitspercol) - 1;
 
-       if (! external_vgaiobase)
+       if (!external_vgaiobase)
                return 1;
 
-       ext_color[regno].red = red;
-       ext_color[regno].green = green;
-       ext_color[regno].blue = blue;
-
        switch (external_card_type) {
-         case IS_VGA:
-           OUTB(0x3c8, regno);
-           DACDelay;
-           OUTB(0x3c9, red & colmask);
-           DACDelay;
-           OUTB(0x3c9, green & colmask);
-           DACDelay;
-           OUTB(0x3c9, blue & colmask);
-           DACDelay;
-           return 0;
-
-         case IS_MV300:
-           OUTB((MV300_reg[regno] << 2)+1, red);
-           OUTB((MV300_reg[regno] << 2)+1, green);
-           OUTB((MV300_reg[regno] << 2)+1, blue);
-           return 0;
-
-         default:
-           return 1;
-         }
-}
-       
+       case IS_VGA:
+               OUTB(0x3c8, regno);
+               DACDelay;
+               OUTB(0x3c9, red & colmask);
+               DACDelay;
+               OUTB(0x3c9, green & colmask);
+               DACDelay;
+               OUTB(0x3c9, blue & colmask);
+               DACDelay;
+               return 0;
 
-static int ext_detect( void )
+       case IS_MV300:
+               OUTB((MV300_reg[regno] << 2) + 1, red);
+               OUTB((MV300_reg[regno] << 2) + 1, green);
+               OUTB((MV300_reg[regno] << 2) + 1, blue);
+               return 0;
 
+       default:
+               return 1;
+       }
+}
+
+static int ext_detect(void)
 {
        struct fb_var_screeninfo *myvar = &atafb_predefined[0];
        struct atafb_par dummy_par;
@@ -2284,213 +2298,182 @@ static int ext_detect( void )
 static void set_screen_base(void *s_base)
 {
        unsigned long addr;
-       addr= virt_to_phys(s_base);
+
+       addr = virt_to_phys(s_base);
        /* Setup Screen Memory */
-       shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
-       shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
-       shifter.bas_lo=(unsigned char)  (addr & 0x0000ff);
+       shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
+       shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
+       shifter.bas_lo = (unsigned char)(addr & 0x0000ff);
 }
 
-
-static int pan_display( struct fb_var_screeninfo *var,
-                        struct atafb_par *par )
+static int pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 {
+       struct atafb_par *par = (struct atafb_par *)info->par;
+
        if (!fbhw->set_screen_base ||
-               (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
+           (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
                return -EINVAL;
        var->xoffset = up(var->xoffset, 16);
        par->screen_base = screen_base +
-               (var->yoffset * fb_display[fb_info.currcon].var.xres_virtual + var->xoffset)
-               * fb_display[fb_info.currcon].var.bits_per_pixel / 8;
-       fbhw->set_screen_base (par->screen_base);
+               (var->yoffset * info->var.xres_virtual + var->xoffset)
+               * info->var.bits_per_pixel / 8;
+       fbhw->set_screen_base(par->screen_base);
        return 0;
 }
 
-
 /* ------------ Interfaces to hardware functions ------------ */
 
-
 #ifdef ATAFB_TT
 static struct fb_hwswitch tt_switch = {
-       tt_detect, tt_encode_fix, tt_decode_var, tt_encode_var,
-       tt_get_par, tt_set_par, tt_getcolreg, 
-       set_screen_base, NULL, pan_display
+       .detect         = tt_detect,
+       .encode_fix     = tt_encode_fix,
+       .decode_var     = tt_decode_var,
+       .encode_var     = tt_encode_var,
+       .get_par        = tt_get_par,
+       .set_par        = tt_set_par,
+       .set_screen_base = set_screen_base,
+       .pan_display    = pan_display,
 };
 #endif
 
 #ifdef ATAFB_FALCON
 static struct fb_hwswitch falcon_switch = {
-       falcon_detect, falcon_encode_fix, falcon_decode_var, falcon_encode_var,
-       falcon_get_par, falcon_set_par, falcon_getcolreg,
-       set_screen_base, falcon_blank, falcon_pan_display
+       .detect         = falcon_detect,
+       .encode_fix     = falcon_encode_fix,
+       .decode_var     = falcon_decode_var,
+       .encode_var     = falcon_encode_var,
+       .get_par        = falcon_get_par,
+       .set_par        = falcon_set_par,
+       .set_screen_base = set_screen_base,
+       .blank          = falcon_blank,
+       .pan_display    = falcon_pan_display,
 };
 #endif
 
 #ifdef ATAFB_STE
 static struct fb_hwswitch st_switch = {
-       stste_detect, stste_encode_fix, stste_decode_var, stste_encode_var,
-       stste_get_par, stste_set_par, stste_getcolreg,
-       stste_set_screen_base, NULL, pan_display
+       .detect         = stste_detect,
+       .encode_fix     = stste_encode_fix,
+       .decode_var     = stste_decode_var,
+       .encode_var     = stste_encode_var,
+       .get_par        = stste_get_par,
+       .set_par        = stste_set_par,
+       .set_screen_base = stste_set_screen_base,
+       .pan_display    = pan_display
 };
 #endif
 
 #ifdef ATAFB_EXT
 static struct fb_hwswitch ext_switch = {
-       ext_detect, ext_encode_fix, ext_decode_var, ext_encode_var,
-       ext_get_par, ext_set_par, ext_getcolreg, NULL, NULL, NULL
+       .detect         = ext_detect,
+       .encode_fix     = ext_encode_fix,
+       .decode_var     = ext_decode_var,
+       .encode_var     = ext_encode_var,
+       .get_par        = ext_get_par,
+       .set_par        = ext_set_par,
 };
 #endif
 
-
-
-static void atafb_get_par( struct atafb_par *par )
+static void ata_get_par(struct atafb_par *par)
 {
-       if (current_par_valid) {
-               *par=current_par;
-       }
+       if (current_par_valid)
+               *par = current_par;
        else
                fbhw->get_par(par);
 }
 
-
-static void atafb_set_par( struct atafb_par *par )
+static void ata_set_par(struct atafb_par *par)
 {
        fbhw->set_par(par);
-       current_par=*par;
-       current_par_valid=1;
+       current_par = *par;
+       current_par_valid = 1;
 }
 
 
-
 /* =========================================================== */
 /* ============== Hardware Independent Functions ============= */
 /* =========================================================== */
 
-
 /* used for hardware scrolling */
 
-static int
-fb_update_var(int con, struct fb_info *info)
-{
-       int off=fb_display[con].var.yoffset*fb_display[con].var.xres_virtual*
-                       fb_display[con].var.bits_per_pixel>>3;
-
-       current_par.screen_base=screen_base + off;
-
-       if (fbhw->set_screen_base)
-               fbhw->set_screen_base(current_par.screen_base);
-       return 0;
-}
-
-static int
-do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
+static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
 {
-       int err,activate;
+       int err, activate;
        struct atafb_par par;
-       if ((err=fbhw->decode_var(var, &par)))
+
+       err = fbhw->decode_var(var, &par);
+       if (err)
                return err;
-       activate=var->activate;
+       activate = var->activate;
        if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
-               atafb_set_par(&par);
+               ata_set_par(&par);
        fbhw->encode_var(var, &par);
-       var->activate=activate;
+       var->activate = activate;
        return 0;
 }
 
-static int
-atafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
 {
        struct atafb_par par;
-       if (con == -1)
-               atafb_get_par(&par);
-       else {
-         int err;
-               if ((err=fbhw->decode_var(&fb_display[con].var,&par)))
-                 return err;
-       }
+       int err;
+       // Get fix directly (case con == -1 before)??
+       err = fbhw->decode_var(&info->var, &par);
+       if (err)
+               return err;
        memset(fix, 0, sizeof(struct fb_fix_screeninfo));
        return fbhw->encode_fix(fix, &par);
 }
-       
-static int
-atafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+
+static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
        struct atafb_par par;
-       if (con == -1) {
-               atafb_get_par(&par);
-               fbhw->encode_var(var, &par);
-       }
-       else
-               *var=fb_display[con].var;
+
+       ata_get_par(&par);
+       fbhw->encode_var(var, &par);
+
        return 0;
 }
 
-static void
-atafb_set_disp(int con, struct fb_info *info)
+// No longer called by fbcon!
+// Still called by set_var internally
+
+static void atafb_set_disp(struct fb_info *info)
 {
-       struct fb_fix_screeninfo fix;
-       struct fb_var_screeninfo var;
-       struct display *display;
+       atafb_get_var(&info->var, info);
+       atafb_get_fix(&info->fix, info);
 
-       if (con >= 0)
-               display = &fb_display[con];
-       else
-               display = &disp;        /* used during initialization */
-
-       atafb_get_fix(&fix, con, info);
-       atafb_get_var(&var, con, info);
-       if (con == -1)
-               con=0;
-       info->screen_base = (void *)fix.smem_start;
-       display->visual = fix.visual;
-       display->type = fix.type;
-       display->type_aux = fix.type_aux;
-       display->ypanstep = fix.ypanstep;
-       display->ywrapstep = fix.ywrapstep;
-       display->line_length = fix.line_length;
-       if (fix.visual != FB_VISUAL_PSEUDOCOLOR &&
-               fix.visual != FB_VISUAL_DIRECTCOLOR)
-               display->can_soft_blank = 0;
-       else
-               display->can_soft_blank = 1;
-       display->inverse =
-           (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
-       switch (fix.type) {
-           case FB_TYPE_INTERLEAVED_PLANES:
-               switch (var.bits_per_pixel) {
-#ifdef FBCON_HAS_IPLAN2P2
-                   case 2:
-                       display->dispsw = &fbcon_iplan2p2;
+       info->screen_base = (void *)info->fix.smem_start;
+
+       switch (info->fix.type) {
+       case FB_TYPE_INTERLEAVED_PLANES:
+               switch (info->var.bits_per_pixel) {
+               case 2:
+                       // display->dispsw = &fbcon_iplan2p2;
                        break;
-#endif
-#ifdef FBCON_HAS_IPLAN2P4
-                   case 4:
-                       display->dispsw = &fbcon_iplan2p4;
+               case 4:
+                       // display->dispsw = &fbcon_iplan2p4;
                        break;
-#endif
-#ifdef FBCON_HAS_IPLAN2P8
-                   case 8:
-                       display->dispsw = &fbcon_iplan2p8;
+               case 8:
+                       // display->dispsw = &fbcon_iplan2p8;
                        break;
-#endif
                }
                break;
-           case FB_TYPE_PACKED_PIXELS:
-               switch (var.bits_per_pixel) {
+       case FB_TYPE_PACKED_PIXELS:
+               switch (info->var.bits_per_pixel) {
 #ifdef FBCON_HAS_MFB
-                   case 1:
-                       display->dispsw = &fbcon_mfb;
+               case 1:
+                       // display->dispsw = &fbcon_mfb;
                        break;
 #endif
 #ifdef FBCON_HAS_CFB8
-                   case 8:
-                       display->dispsw = &fbcon_cfb8;
+               case 8:
+                       // display->dispsw = &fbcon_cfb8;
                        break;
 #endif
 #ifdef FBCON_HAS_CFB16
-                   case 16:
-                       display->dispsw = &fbcon_cfb16;
-                       display->dispsw_data = fbcon_cfb16_cmap;
+               case 16:
+                       // display->dispsw = &fbcon_cfb16;
+                       // display->dispsw_data = fbcon_cfb16_cmap;
                        break;
 #endif
                }
@@ -2498,74 +2481,203 @@ atafb_set_disp(int con, struct fb_info *info)
        }
 }
 
+static int atafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                          u_int transp, struct fb_info *info)
+{
+       red >>= 8;
+       green >>= 8;
+       blue >>= 8;
+
+       return info->fbops->fb_setcolreg(regno, red, green, blue, transp, info);
+}
+
 static int
-atafb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+atafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 {
-       int err,oldxres,oldyres,oldbpp,oldxres_virtual,
-           oldyres_virtual,oldyoffset;
-       if ((err=do_fb_set_var(var, con==info->currcon)))
-               return err;
-       if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
-               oldxres=fb_display[con].var.xres;
-               oldyres=fb_display[con].var.yres;
-               oldxres_virtual=fb_display[con].var.xres_virtual;
-               oldyres_virtual=fb_display[con].var.yres_virtual;
-               oldbpp=fb_display[con].var.bits_per_pixel;
-               oldyoffset=fb_display[con].var.yoffset;
-               fb_display[con].var=*var;
-               if (oldxres != var->xres || oldyres != var->yres 
-                   || oldxres_virtual != var->xres_virtual
-                   || oldyres_virtual != var->yres_virtual
-                   || oldbpp != var->bits_per_pixel
-                   || oldyoffset != var->yoffset) {
-                       atafb_set_disp(con, info);
-                       (*fb_info.changevar)(con);
-                       fb_alloc_cmap(&fb_display[con].cmap, 0, 0);
-                       do_install_cmap(con, info);
-               }
+       int xoffset = var->xoffset;
+       int yoffset = var->yoffset;
+       int err;
+
+       if (var->vmode & FB_VMODE_YWRAP) {
+               if (yoffset < 0 || yoffset >= info->var.yres_virtual || xoffset)
+                       return -EINVAL;
+       } else {
+               if (xoffset + info->var.xres > info->var.xres_virtual ||
+                   yoffset + info->var.yres > info->var.yres_virtual)
+                       return -EINVAL;
        }
-       var->activate=0;
+
+       if (fbhw->pan_display) {
+               err = fbhw->pan_display(var, info);
+               if (err)
+                       return err;
+       } else
+               return -EINVAL;
+
+       info->var.xoffset = xoffset;
+       info->var.yoffset = yoffset;
+
+       if (var->vmode & FB_VMODE_YWRAP)
+               info->var.vmode |= FB_VMODE_YWRAP;
+       else
+               info->var.vmode &= ~FB_VMODE_YWRAP;
+
        return 0;
 }
 
+/*
+ * generic drawing routines; imageblit needs updating for image depth > 1
+ */
+
+#if BITS_PER_LONG == 32
+#define BYTES_PER_LONG 4
+#define SHIFT_PER_LONG 5
+#elif BITS_PER_LONG == 64
+#define BYTES_PER_LONG 8
+#define SHIFT_PER_LONG 6
+#else
+#define Please update me
+#endif
 
 
-static int
-atafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
+static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
-       if (con == info->currcon) /* current console ? */
-               return fb_get_cmap(cmap, kspc, fbhw->getcolreg, info);
+       struct atafb_par *par = (struct atafb_par *)info->par;
+       int x2, y2;
+       u32 width, height;
+
+       if (!rect->width || !rect->height)
+               return;
+
+       /*
+        * We could use hardware clipping but on many cards you get around
+        * hardware clipping by writing to framebuffer directly.
+        * */
+       x2 = rect->dx + rect->width;
+       y2 = rect->dy + rect->height;
+       x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
+       y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
+       width = x2 - rect->dx;
+       height = y2 - rect->dy;
+
+       if (info->var.bits_per_pixel == 1)
+               atafb_mfb_fillrect(info, par->next_line, rect->color,
+                                  rect->dy, rect->dx, height, width);
+       else if (info->var.bits_per_pixel == 2)
+               atafb_iplan2p2_fillrect(info, par->next_line, rect->color,
+                                       rect->dy, rect->dx, height, width);
+       else if (info->var.bits_per_pixel == 4)
+               atafb_iplan2p4_fillrect(info, par->next_line, rect->color,
+                                       rect->dy, rect->dx, height, width);
        else
-               if (fb_display[con].cmap.len) /* non default colormap ? */
-                       fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-               else
-                       fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-                                    cmap, kspc ? 0 : 2);
-       return 0;
+               atafb_iplan2p8_fillrect(info, par->next_line, rect->color,
+                                       rect->dy, rect->dx, height, width);
+
+       return;
 }
 
-static int
-atafb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 {
-       int xoffset = var->xoffset;
-       int yoffset = var->yoffset;
-       int err;
+       struct atafb_par *par = (struct atafb_par *)info->par;
+       int x2, y2;
+       u32 dx, dy, sx, sy, width, height;
+       int rev_copy = 0;
+
+       /* clip the destination */
+       x2 = area->dx + area->width;
+       y2 = area->dy + area->height;
+       dx = area->dx > 0 ? area->dx : 0;
+       dy = area->dy > 0 ? area->dy : 0;
+       x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
+       y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
+       width = x2 - dx;
+       height = y2 - dy;
+
+       /* update sx,sy */
+       sx = area->sx + (dx - area->dx);
+       sy = area->sy + (dy - area->dy);
+
+       /* the source must be completely inside the virtual screen */
+       if (sx < 0 || sy < 0 || (sx + width) > info->var.xres_virtual ||
+           (sy + height) > info->var.yres_virtual)
+               return;
 
-       if (   xoffset < 0 || xoffset + fb_display[con].var.xres > fb_display[con].var.xres_virtual
-           || yoffset < 0 || yoffset + fb_display[con].var.yres > fb_display[con].var.yres_virtual)
-               return -EINVAL;
+       if (dy > sy || (dy == sy && dx > sx)) {
+               dy += height;
+               sy += height;
+               rev_copy = 1;
+       }
 
-       if (con == info->currcon) {
-               if (fbhw->pan_display) {
-                       if ((err = fbhw->pan_display(var, &current_par)))
-                               return err;
+       if (info->var.bits_per_pixel == 1)
+               atafb_mfb_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
+       else if (info->var.bits_per_pixel == 2)
+               atafb_iplan2p2_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
+       else if (info->var.bits_per_pixel == 4)
+               atafb_iplan2p4_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
+       else
+               atafb_iplan2p8_copyarea(info, par->next_line, sy, sx, dy, dx, height, width);
+
+       return;
+}
+
+static void atafb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+       struct atafb_par *par = (struct atafb_par *)info->par;
+       int x2, y2;
+       unsigned long *dst;
+       int dst_idx;
+       const char *src;
+       u32 dx, dy, width, height, pitch;
+
+       /*
+        * We could use hardware clipping but on many cards you get around
+        * hardware clipping by writing to framebuffer directly like we are
+        * doing here.
+        */
+       x2 = image->dx + image->width;
+       y2 = image->dy + image->height;
+       dx = image->dx;
+       dy = image->dy;
+       x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
+       y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
+       width = x2 - dx;
+       height = y2 - dy;
+
+       if (image->depth == 1) {
+               // used for font data
+               dst = (unsigned long *)
+                       ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
+               dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
+               dst_idx += dy * par->next_line * 8 + dx;
+               src = image->data;
+               pitch = (image->width + 7) / 8;
+               while (height--) {
+
+                       if (info->var.bits_per_pixel == 1)
+                               atafb_mfb_linefill(info, par->next_line,
+                                                  dy, dx, width, src,
+                                                  image->bg_color, image->fg_color);
+                       else if (info->var.bits_per_pixel == 2)
+                               atafb_iplan2p2_linefill(info, par->next_line,
+                                                       dy, dx, width, src,
+                                                       image->bg_color, image->fg_color);
+                       else if (info->var.bits_per_pixel == 4)
+                               atafb_iplan2p4_linefill(info, par->next_line,
+                                                       dy, dx, width, src,
+                                                       image->bg_color, image->fg_color);
+                       else
+                               atafb_iplan2p8_linefill(info, par->next_line,
+                                                       dy, dx, width, src,
+                                                       image->bg_color, image->fg_color);
+                       dy++;
+                       src += pitch;
                }
-               else
-                       return -EINVAL;
+       } else {
+               // only used for logo; broken
+               c2p(info->screen_base, image->data, dx, dy, width, height,
+                   par->next_line, par->next_plane, image->width,
+                   info->var.bits_per_pixel);
        }
-       fb_display[con].var.xoffset = var->xoffset;
-       fb_display[con].var.yoffset = var->yoffset;
-       return 0;
 }
 
 static int
@@ -2584,7 +2696,7 @@ atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
                if (copy_from_user((void *)&current_par, (void *)arg,
                                   sizeof(struct atafb_par)))
                        return -EFAULT;
-               atafb_set_par(&current_par);
+               ata_set_par(&current_par);
                return 0;
 #endif
        }
@@ -2598,42 +2710,82 @@ atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
  * 3 = suspend hsync
  * 4 = off
  */
-static int 
-atafb_blank(int blank, struct fb_info *info)
+static int atafb_blank(int blank, struct fb_info *info)
 {
        unsigned short black[16];
        struct fb_cmap cmap;
        if (fbhw->blank && !fbhw->blank(blank))
                return 1;
        if (blank) {
-               memset(black, 0, 16*sizeof(unsigned short));
-               cmap.red=black;
-               cmap.green=black;
-               cmap.blue=black;
-               cmap.transp=NULL;
-               cmap.start=0;
-               cmap.len=16;
-               fb_set_cmap(&cmap, 1, info);
+               memset(black, 0, 16 * sizeof(unsigned short));
+               cmap.red = black;
+               cmap.green = black;
+               cmap.blue = black;
+               cmap.transp = NULL;
+               cmap.start = 0;
+               cmap.len = 16;
+               fb_set_cmap(&cmap, info);
        }
+#if 0
        else
-               do_install_cmap(info->currcon, info);
+               do_install_cmap(info);
+#endif
+       return 0;
+}
+
+       /*
+        * New fbcon interface ...
+        */
+
+        /* check var by decoding var into hw par, rounding if necessary,
+         * then encoding hw par back into new, validated var */
+static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       int err;
+       struct atafb_par par;
+
+       /* Validate wanted screen parameters */
+       // if ((err = ata_decode_var(var, &par)))
+       err = fbhw->decode_var(var, &par);
+       if (err)
+               return err;
+
+       /* Encode (possibly rounded) screen parameters */
+       fbhw->encode_var(var, &par);
        return 0;
 }
 
+       /* actually set hw par by decoding var, then setting hardware from
+        * hw par just decoded */
+static int atafb_set_par(struct fb_info *info)
+{
+       struct atafb_par *par = (struct atafb_par *)info->par;
+
+       /* Decode wanted screen parameters */
+       fbhw->decode_var(&info->var, par);
+       fbhw->encode_fix(&info->fix, par);
+
+       /* Set new videomode */
+       ata_set_par(par);
+
+       return 0;
+}
+
+
 static struct fb_ops atafb_ops = {
        .owner =        THIS_MODULE,
-       .fb_get_fix =   atafb_get_fix,
-       .fb_get_var =   atafb_get_var,
-       .fb_set_var =   atafb_set_var,
-       .fb_get_cmap =  atafb_get_cmap,
-       .fb_set_cmap =  gen_set_cmap,
-       .fb_pan_display =atafb_pan_display,
+       .fb_check_var   = atafb_check_var,
+       .fb_set_par     = atafb_set_par,
+       .fb_setcolreg   = atafb_setcolreg,
        .fb_blank =     atafb_blank,
+       .fb_pan_display = atafb_pan_display,
+       .fb_fillrect    = atafb_fillrect,
+       .fb_copyarea    = atafb_copyarea,
+       .fb_imageblit   = atafb_imageblit,
        .fb_ioctl =     atafb_ioctl,
 };
 
-static void
-check_default_par( int detected_mode )
+static void check_default_par(int detected_mode)
 {
        char default_name[10];
        int i;
@@ -2642,199 +2794,41 @@ check_default_par( int detected_mode )
 
        /* First try the user supplied mode */
        if (default_par) {
-               var=atafb_predefined[default_par-1];
+               var = atafb_predefined[default_par - 1];
                var.activate = FB_ACTIVATE_TEST;
-               if (do_fb_set_var(&var,1))
-                       default_par=0;          /* failed */
+               if (do_fb_set_var(&var, 1))
+                       default_par = 0;        /* failed */
        }
        /* Next is the autodetected one */
-       if (! default_par) {
-               var=atafb_predefined[detected_mode-1]; /* autodetect */
+       if (!default_par) {
+               var = atafb_predefined[detected_mode - 1]; /* autodetect */
                var.activate = FB_ACTIVATE_TEST;
-               if (!do_fb_set_var(&var,1))
-                       default_par=detected_mode;
+               if (!do_fb_set_var(&var, 1))
+                       default_par = detected_mode;
        }
        /* If that also failed, try some default modes... */
-       if (! default_par) {
+       if (!default_par) {
                /* try default1, default2... */
-               for (i=1 ; i < 10 ; i++) {
-                       sprintf(default_name,"default%d",i);
-                       default_par=get_video_mode(default_name);
-                       if (! default_par)
+               for (i = 1; i < 10; i++) {
+                       sprintf(default_name,"default%d", i);
+                       default_par = get_video_mode(default_name);
+                       if (!default_par)
                                panic("can't set default video mode");
-                       var=atafb_predefined[default_par-1];
+                       var = atafb_predefined[default_par - 1];
                        var.activate = FB_ACTIVATE_TEST;
-                       if (! do_fb_set_var(&var,1))
+                       if (!do_fb_set_var(&var,1))
                                break;  /* ok */
                }
        }
-       min_mem=var.xres_virtual * var.yres_virtual * var.bits_per_pixel/8;
+       min_mem = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8;
        if (default_mem_req < min_mem)
-               default_mem_req=min_mem;
-}
-
-static int
-atafb_switch(int con, struct fb_info *info)
-{
-       /* Do we have to save the colormap ? */
-       if (fb_display[info->currcon].cmap.len)
-               fb_get_cmap(&fb_display[info->currcon].cmap, 1, fbhw->getcolreg,
-                           info);
-       do_fb_set_var(&fb_display[con].var,1);
-       info->currcon=con;
-       /* Install new colormap */
-       do_install_cmap(con, info);
-       return 0;
+               default_mem_req = min_mem;
 }
 
-int __init atafb_init(void)
-{
-       int pad;
-       int detected_mode;
-       unsigned long mem_req;
-
-       if (!MACH_IS_ATARI)
-               return -ENXIO;
-
-       do {
-#ifdef ATAFB_EXT
-               if (external_addr) {
-                       fbhw = &ext_switch;
-                       atafb_ops.fb_setcolreg = &ext_setcolreg;
-                       break;
-               }
-#endif
-#ifdef ATAFB_TT
-               if (ATARIHW_PRESENT(TT_SHIFTER)) {
-                       fbhw = &tt_switch;
-                       atafb_ops.fb_setcolreg = &tt_setcolreg;
-                       break;
-               }
-#endif
-#ifdef ATAFB_FALCON
-               if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
-                       fbhw = &falcon_switch;
-                       atafb_ops.fb_setcolreg = &falcon_setcolreg;
-                       request_irq(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO,
-                                   "framebuffer/modeswitch", falcon_vbl_switcher);
-                       break;
-               }
-#endif
-#ifdef ATAFB_STE
-               if (ATARIHW_PRESENT(STND_SHIFTER) ||
-                   ATARIHW_PRESENT(EXTD_SHIFTER)) {
-                       fbhw = &st_switch;
-                       atafb_ops.fb_setcolreg = &stste_setcolreg;
-                       break;
-               }
-               fbhw = &st_switch;
-               atafb_ops.fb_setcolreg = &stste_setcolreg;
-               printk("Cannot determine video hardware; defaulting to ST(e)\n");
-#else /* ATAFB_STE */
-               /* no default driver included */
-               /* Nobody will ever see this message :-) */
-               panic("Cannot initialize video hardware");
-#endif
-       } while (0);
-
-       /* Multisync monitor capabilities */
-       /* Atari-TOS defaults if no boot option present */
-       if (fb_info.monspecs.hfmin == 0) {
-           fb_info.monspecs.hfmin = 31000;
-           fb_info.monspecs.hfmax = 32000;
-           fb_info.monspecs.vfmin = 58;
-           fb_info.monspecs.vfmax = 62;
-       }
-
-       detected_mode = fbhw->detect();
-       check_default_par(detected_mode);
-#ifdef ATAFB_EXT
-       if (!external_addr) {
-#endif /* ATAFB_EXT */
-               mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
-               mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
-               screen_base = atari_stram_alloc(mem_req, "atafb");
-               if (!screen_base)
-                       panic("Cannot allocate screen memory");
-               memset(screen_base, 0, mem_req);
-               pad = -(unsigned long)screen_base & (PAGE_SIZE-1);
-               screen_base+=pad;
-               real_screen_base=screen_base+ovsc_offset;
-               screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
-               st_ovsc_switch();
-               if (CPU_IS_040_OR_060) {
-                       /* On a '040+, the cache mode of video RAM must be set to
-                        * write-through also for internal video hardware! */
-                       cache_push(virt_to_phys(screen_base), screen_len);
-                       kernel_set_cachemode(screen_base, screen_len,
-                                            IOMAP_WRITETHROUGH);
-               }
-#ifdef ATAFB_EXT
-       }
-       else {
-               /* Map the video memory (physical address given) to somewhere
-                * in the kernel address space.
-                */
-               external_addr =
-                 ioremap_writethrough((unsigned long)external_addr,
-                                      external_len);
-               if (external_vgaiobase)
-                       external_vgaiobase =
-                         (unsigned long)ioremap(external_vgaiobase, 0x10000);
-               screen_base      =
-               real_screen_base = external_addr;
-               screen_len       = external_len & PAGE_MASK;
-               memset (screen_base, 0, external_len);
-       }
-#endif /* ATAFB_EXT */
-
-       strcpy(fb_info.modename, "Atari Builtin ");
-       fb_info.changevar = NULL;
-       fb_info.fbops = &atafb_ops;
-       fb_info.disp = &disp;
-       fb_info.currcon = -1;
-       fb_info.switch_con = &atafb_switch;
-       fb_info.updatevar = &fb_update_var;
-       fb_info.flags = FBINFO_FLAG_DEFAULT;
-       do_fb_set_var(&atafb_predefined[default_par-1], 1);
-       strcat(fb_info.modename, fb_var_names[default_par-1][0]);
-
-       atafb_get_var(&disp.var, -1, &fb_info);
-       atafb_set_disp(-1, &fb_info);
-       do_install_cmap(0, &fb_info);
-
-       if (register_framebuffer(&fb_info) < 0) {
-#ifdef ATAFB_EXT
-               if (external_addr) {
-                       iounmap(external_addr);
-                       external_addr = NULL;
-               }
-               if (external_vgaiobase) {
-                       iounmap((void*)external_vgaiobase);
-                       external_vgaiobase = 0;
-               }
-#endif
-               return -EINVAL;
-       }
-
-       printk("Determined %dx%d, depth %d\n",
-              disp.var.xres, disp.var.yres, disp.var.bits_per_pixel);
-       if ((disp.var.xres != disp.var.xres_virtual) ||
-           (disp.var.yres != disp.var.yres_virtual))
-          printk("   virtual %dx%d\n",
-                         disp.var.xres_virtual, disp.var.yres_virtual);
-       printk("fb%d: %s frame buffer device, using %dK of video memory\n",
-              fb_info.node, fb_info.modename, screen_len>>10);
-
-       /* TODO: This driver cannot be unloaded yet */
-       return 0;
-}
-
-
 #ifdef ATAFB_EXT
 static void __init atafb_setup_ext(char *spec)
 {
-       int             xres, xres_virtual, yres, depth, planes;
+       int xres, xres_virtual, yres, depth, planes;
        unsigned long addr, len;
        char *p;
 
@@ -2848,27 +2842,31 @@ static void __init atafb_setup_ext(char *spec)
         *
         * Even xres_virtual is available, we neither support panning nor hw-scrolling!
         */
-       if (!(p = strsep(&spec, ";")) || !*p)
-           return;
+       p = strsep(&spec, ";");
+       if (!p || !*p)
+               return;
        xres_virtual = xres = simple_strtoul(p, NULL, 10);
        if (xres <= 0)
-           return;
+               return;
 
-       if (!(p = strsep(&spec, ";")) || !*p)
-           return;
+       p = strsep(&spec, ";");
+       if (!p || !*p)
+               return;
        yres = simple_strtoul(p, NULL, 10);
        if (yres <= 0)
-           return;
+               return;
 
-       if (!(p = strsep(&spec, ";")) || !*p)
-           return;
+       p = strsep(&spec, ";");
+       if (!p || !*p)
+               return;
        depth = simple_strtoul(p, NULL, 10);
        if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
-               depth != 16 && depth != 24)
-           return;
+           depth != 16 && depth != 24)
+               return;
 
-       if (!(p = strsep(&spec, ";")) || !*p)
-           return;
+       p = strsep(&spec, ";");
+       if (!p || !*p)
+               return;
        if (*p == 'i')
                planes = FB_TYPE_INTERLEAVED_PLANES;
        else if (*p == 'p')
@@ -2876,25 +2874,27 @@ static void __init atafb_setup_ext(char *spec)
        else if (*p == 'n')
                planes = FB_TYPE_PLANES;
        else if (*p == 't')
-               planes = -1; /* true color */
+               planes = -1;            /* true color */
        else
                return;
 
-
-       if (!(p = strsep(&spec, ";")) || !*p)
+       p = strsep(&spec, ";");
+       if (!p || !*p)
                return;
        addr = simple_strtoul(p, NULL, 0);
 
-       if (!(p = strsep(&spec, ";")) || !*p)
-               len = xres*yres*depth/8;
+       p = strsep(&spec, ";");
+       if (!p || !*p)
+               len = xres * yres * depth / 8;
        else
                len = simple_strtoul(p, NULL, 0);
 
-       if ((p = strsep(&spec, ";")) && *p) {
-               external_vgaiobase=simple_strtoul(p, NULL, 0);
-       }
+       p = strsep(&spec, ";");
+       if (p && *p)
+               external_vgaiobase = simple_strtoul(p, NULL, 0);
 
-       if ((p = strsep(&spec, ";")) && *p) {
+       p = strsep(&spec, ";");
+       if (p && *p) {
                external_bitspercol = simple_strtoul(p, NULL, 0);
                if (external_bitspercol > 8)
                        external_bitspercol = 8;
@@ -2902,59 +2902,61 @@ static void __init atafb_setup_ext(char *spec)
                        external_bitspercol = 1;
        }
 
-       if ((p = strsep(&spec, ";")) && *p) {
+       p = strsep(&spec, ";");
+       if (p && *p) {
                if (!strcmp(p, "vga"))
                        external_card_type = IS_VGA;
                if (!strcmp(p, "mv300"))
                        external_card_type = IS_MV300;
        }
 
-       if ((p = strsep(&spec, ";")) && *p) {
+       p = strsep(&spec, ";");
+       if (p && *p) {
                xres_virtual = simple_strtoul(p, NULL, 10);
                if (xres_virtual < xres)
                        xres_virtual = xres;
-               if (xres_virtual*yres*depth/8 > len)
-                       len=xres_virtual*yres*depth/8;
+               if (xres_virtual * yres * depth / 8 > len)
+                       len = xres_virtual * yres * depth / 8;
        }
 
-       external_xres  = xres;
-       external_xres_virtual  = xres_virtual;
-       external_yres  = yres;
+       external_xres = xres;
+       external_xres_virtual = xres_virtual;
+       external_yres = yres;
        external_depth = depth;
        external_pmode = planes;
-       external_addr  = (void *)addr;
-       external_len   = len;
-
-       if (external_card_type == IS_MV300)
-         switch (external_depth) {
-           case 1:
-             MV300_reg = MV300_reg_1bit;
-             break;
-           case 4:
-             MV300_reg = MV300_reg_4bit;
-             break;
-           case 8:
-             MV300_reg = MV300_reg_8bit;
-             break;
-           }
+       external_addr = (void *)addr;
+       external_len = len;
+
+       if (external_card_type == IS_MV300) {
+               switch (external_depth) {
+               case 1:
+                       MV300_reg = MV300_reg_1bit;
+                       break;
+               case 4:
+                       MV300_reg = MV300_reg_4bit;
+                       break;
+               case 8:
+                       MV300_reg = MV300_reg_8bit;
+                       break;
+               }
+       }
 }
 #endif /* ATAFB_EXT */
 
-
 static void __init atafb_setup_int(char *spec)
 {
        /* Format to config extended internal video hardware like OverScan:
-       "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
-       Explanation:
-       <xres>: x-resolution 
-       <yres>: y-resolution
-       The following are only needed if you have an overscan which
-       needs a black border:
-       <xres_max>: max. length of a line in pixels your OverScan hardware would allow
-       <yres_max>: max. number of lines your OverScan hardware would allow
-       <offset>: Offset from physical beginning to visible beginning
-                 of screen in bytes
-       */
+        * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
+        * Explanation:
+        * <xres>: x-resolution
+        * <yres>: y-resolution
+        * The following are only needed if you have an overscan which
+        * needs a black border:
+        * <xres_max>: max. length of a line in pixels your OverScan hardware would allow
+        * <yres_max>: max. number of lines your OverScan hardware would allow
+        * <offset>: Offset from physical beginning to visible beginning
+        *        of screen in bytes
+        */
        int xres;
        char *p;
 
@@ -2963,23 +2965,19 @@ static void __init atafb_setup_int(char *spec)
        xres = simple_strtoul(p, NULL, 10);
        if (!(p = strsep(&spec, ";")) || !*p)
                return;
-       sttt_xres=xres;
-       tt_yres=st_yres=simple_strtoul(p, NULL, 10);
-       if ((p=strsep(&spec, ";")) && *p) {
-               sttt_xres_virtual=simple_strtoul(p, NULL, 10);
-       }
-       if ((p=strsep(&spec, ";")) && *p) {
-               sttt_yres_virtual=simple_strtoul(p, NULL, 0);
-       }
-       if ((p=strsep(&spec, ";")) && *p) {
-               ovsc_offset=simple_strtoul(p, NULL, 0);
-       }
+       sttt_xres = xres;
+       tt_yres = st_yres = simple_strtoul(p, NULL, 10);
+       if ((p = strsep(&spec, ";")) && *p)
+               sttt_xres_virtual = simple_strtoul(p, NULL, 10);
+       if ((p = strsep(&spec, ";")) && *p)
+               sttt_yres_virtual = simple_strtoul(p, NULL, 0);
+       if ((p = strsep(&spec, ";")) && *p)
+               ovsc_offset = simple_strtoul(p, NULL, 0);
 
        if (ovsc_offset || (sttt_yres_virtual != st_yres))
-               use_hwscroll=0;
+               use_hwscroll = 0;
 }
 
-
 #ifdef ATAFB_FALCON
 static void __init atafb_setup_mcap(char *spec)
 {
@@ -3018,7 +3016,6 @@ static void __init atafb_setup_mcap(char *spec)
 }
 #endif /* ATAFB_FALCON */
 
-
 static void __init atafb_setup_user(char *spec)
 {
        /* Format of user defined video mode is: <xres>;<yres>;<depth>
@@ -3026,81 +3023,257 @@ static void __init atafb_setup_user(char *spec)
        char *p;
        int xres, yres, depth, temp;
 
-       if (!(p = strsep(&spec, ";")) || !*p)
+       p = strsep(&spec, ";");
+       if (!p || !*p)
                return;
        xres = simple_strtoul(p, NULL, 10);
-       if (!(p = strsep(&spec, ";")) || !*p)
+       p = strsep(&spec, ";");
+       if (!p || !*p)
                return;
        yres = simple_strtoul(p, NULL, 10);
-       if (!(p = strsep(&spec, "")) || !*p)
+       p = strsep(&spec, "");
+       if (!p || !*p)
                return;
        depth = simple_strtoul(p, NULL, 10);
-       if ((temp=get_video_mode("user0"))) {
-               default_par=temp;
-               atafb_predefined[default_par-1].xres = xres;
-               atafb_predefined[default_par-1].yres = yres;
-               atafb_predefined[default_par-1].bits_per_pixel = depth;
+       temp = get_video_mode("user0");
+       if (temp) {
+               default_par = temp;
+               atafb_predefined[default_par - 1].xres = xres;
+               atafb_predefined[default_par - 1].yres = yres;
+               atafb_predefined[default_par - 1].bits_per_pixel = depth;
        }
 }
 
-int __init atafb_setup( char *options )
+int __init atafb_setup(char *options)
 {
-    char *this_opt;
-    int temp;
-
-    fb_info.fontname[0] = '\0';
+       char *this_opt;
+       int temp;
 
-    if (!options || !*options)
+       if (!options || !*options)
                return 0;
-    
-    while ((this_opt = strsep(&options, ",")) != NULL) {        
-       if (!*this_opt) continue;
-       if ((temp=get_video_mode(this_opt)))
-               default_par=temp;
-       else if (! strcmp(this_opt, "inverse"))
-               inverse=1;
-       else if (!strncmp(this_opt, "font:", 5))
-          strcpy(fb_info.fontname, this_opt+5);
-       else if (! strncmp(this_opt, "hwscroll_",9)) {
-               hwscroll=simple_strtoul(this_opt+9, NULL, 10);
-               if (hwscroll < 0)
-                       hwscroll = 0;
-               if (hwscroll > 200)
-                       hwscroll = 200;
-       }
+
+       while ((this_opt = strsep(&options, ",")) != NULL) {
+               if (!*this_opt)
+                       continue;
+               if ((temp = get_video_mode(this_opt))) {
+                       default_par = temp;
+                       mode_option = this_opt;
+               } else if (!strcmp(this_opt, "inverse"))
+                       inverse = 1;
+               else if (!strncmp(this_opt, "hwscroll_", 9)) {
+                       hwscroll = simple_strtoul(this_opt + 9, NULL, 10);
+                       if (hwscroll < 0)
+                               hwscroll = 0;
+                       if (hwscroll > 200)
+                               hwscroll = 200;
+               }
 #ifdef ATAFB_EXT
-       else if (!strcmp(this_opt,"mv300")) {
-               external_bitspercol = 8;
-               external_card_type = IS_MV300;
+               else if (!strcmp(this_opt, "mv300")) {
+                       external_bitspercol = 8;
+                       external_card_type = IS_MV300;
+               } else if (!strncmp(this_opt, "external:", 9))
+                       atafb_setup_ext(this_opt + 9);
+#endif
+               else if (!strncmp(this_opt, "internal:", 9))
+                       atafb_setup_int(this_opt + 9);
+#ifdef ATAFB_FALCON
+               else if (!strncmp(this_opt, "eclock:", 7)) {
+                       fext.f = simple_strtoul(this_opt + 7, NULL, 10);
+                       /* external pixelclock in kHz --> ps */
+                       fext.t = 1000000000 / fext.f;
+                       fext.f *= 1000;
+               } else if (!strncmp(this_opt, "monitorcap:", 11))
+                       atafb_setup_mcap(this_opt + 11);
+#endif
+               else if (!strcmp(this_opt, "keep"))
+                       DontCalcRes = 1;
+               else if (!strncmp(this_opt, "R", 1))
+                       atafb_setup_user(this_opt + 1);
        }
-       else if (!strncmp(this_opt,"external:",9))
-               atafb_setup_ext(this_opt+9);
+       return 0;
+}
+
+int __init atafb_init(void)
+{
+       int pad;
+       int detected_mode;
+       unsigned int defmode = 0;
+       unsigned long mem_req;
+
+#ifndef MODULE
+       char *option = NULL;
+
+       if (fb_get_options("atafb", &option))
+               return -ENODEV;
+       atafb_setup(option);
+#endif
+       printk("atafb_init: start\n");
+
+       if (!MACH_IS_ATARI)
+               return -ENXIO;
+
+       do {
+#ifdef ATAFB_EXT
+               if (external_addr) {
+                       printk("atafb_init: initializing external hw\n");
+                       fbhw = &ext_switch;
+                       atafb_ops.fb_setcolreg = &ext_setcolreg;
+                       defmode = DEFMODE_EXT;
+                       break;
+               }
+#endif
+#ifdef ATAFB_TT
+               if (ATARIHW_PRESENT(TT_SHIFTER)) {
+                       printk("atafb_init: initializing TT hw\n");
+                       fbhw = &tt_switch;
+                       atafb_ops.fb_setcolreg = &tt_setcolreg;
+                       defmode = DEFMODE_TT;
+                       break;
+               }
 #endif
-       else if (!strncmp(this_opt,"internal:",9))
-               atafb_setup_int(this_opt+9);
 #ifdef ATAFB_FALCON
-       else if (!strncmp(this_opt, "eclock:", 7)) {
-               fext.f = simple_strtoul(this_opt+7, NULL, 10);
-               /* external pixelclock in kHz --> ps */
-               fext.t = 1000000000/fext.f;
-               fext.f *= 1000;
+               if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
+                       printk("atafb_init: initializing Falcon hw\n");
+                       fbhw = &falcon_switch;
+                       atafb_ops.fb_setcolreg = &falcon_setcolreg;
+                       request_irq(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO,
+                                   "framebuffer/modeswitch", falcon_vbl_switcher);
+                       defmode = DEFMODE_F30;
+                       break;
+               }
+#endif
+#ifdef ATAFB_STE
+               if (ATARIHW_PRESENT(STND_SHIFTER) ||
+                   ATARIHW_PRESENT(EXTD_SHIFTER)) {
+                       printk("atafb_init: initializing ST/E hw\n");
+                       fbhw = &st_switch;
+                       atafb_ops.fb_setcolreg = &stste_setcolreg;
+                       defmode = DEFMODE_STE;
+                       break;
+               }
+               fbhw = &st_switch;
+               atafb_ops.fb_setcolreg = &stste_setcolreg;
+               printk("Cannot determine video hardware; defaulting to ST(e)\n");
+#else /* ATAFB_STE */
+               /* no default driver included */
+               /* Nobody will ever see this message :-) */
+               panic("Cannot initialize video hardware");
+#endif
+       } while (0);
+
+       /* Multisync monitor capabilities */
+       /* Atari-TOS defaults if no boot option present */
+       if (fb_info.monspecs.hfmin == 0) {
+               fb_info.monspecs.hfmin = 31000;
+               fb_info.monspecs.hfmax = 32000;
+               fb_info.monspecs.vfmin = 58;
+               fb_info.monspecs.vfmax = 62;
        }
-       else if (!strncmp(this_opt, "monitorcap:", 11))
-               atafb_setup_mcap(this_opt+11);
+
+       detected_mode = fbhw->detect();
+       check_default_par(detected_mode);
+#ifdef ATAFB_EXT
+       if (!external_addr) {
+#endif /* ATAFB_EXT */
+               mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
+               mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
+               screen_base = atari_stram_alloc(mem_req, "atafb");
+               if (!screen_base)
+                       panic("Cannot allocate screen memory");
+               memset(screen_base, 0, mem_req);
+               pad = -(unsigned long)screen_base & (PAGE_SIZE - 1);
+               screen_base += pad;
+               real_screen_base = screen_base + ovsc_offset;
+               screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
+               st_ovsc_switch();
+               if (CPU_IS_040_OR_060) {
+                       /* On a '040+, the cache mode of video RAM must be set to
+                        * write-through also for internal video hardware! */
+                       cache_push(virt_to_phys(screen_base), screen_len);
+                       kernel_set_cachemode(screen_base, screen_len,
+                                            IOMAP_WRITETHROUGH);
+               }
+               printk("atafb: screen_base %p real_screen_base %p screen_len %d\n",
+                       screen_base, real_screen_base, screen_len);
+#ifdef ATAFB_EXT
+       } else {
+               /* Map the video memory (physical address given) to somewhere
+                * in the kernel address space.
+                */
+               external_addr = ioremap_writethrough((unsigned long)external_addr,
+                                                    external_len);
+               if (external_vgaiobase)
+                       external_vgaiobase =
+                         (unsigned long)ioremap(external_vgaiobase, 0x10000);
+               screen_base =
+               real_screen_base = external_addr;
+               screen_len = external_len & PAGE_MASK;
+               memset (screen_base, 0, external_len);
+       }
+#endif /* ATAFB_EXT */
+
+//     strcpy(fb_info.mode->name, "Atari Builtin ");
+       fb_info.fbops = &atafb_ops;
+       // try to set default (detected; requested) var
+       do_fb_set_var(&atafb_predefined[default_par - 1], 1);
+       // reads hw state into current par, which may not be sane yet
+       ata_get_par(&current_par);
+       fb_info.par = &current_par;
+       // tries to read from HW which may not be initialized yet
+       // so set sane var first, then call atafb_set_par
+       atafb_get_var(&fb_info.var, &fb_info);
+       fb_info.flags = FBINFO_FLAG_DEFAULT;
+
+       if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb,
+                         NUM_TOTAL_MODES, &atafb_modedb[defmode],
+                         fb_info.var.bits_per_pixel)) {
+               return -EINVAL;
+       }
+
+       atafb_set_disp(&fb_info);
+
+       fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0);
+
+
+       printk("Determined %dx%d, depth %d\n",
+              fb_info.var.xres, fb_info.var.yres, fb_info.var.bits_per_pixel);
+       if ((fb_info.var.xres != fb_info.var.xres_virtual) ||
+           (fb_info.var.yres != fb_info.var.yres_virtual))
+               printk("   virtual %dx%d\n", fb_info.var.xres_virtual,
+                      fb_info.var.yres_virtual);
+
+       if (register_framebuffer(&fb_info) < 0) {
+#ifdef ATAFB_EXT
+               if (external_addr) {
+                       iounmap(external_addr);
+                       external_addr = NULL;
+               }
+               if (external_vgaiobase) {
+                       iounmap((void*)external_vgaiobase);
+                       external_vgaiobase = 0;
+               }
 #endif
-       else if (!strcmp(this_opt, "keep"))
-               DontCalcRes = 1;
-       else if (!strncmp(this_opt, "R", 1))
-               atafb_setup_user(this_opt+1);
-    }
-    return 0;
+               return -EINVAL;
+       }
+
+       // FIXME: mode needs setting!
+       //printk("fb%d: %s frame buffer device, using %dK of video memory\n",
+       //       fb_info.node, fb_info.mode->name, screen_len>>10);
+       printk("fb%d: frame buffer device, using %dK of video memory\n",
+              fb_info.node, screen_len >> 10);
+
+       /* TODO: This driver cannot be unloaded yet */
+       return 0;
 }
 
+module_init(atafb_init);
+
 #ifdef MODULE
 MODULE_LICENSE("GPL");
 
-int init_module(void)
+int cleanup_module(void)
 {
-       return atafb_init();
+       unregister_framebuffer(&fb_info);
+       return atafb_deinit();
 }
 #endif /* MODULE */
diff --git a/drivers/video/atafb.h b/drivers/video/atafb.h
new file mode 100644 (file)
index 0000000..014e059
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _VIDEO_ATAFB_H
+#define _VIDEO_ATAFB_H
+
+void atafb_mfb_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
+                       int dx, int height, int width);
+void atafb_mfb_fillrect(struct fb_info *info, u_long next_line, u32 color,
+                       int sy, int sx, int height, int width);
+void atafb_mfb_linefill(struct fb_info *info, u_long next_line,
+                       int dy, int dx, u32 width,
+                       const u8 *data, u32 bgcolor, u32 fgcolor);
+
+void atafb_iplan2p2_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
+                            int dx, int height, int width);
+void atafb_iplan2p2_fillrect(struct fb_info *info, u_long next_line, u32 color,
+                            int sy, int sx, int height, int width);
+void atafb_iplan2p2_linefill(struct fb_info *info, u_long next_line,
+                            int dy, int dx, u32 width,
+                            const u8 *data, u32 bgcolor, u32 fgcolor);
+
+void atafb_iplan2p4_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
+                            int dx, int height, int width);
+void atafb_iplan2p4_fillrect(struct fb_info *info, u_long next_line, u32 color,
+                            int sy, int sx, int height, int width);
+void atafb_iplan2p4_linefill(struct fb_info *info, u_long next_line,
+                            int dy, int dx, u32 width,
+                            const u8 *data, u32 bgcolor, u32 fgcolor);
+
+void atafb_iplan2p8_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy,
+                            int dx, int height, int width);
+void atafb_iplan2p8_fillrect(struct fb_info *info, u_long next_line, u32 color,
+                            int sy, int sx, int height, int width);
+void atafb_iplan2p8_linefill(struct fb_info *info, u_long next_line,
+                            int dy, int dx, u32 width,
+                            const u8 *data, u32 bgcolor, u32 fgcolor);
+
+#endif /* _VIDEO_ATAFB_H */
diff --git a/drivers/video/atafb_iplan2p2.c b/drivers/video/atafb_iplan2p2.c
new file mode 100644 (file)
index 0000000..8cc9c50
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ *  linux/drivers/video/iplan2p2.c -- Low level frame buffer operations for
+ *                                   interleaved bitplanes Ã  la Atari (2
+ *                                   planes, 2 bytes interleave)
+ *
+ *     Created 5 Apr 1997 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+
+#include <asm/setup.h>
+
+#include "atafb.h"
+
+#define BPL    2
+#include "atafb_utils.h"
+
+void atafb_iplan2p2_copyarea(struct fb_info *info, u_long next_line,
+                            int sy, int sx, int dy, int dx,
+                            int height, int width)
+{
+       /*  bmove() has to distinguish two major cases: If both, source and
+        *  destination, start at even addresses or both are at odd
+        *  addresses, just the first odd and last even column (if present)
+        *  require special treatment (memmove_col()). The rest between
+        *  then can be copied by normal operations, because all adjacent
+        *  bytes are affected and are to be stored in the same order.
+        *    The pathological case is when the move should go from an odd
+        *  address to an even or vice versa. Since the bytes in the plane
+        *  words must be assembled in new order, it seems wisest to make
+        *  all movements by memmove_col().
+        */
+
+       u8 *src, *dst;
+       u32 *s, *d;
+       int w, l , i, j;
+       u_int colsize;
+       u_int upwards = (dy < sy) || (dy == sy && dx < sx);
+
+       colsize = height;
+       if (!((sx ^ dx) & 15)) {
+               /* odd->odd or even->even */
+
+               if (upwards) {
+                       src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
+                       dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
+                       if (sx & 15) {
+                               memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2);
+                               src += BPL * 2;
+                               dst += BPL * 2;
+                               width -= 8;
+                       }
+                       w = width >> 4;
+                       if (w) {
+                               s = (u32 *)src;
+                               d = (u32 *)dst;
+                               w *= BPL / 2;
+                               l = next_line - w * 4;
+                               for (j = height; j > 0; j--) {
+                                       for (i = w; i > 0; i--)
+                                               *d++ = *s++;
+                                       s = (u32 *)((u8 *)s + l);
+                                       d = (u32 *)((u8 *)d + l);
+                               }
+                       }
+                       if (width & 15)
+                               memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL),
+                                             0xff00ff00, height, next_line - BPL * 2);
+               } else {
+                       src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
+                       dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
+
+                       if ((sx + width) & 15) {
+                               src -= BPL * 2;
+                               dst -= BPL * 2;
+                               memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2);
+                               width -= 8;
+                       }
+                       w = width >> 4;
+                       if (w) {
+                               s = (u32 *)src;
+                               d = (u32 *)dst;
+                               w *= BPL / 2;
+                               l = next_line - w * 4;
+                               for (j = height; j > 0; j--) {
+                                       for (i = w; i > 0; i--)
+                                               *--d = *--s;
+                                       s = (u32 *)((u8 *)s - l);
+                                       d = (u32 *)((u8 *)d - l);
+                               }
+                       }
+                       if (sx & 15)
+                               memmove32_col(dst - (width - 16) / (8 / BPL),
+                                             src - (width - 16) / (8 / BPL),
+                                             0xff00ff, colsize, -next_line - BPL * 2);
+               }
+       } else {
+               /* odd->even or even->odd */
+               if (upwards) {
+                       u32 *src32, *dst32;
+                       u32 pval[4], v, v1, mask;
+                       int i, j, w, f;
+
+                       src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
+                       dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
+
+                       mask = 0xff00ff00;
+                       f = 0;
+                       w = width;
+                       if (sx & 15) {
+                               f = 1;
+                               w += 8;
+                       }
+                       if ((sx + width) & 15)
+                               f |= 2;
+                       w >>= 4;
+                       for (i = height; i; i--) {
+                               src32 = (u32 *)src;
+                               dst32 = (u32 *)dst;
+
+                               if (f & 1) {
+                                       pval[0] = (*src32++ << 8) & mask;
+                               } else {
+                                       pval[0] = dst32[0] & mask;
+                               }
+
+                               for (j = w; j > 0; j--) {
+                                       v = *src32++;
+                                       v1 = v & mask;
+                                       *dst32++ = pval[0] | (v1 >> 8);
+                                       pval[0] = (v ^ v1) << 8;
+                               }
+
+                               if (f & 2) {
+                                       dst32[0] = (dst32[0] & mask) | pval[0];
+                               }
+
+                               src += next_line;
+                               dst += next_line;
+                       }
+               } else {
+                       u32 *src32, *dst32;
+                       u32 pval[4], v, v1, mask;
+                       int i, j, w, f;
+
+                       src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
+                       dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
+
+                       mask = 0xff00ff;
+                       f = 0;
+                       w = width;
+                       if ((dx + width) & 15)
+                               f = 1;
+                       if (sx & 15) {
+                               f |= 2;
+                               w += 8;
+                       }
+                       w >>= 4;
+                       for (i = height; i; i--) {
+                               src32 = (u32 *)src;
+                               dst32 = (u32 *)dst;
+
+                               if (f & 1) {
+                                       pval[0] = dst32[-1] & mask;
+                               } else {
+                                       pval[0] = (*--src32 >> 8) & mask;
+                               }
+
+                               for (j = w; j > 0; j--) {
+                                       v = *--src32;
+                                       v1 = v & mask;
+                                       *--dst32 = pval[0] | (v1 << 8);
+                                       pval[0] = (v ^ v1) >> 8;
+                               }
+
+                               if (!(f & 2)) {
+                                       dst32[-1] = (dst32[-1] & mask) | pval[0];
+                               }
+
+                               src -= next_line;
+                               dst -= next_line;
+                       }
+               }
+       }
+}
+
+void atafb_iplan2p2_fillrect(struct fb_info *info, u_long next_line, u32 color,
+                             int sy, int sx, int height, int width)
+{
+       u32 *dest;
+       int rows, i;
+       u32 cval[4];
+
+       dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL));
+       if (sx & 15) {
+               u8 *dest8 = (u8 *)dest + 1;
+
+               expand8_col2mask(color, cval);
+
+               for (i = height; i; i--) {
+                       fill8_col(dest8, cval);
+                       dest8 += next_line;
+               }
+               dest += BPL / 2;
+               width -= 8;
+       }
+
+       expand16_col2mask(color, cval);
+       rows = width >> 4;
+       if (rows) {
+               u32 *d = dest;
+               u32 off = next_line - rows * BPL * 2;
+               for (i = height; i; i--) {
+                       d = fill16_col(d, rows, cval);
+                       d = (u32 *)((long)d + off);
+               }
+               dest += rows * BPL / 2;
+               width &= 15;
+       }
+
+       if (width) {
+               u8 *dest8 = (u8 *)dest;
+
+               expand8_col2mask(color, cval);
+
+               for (i = height; i; i--) {
+                       fill8_col(dest8, cval);
+                       dest8 += next_line;
+               }
+       }
+}
+
+void atafb_iplan2p2_linefill(struct fb_info *info, u_long next_line,
+                             int dy, int dx, u32 width,
+                             const u8 *data, u32 bgcolor, u32 fgcolor)
+{
+       u32 *dest;
+       const u16 *data16;
+       int rows;
+       u32 fgm[4], bgm[4], m;
+
+       dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL));
+       if (dx & 15) {
+               fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++);
+               dest += BPL / 2;
+               width -= 8;
+       }
+
+       if (width >= 16) {
+               data16 = (const u16 *)data;
+               expand16_2col2mask(fgcolor, bgcolor, fgm, bgm);
+
+               for (rows = width / 16; rows; rows--) {
+                       u16 d = *data16++;
+                       m = d | ((u32)d << 16);
+                       *dest++ = (m & fgm[0]) ^ bgm[0];
+               }
+
+               data = (const u8 *)data16;
+               width &= 15;
+       }
+
+       if (width)
+               fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
+}
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+
+int init_module(void)
+{
+       return 0;
+}
+
+void cleanup_module(void)
+{
+}
+#endif /* MODULE */
+
+
+    /*
+     *  Visible symbols for modules
+     */
+
+EXPORT_SYMBOL(atafb_iplan2p2_copyarea);
+EXPORT_SYMBOL(atafb_iplan2p2_fillrect);
+EXPORT_SYMBOL(atafb_iplan2p2_linefill);
diff --git a/drivers/video/atafb_iplan2p4.c b/drivers/video/atafb_iplan2p4.c
new file mode 100644 (file)
index 0000000..bee0d89
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ *  linux/drivers/video/iplan2p4.c -- Low level frame buffer operations for
+ *                                   interleaved bitplanes Ã  la Atari (4
+ *                                   planes, 2 bytes interleave)
+ *
+ *     Created 5 Apr 1997 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+
+#include <asm/setup.h>
+
+#include "atafb.h"
+
+#define BPL    4
+#include "atafb_utils.h"
+
+void atafb_iplan2p4_copyarea(struct fb_info *info, u_long next_line,
+                            int sy, int sx, int dy, int dx,
+                            int height, int width)
+{
+       /*  bmove() has to distinguish two major cases: If both, source and
+        *  destination, start at even addresses or both are at odd
+        *  addresses, just the first odd and last even column (if present)
+        *  require special treatment (memmove_col()). The rest between
+        *  then can be copied by normal operations, because all adjacent
+        *  bytes are affected and are to be stored in the same order.
+        *    The pathological case is when the move should go from an odd
+        *  address to an even or vice versa. Since the bytes in the plane
+        *  words must be assembled in new order, it seems wisest to make
+        *  all movements by memmove_col().
+        */
+
+       u8 *src, *dst;
+       u32 *s, *d;
+       int w, l , i, j;
+       u_int colsize;
+       u_int upwards = (dy < sy) || (dy == sy && dx < sx);
+
+       colsize = height;
+       if (!((sx ^ dx) & 15)) {
+               /* odd->odd or even->even */
+
+               if (upwards) {
+                       src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
+                       dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
+                       if (sx & 15) {
+                               memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2);
+                               src += BPL * 2;
+                               dst += BPL * 2;
+                               width -= 8;
+                       }
+                       w = width >> 4;
+                       if (w) {
+                               s = (u32 *)src;
+                               d = (u32 *)dst;
+                               w *= BPL / 2;
+                               l = next_line - w * 4;
+                               for (j = height; j > 0; j--) {
+                                       for (i = w; i > 0; i--)
+                                               *d++ = *s++;
+                                       s = (u32 *)((u8 *)s + l);
+                                       d = (u32 *)((u8 *)d + l);
+                               }
+                       }
+                       if (width & 15)
+                               memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL),
+                                             0xff00ff00, height, next_line - BPL * 2);
+               } else {
+                       src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
+                       dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
+
+                       if ((sx + width) & 15) {
+                               src -= BPL * 2;
+                               dst -= BPL * 2;
+                               memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2);
+                               width -= 8;
+                       }
+                       w = width >> 4;
+                       if (w) {
+                               s = (u32 *)src;
+                               d = (u32 *)dst;
+                               w *= BPL / 2;
+                               l = next_line - w * 4;
+                               for (j = height; j > 0; j--) {
+                                       for (i = w; i > 0; i--)
+                                               *--d = *--s;
+                                       s = (u32 *)((u8 *)s - l);
+                                       d = (u32 *)((u8 *)d - l);
+                               }
+                       }
+                       if (sx & 15)
+                               memmove32_col(dst - (width - 16) / (8 / BPL),
+                                             src - (width - 16) / (8 / BPL),
+                                             0xff00ff, colsize, -next_line - BPL * 2);
+               }
+       } else {
+               /* odd->even or even->odd */
+               if (upwards) {
+                       u32 *src32, *dst32;
+                       u32 pval[4], v, v1, mask;
+                       int i, j, w, f;
+
+                       src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
+                       dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
+
+                       mask = 0xff00ff00;
+                       f = 0;
+                       w = width;
+                       if (sx & 15) {
+                               f = 1;
+                               w += 8;
+                       }
+                       if ((sx + width) & 15)
+                               f |= 2;
+                       w >>= 4;
+                       for (i = height; i; i--) {
+                               src32 = (u32 *)src;
+                               dst32 = (u32 *)dst;
+
+                               if (f & 1) {
+                                       pval[0] = (*src32++ << 8) & mask;
+                                       pval[1] = (*src32++ << 8) & mask;
+                               } else {
+                                       pval[0] = dst32[0] & mask;
+                                       pval[1] = dst32[1] & mask;
+                               }
+
+                               for (j = w; j > 0; j--) {
+                                       v = *src32++;
+                                       v1 = v & mask;
+                                       *dst32++ = pval[0] | (v1 >> 8);
+                                       pval[0] = (v ^ v1) << 8;
+                                       v = *src32++;
+                                       v1 = v & mask;
+                                       *dst32++ = pval[1] | (v1 >> 8);
+                                       pval[1] = (v ^ v1) << 8;
+                               }
+
+                               if (f & 2) {
+                                       dst32[0] = (dst32[0] & mask) | pval[0];
+                                       dst32[1] = (dst32[1] & mask) | pval[1];
+                               }
+
+                               src += next_line;
+                               dst += next_line;
+                       }
+               } else {
+                       u32 *src32, *dst32;
+                       u32 pval[4], v, v1, mask;
+                       int i, j, w, f;
+
+                       src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
+                       dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
+
+                       mask = 0xff00ff;
+                       f = 0;
+                       w = width;
+                       if ((dx + width) & 15)
+                               f = 1;
+                       if (sx & 15) {
+                               f |= 2;
+                               w += 8;
+                       }
+                       w >>= 4;
+                       for (i = height; i; i--) {
+                               src32 = (u32 *)src;
+                               dst32 = (u32 *)dst;
+
+                               if (f & 1) {
+                                       pval[0] = dst32[-1] & mask;
+                                       pval[1] = dst32[-2] & mask;
+                               } else {
+                                       pval[0] = (*--src32 >> 8) & mask;
+                                       pval[1] = (*--src32 >> 8) & mask;
+                               }
+
+                               for (j = w; j > 0; j--) {
+                                       v = *--src32;
+                                       v1 = v & mask;
+                                       *--dst32 = pval[0] | (v1 << 8);
+                                       pval[0] = (v ^ v1) >> 8;
+                                       v = *--src32;
+                                       v1 = v & mask;
+                                       *--dst32 = pval[1] | (v1 << 8);
+                                       pval[1] = (v ^ v1) >> 8;
+                               }
+
+                               if (!(f & 2)) {
+                                       dst32[-1] = (dst32[-1] & mask) | pval[0];
+                                       dst32[-2] = (dst32[-2] & mask) | pval[1];
+                               }
+
+                               src -= next_line;
+                               dst -= next_line;
+                       }
+               }
+       }
+}
+
+void atafb_iplan2p4_fillrect(struct fb_info *info, u_long next_line, u32 color,
+                             int sy, int sx, int height, int width)
+{
+       u32 *dest;
+       int rows, i;
+       u32 cval[4];
+
+       dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL));
+       if (sx & 15) {
+               u8 *dest8 = (u8 *)dest + 1;
+
+               expand8_col2mask(color, cval);
+
+               for (i = height; i; i--) {
+                       fill8_col(dest8, cval);
+                       dest8 += next_line;
+               }
+               dest += BPL / 2;
+               width -= 8;
+       }
+
+       expand16_col2mask(color, cval);
+       rows = width >> 4;
+       if (rows) {
+               u32 *d = dest;
+               u32 off = next_line - rows * BPL * 2;
+               for (i = height; i; i--) {
+                       d = fill16_col(d, rows, cval);
+                       d = (u32 *)((long)d + off);
+               }
+               dest += rows * BPL / 2;
+               width &= 15;
+       }
+
+       if (width) {
+               u8 *dest8 = (u8 *)dest;
+
+               expand8_col2mask(color, cval);
+
+               for (i = height; i; i--) {
+                       fill8_col(dest8, cval);
+                       dest8 += next_line;
+               }
+       }
+}
+
+void atafb_iplan2p4_linefill(struct fb_info *info, u_long next_line,
+                             int dy, int dx, u32 width,
+                             const u8 *data, u32 bgcolor, u32 fgcolor)
+{
+       u32 *dest;
+       const u16 *data16;
+       int rows;
+       u32 fgm[4], bgm[4], m;
+
+       dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL));
+       if (dx & 15) {
+               fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++);
+               dest += BPL / 2;
+               width -= 8;
+       }
+
+       if (width >= 16) {
+               data16 = (const u16 *)data;
+               expand16_2col2mask(fgcolor, bgcolor, fgm, bgm);
+
+               for (rows = width / 16; rows; rows--) {
+                       u16 d = *data16++;
+                       m = d | ((u32)d << 16);
+                       *dest++ = (m & fgm[0]) ^ bgm[0];
+                       *dest++ = (m & fgm[1]) ^ bgm[1];
+               }
+
+               data = (const u8 *)data16;
+               width &= 15;
+       }
+
+       if (width)
+               fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
+}
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+
+int init_module(void)
+{
+       return 0;
+}
+
+void cleanup_module(void)
+{
+}
+#endif /* MODULE */
+
+
+    /*
+     *  Visible symbols for modules
+     */
+
+EXPORT_SYMBOL(atafb_iplan2p4_copyarea);
+EXPORT_SYMBOL(atafb_iplan2p4_fillrect);
+EXPORT_SYMBOL(atafb_iplan2p4_linefill);
diff --git a/drivers/video/atafb_iplan2p8.c b/drivers/video/atafb_iplan2p8.c
new file mode 100644 (file)
index 0000000..356fb52
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ *  linux/drivers/video/iplan2p8.c -- Low level frame buffer operations for
+ *                                   interleaved bitplanes Ã  la Atari (8
+ *                                   planes, 2 bytes interleave)
+ *
+ *     Created 5 Apr 1997 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+
+#include <asm/setup.h>
+
+#include "atafb.h"
+
+#define BPL    8
+#include "atafb_utils.h"
+
+
+/* Copies a 8 plane column from 's', height 'h', to 'd'. */
+
+/* This expands a 8 bit color into two longs for two movepl (8 plane)
+ * operations.
+ */
+
+void atafb_iplan2p8_copyarea(struct fb_info *info, u_long next_line,
+                            int sy, int sx, int dy, int dx,
+                            int height, int width)
+{
+       /*  bmove() has to distinguish two major cases: If both, source and
+        *  destination, start at even addresses or both are at odd
+        *  addresses, just the first odd and last even column (if present)
+        *  require special treatment (memmove_col()). The rest between
+        *  then can be copied by normal operations, because all adjacent
+        *  bytes are affected and are to be stored in the same order.
+        *    The pathological case is when the move should go from an odd
+        *  address to an even or vice versa. Since the bytes in the plane
+        *  words must be assembled in new order, it seems wisest to make
+        *  all movements by memmove_col().
+        */
+
+       u8 *src, *dst;
+       u32 *s, *d;
+       int w, l , i, j;
+       u_int colsize;
+       u_int upwards = (dy < sy) || (dy == sy && dx < sx);
+
+       colsize = height;
+       if (!((sx ^ dx) & 15)) {
+               /* odd->odd or even->even */
+
+               if (upwards) {
+                       src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
+                       dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
+                       if (sx & 15) {
+                               memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2);
+                               src += BPL * 2;
+                               dst += BPL * 2;
+                               width -= 8;
+                       }
+                       w = width >> 4;
+                       if (w) {
+                               s = (u32 *)src;
+                               d = (u32 *)dst;
+                               w *= BPL / 2;
+                               l = next_line - w * 4;
+                               for (j = height; j > 0; j--) {
+                                       for (i = w; i > 0; i--)
+                                               *d++ = *s++;
+                                       s = (u32 *)((u8 *)s + l);
+                                       d = (u32 *)((u8 *)d + l);
+                               }
+                       }
+                       if (width & 15)
+                               memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL),
+                                             0xff00ff00, height, next_line - BPL * 2);
+               } else {
+                       src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
+                       dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
+
+                       if ((sx + width) & 15) {
+                               src -= BPL * 2;
+                               dst -= BPL * 2;
+                               memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2);
+                               width -= 8;
+                       }
+                       w = width >> 4;
+                       if (w) {
+                               s = (u32 *)src;
+                               d = (u32 *)dst;
+                               w *= BPL / 2;
+                               l = next_line - w * 4;
+                               for (j = height; j > 0; j--) {
+                                       for (i = w; i > 0; i--)
+                                               *--d = *--s;
+                                       s = (u32 *)((u8 *)s - l);
+                                       d = (u32 *)((u8 *)d - l);
+                               }
+                       }
+                       if (sx & 15)
+                               memmove32_col(dst - (width - 16) / (8 / BPL),
+                                             src - (width - 16) / (8 / BPL),
+                                             0xff00ff, colsize, -next_line - BPL * 2);
+               }
+       } else {
+               /* odd->even or even->odd */
+               if (upwards) {
+                       u32 *src32, *dst32;
+                       u32 pval[4], v, v1, mask;
+                       int i, j, w, f;
+
+                       src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL);
+                       dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL);
+
+                       mask = 0xff00ff00;
+                       f = 0;
+                       w = width;
+                       if (sx & 15) {
+                               f = 1;
+                               w += 8;
+                       }
+                       if ((sx + width) & 15)
+                               f |= 2;
+                       w >>= 4;
+                       for (i = height; i; i--) {
+                               src32 = (u32 *)src;
+                               dst32 = (u32 *)dst;
+
+                               if (f & 1) {
+                                       pval[0] = (*src32++ << 8) & mask;
+                                       pval[1] = (*src32++ << 8) & mask;
+                                       pval[2] = (*src32++ << 8) & mask;
+                                       pval[3] = (*src32++ << 8) & mask;
+                               } else {
+                                       pval[0] = dst32[0] & mask;
+                                       pval[1] = dst32[1] & mask;
+                                       pval[2] = dst32[2] & mask;
+                                       pval[3] = dst32[3] & mask;
+                               }
+
+                               for (j = w; j > 0; j--) {
+                                       v = *src32++;
+                                       v1 = v & mask;
+                                       *dst32++ = pval[0] | (v1 >> 8);
+                                       pval[0] = (v ^ v1) << 8;
+                                       v = *src32++;
+                                       v1 = v & mask;
+                                       *dst32++ = pval[1] | (v1 >> 8);
+                                       pval[1] = (v ^ v1) << 8;
+                                       v = *src32++;
+                                       v1 = v & mask;
+                                       *dst32++ = pval[2] | (v1 >> 8);
+                                       pval[2] = (v ^ v1) << 8;
+                                       v = *src32++;
+                                       v1 = v & mask;
+                                       *dst32++ = pval[3] | (v1 >> 8);
+                                       pval[3] = (v ^ v1) << 8;
+                               }
+
+                               if (f & 2) {
+                                       dst32[0] = (dst32[0] & mask) | pval[0];
+                                       dst32[1] = (dst32[1] & mask) | pval[1];
+                                       dst32[2] = (dst32[2] & mask) | pval[2];
+                                       dst32[3] = (dst32[3] & mask) | pval[3];
+                               }
+
+                               src += next_line;
+                               dst += next_line;
+                       }
+               } else {
+                       u32 *src32, *dst32;
+                       u32 pval[4], v, v1, mask;
+                       int i, j, w, f;
+
+                       src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL);
+                       dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL);
+
+                       mask = 0xff00ff;
+                       f = 0;
+                       w = width;
+                       if ((dx + width) & 15)
+                               f = 1;
+                       if (sx & 15) {
+                               f |= 2;
+                               w += 8;
+                       }
+                       w >>= 4;
+                       for (i = height; i; i--) {
+                               src32 = (u32 *)src;
+                               dst32 = (u32 *)dst;
+
+                               if (f & 1) {
+                                       pval[0] = dst32[-1] & mask;
+                                       pval[1] = dst32[-2] & mask;
+                                       pval[2] = dst32[-3] & mask;
+                                       pval[3] = dst32[-4] & mask;
+                               } else {
+                                       pval[0] = (*--src32 >> 8) & mask;
+                                       pval[1] = (*--src32 >> 8) & mask;
+                                       pval[2] = (*--src32 >> 8) & mask;
+                                       pval[3] = (*--src32 >> 8) & mask;
+                               }
+
+                               for (j = w; j > 0; j--) {
+                                       v = *--src32;
+                                       v1 = v & mask;
+                                       *--dst32 = pval[0] | (v1 << 8);
+                                       pval[0] = (v ^ v1) >> 8;
+                                       v = *--src32;
+                                       v1 = v & mask;
+                                       *--dst32 = pval[1] | (v1 << 8);
+                                       pval[1] = (v ^ v1) >> 8;
+                                       v = *--src32;
+                                       v1 = v & mask;
+                                       *--dst32 = pval[2] | (v1 << 8);
+                                       pval[2] = (v ^ v1) >> 8;
+                                       v = *--src32;
+                                       v1 = v & mask;
+                                       *--dst32 = pval[3] | (v1 << 8);
+                                       pval[3] = (v ^ v1) >> 8;
+                               }
+
+                               if (!(f & 2)) {
+                                       dst32[-1] = (dst32[-1] & mask) | pval[0];
+                                       dst32[-2] = (dst32[-2] & mask) | pval[1];
+                                       dst32[-3] = (dst32[-3] & mask) | pval[2];
+                                       dst32[-4] = (dst32[-4] & mask) | pval[3];
+                               }
+
+                               src -= next_line;
+                               dst -= next_line;
+                       }
+               }
+       }
+}
+
+void atafb_iplan2p8_fillrect(struct fb_info *info, u_long next_line, u32 color,
+                             int sy, int sx, int height, int width)
+{
+       u32 *dest;
+       int rows, i;
+       u32 cval[4];
+
+       dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL));
+       if (sx & 15) {
+               u8 *dest8 = (u8 *)dest + 1;
+
+               expand8_col2mask(color, cval);
+
+               for (i = height; i; i--) {
+                       fill8_col(dest8, cval);
+                       dest8 += next_line;
+               }
+               dest += BPL / 2;
+               width -= 8;
+       }
+
+       expand16_col2mask(color, cval);
+       rows = width >> 4;
+       if (rows) {
+               u32 *d = dest;
+               u32 off = next_line - rows * BPL * 2;
+               for (i = height; i; i--) {
+                       d = fill16_col(d, rows, cval);
+                       d = (u32 *)((long)d + off);
+               }
+               dest += rows * BPL / 2;
+               width &= 15;
+       }
+
+       if (width) {
+               u8 *dest8 = (u8 *)dest;
+
+               expand8_col2mask(color, cval);
+
+               for (i = height; i; i--) {
+                       fill8_col(dest8, cval);
+                       dest8 += next_line;
+               }
+       }
+}
+
+void atafb_iplan2p8_linefill(struct fb_info *info, u_long next_line,
+                            int dy, int dx, u32 width,
+                            const u8 *data, u32 bgcolor, u32 fgcolor)
+{
+       u32 *dest;
+       const u16 *data16;
+       int rows;
+       u32 fgm[4], bgm[4], m;
+
+       dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL));
+       if (dx & 15) {
+               fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++);
+               dest += BPL / 2;
+               width -= 8;
+       }
+
+       if (width >= 16) {
+               data16 = (const u16 *)data;
+               expand16_2col2mask(fgcolor, bgcolor, fgm, bgm);
+
+               for (rows = width / 16; rows; rows--) {
+                       u16 d = *data16++;
+                       m = d | ((u32)d << 16);
+                       *dest++ = (m & fgm[0]) ^ bgm[0];
+                       *dest++ = (m & fgm[1]) ^ bgm[1];
+                       *dest++ = (m & fgm[2]) ^ bgm[2];
+                       *dest++ = (m & fgm[3]) ^ bgm[3];
+               }
+
+               data = (const u8 *)data16;
+               width &= 15;
+       }
+
+       if (width)
+               fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
+}
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+
+int init_module(void)
+{
+       return 0;
+}
+
+void cleanup_module(void)
+{
+}
+#endif /* MODULE */
+
+
+    /*
+     *  Visible symbols for modules
+     */
+
+EXPORT_SYMBOL(atafb_iplan2p8_copyarea);
+EXPORT_SYMBOL(atafb_iplan2p8_fillrect);
+EXPORT_SYMBOL(atafb_iplan2p8_linefill);
diff --git a/drivers/video/atafb_mfb.c b/drivers/video/atafb_mfb.c
new file mode 100644 (file)
index 0000000..6a352d6
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ *  linux/drivers/video/mfb.c -- Low level frame buffer operations for
+ *                              monochrome
+ *
+ *     Created 5 Apr 1997 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+
+#include "atafb.h"
+#include "atafb_utils.h"
+
+
+    /*
+     *  Monochrome
+     */
+
+void atafb_mfb_copyarea(struct fb_info *info, u_long next_line,
+                       int sy, int sx, int dy, int dx,
+                       int height, int width)
+{
+       u8 *src, *dest;
+       u_int rows;
+
+       if (sx == 0 && dx == 0 && width == next_line) {
+               src = (u8 *)info->screen_base + sy * (width >> 3);
+               dest = (u8 *)info->screen_base + dy * (width >> 3);
+               fb_memmove(dest, src, height * (width >> 3));
+       } else if (dy <= sy) {
+               src = (u8 *)info->screen_base + sy * next_line + (sx >> 3);
+               dest = (u8 *)info->screen_base + dy * next_line + (dx >> 3);
+               for (rows = height; rows--;) {
+                       fb_memmove(dest, src, width >> 3);
+                       src += next_line;
+                       dest += next_line;
+               }
+       } else {
+               src = (u8 *)info->screen_base + (sy + height - 1) * next_line + (sx >> 3);
+               dest = (u8 *)info->screen_base + (dy + height - 1) * next_line + (dx >> 3);
+               for (rows = height; rows--;) {
+                       fb_memmove(dest, src, width >> 3);
+                       src -= next_line;
+                       dest -= next_line;
+               }
+       }
+}
+
+void atafb_mfb_fillrect(struct fb_info *info, u_long next_line, u32 color,
+                       int sy, int sx, int height, int width)
+{
+       u8 *dest;
+       u_int rows;
+
+       dest = (u8 *)info->screen_base + sy * next_line + (sx >> 3);
+
+       if (sx == 0 && width == next_line) {
+               if (color)
+                       fb_memset255(dest, height * (width >> 3));
+               else
+                       fb_memclear(dest, height * (width >> 3));
+       } else {
+               for (rows = height; rows--; dest += next_line) {
+                       if (color)
+                               fb_memset255(dest, width >> 3);
+                       else
+                               fb_memclear_small(dest, width >> 3);
+               }
+       }
+}
+
+void atafb_mfb_linefill(struct fb_info *info, u_long next_line,
+                       int dy, int dx, u32 width,
+                       const u8 *data, u32 bgcolor, u32 fgcolor)
+{
+       u8 *dest;
+       u_int rows;
+
+       dest = (u8 *)info->screen_base + dy * next_line + (dx >> 3);
+
+       for (rows = width / 8; rows--; /* check margins */ ) {
+               // use fast_memmove or fb_memmove
+               *dest++ = *data++;
+       }
+}
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+
+int init_module(void)
+{
+       return 0;
+}
+
+void cleanup_module(void)
+{
+}
+#endif /* MODULE */
+
+
+    /*
+     *  Visible symbols for modules
+     */
+
+EXPORT_SYMBOL(atafb_mfb_copyarea);
+EXPORT_SYMBOL(atafb_mfb_fillrect);
+EXPORT_SYMBOL(atafb_mfb_linefill);
diff --git a/drivers/video/atafb_utils.h b/drivers/video/atafb_utils.h
new file mode 100644 (file)
index 0000000..ac9e19d
--- /dev/null
@@ -0,0 +1,400 @@
+#ifndef _VIDEO_ATAFB_UTILS_H
+#define _VIDEO_ATAFB_UTILS_H
+
+/* ================================================================= */
+/*                      Utility Assembler Functions                  */
+/* ================================================================= */
+
+/* ====================================================================== */
+
+/* Those of a delicate disposition might like to skip the next couple of
+ * pages.
+ *
+ * These functions are drop in replacements for memmove and
+ * memset(_, 0, _). However their five instances add at least a kilobyte
+ * to the object file. You have been warned.
+ *
+ * Not a great fan of assembler for the sake of it, but I think
+ * that these routines are at least 10 times faster than their C
+ * equivalents for large blits, and that's important to the lowest level of
+ * a graphics driver. Question is whether some scheme with the blitter
+ * would be faster. I suspect not for simple text system - not much
+ * asynchrony.
+ *
+ * Code is very simple, just gruesome expansion. Basic strategy is to
+ * increase data moved/cleared at each step to 16 bytes to reduce
+ * instruction per data move overhead. movem might be faster still
+ * For more than 15 bytes, we try to align the write direction on a
+ * longword boundary to get maximum speed. This is even more gruesome.
+ * Unaligned read/write used requires 68020+ - think this is a problem?
+ *
+ * Sorry!
+ */
+
+
+/* ++roman: I've optimized Robert's original versions in some minor
+ * aspects, e.g. moveq instead of movel, let gcc choose the registers,
+ * use movem in some places...
+ * For other modes than 1 plane, lots of more such assembler functions
+ * were needed (e.g. the ones using movep or expanding color values).
+ */
+
+/* ++andreas: more optimizations:
+   subl #65536,d0 replaced by clrw d0; subql #1,d0 for dbcc
+   addal is faster than addaw
+   movep is rather expensive compared to ordinary move's
+   some functions rewritten in C for clarity, no speed loss */
+
+static inline void *fb_memclear_small(void *s, size_t count)
+{
+       if (!count)
+               return 0;
+
+       asm volatile ("\n"
+               "       lsr.l   #1,%1 ; jcc 1f ; move.b %2,-(%0)\n"
+               "1:     lsr.l   #1,%1 ; jcc 1f ; move.w %2,-(%0)\n"
+               "1:     lsr.l   #1,%1 ; jcc 1f ; move.l %2,-(%0)\n"
+               "1:     lsr.l   #1,%1 ; jcc 1f ; move.l %2,-(%0) ; move.l %2,-(%0)\n"
+               "1:"
+               : "=a" (s), "=d" (count)
+               : "d" (0), "0" ((char *)s + count), "1" (count));
+       asm volatile ("\n"
+               "       subq.l  #1,%1\n"
+               "       jcs     3f\n"
+               "       move.l  %2,%%d4; move.l %2,%%d5; move.l %2,%%d6\n"
+               "2:     movem.l %2/%%d4/%%d5/%%d6,-(%0)\n"
+               "       dbra    %1,2b\n"
+               "3:"
+               : "=a" (s), "=d" (count)
+               : "d" (0), "0" (s), "1" (count)
+               : "d4", "d5", "d6"
+               );
+
+       return 0;
+}
+
+
+static inline void *fb_memclear(void *s, size_t count)
+{
+       if (!count)
+               return 0;
+
+       if (count < 16) {
+               asm volatile ("\n"
+                       "       lsr.l   #1,%1 ; jcc 1f ; clr.b (%0)+\n"
+                       "1:     lsr.l   #1,%1 ; jcc 1f ; clr.w (%0)+\n"
+                       "1:     lsr.l   #1,%1 ; jcc 1f ; clr.l (%0)+\n"
+                       "1:     lsr.l   #1,%1 ; jcc 1f ; clr.l (%0)+ ; clr.l (%0)+\n"
+                       "1:"
+                       : "=a" (s), "=d" (count)
+                       : "0" (s), "1" (count));
+       } else {
+               long tmp;
+               asm volatile ("\n"
+                       "       move.l  %1,%2\n"
+                       "       lsr.l   #1,%2 ; jcc 1f ; clr.b (%0)+ ; subq.w #1,%1\n"
+                       "       lsr.l   #1,%2 ; jcs 2f\n"  /* %0 increased=>bit 2 switched*/
+                       "       clr.w   (%0)+  ; subq.w  #2,%1 ; jra 2f\n"
+                       "1:     lsr.l   #1,%2 ; jcc 2f\n"
+                       "       clr.w   (%0)+  ; subq.w  #2,%1\n"
+                       "2:     move.w  %1,%2; lsr.l #2,%1 ; jeq 6f\n"
+                       "       lsr.l   #1,%1 ; jcc 3f ; clr.l (%0)+\n"
+                       "3:     lsr.l   #1,%1 ; jcc 4f ; clr.l (%0)+ ; clr.l (%0)+\n"
+                       "4:     subq.l  #1,%1 ; jcs 6f\n"
+                       "5:     clr.l   (%0)+; clr.l (%0)+ ; clr.l (%0)+ ; clr.l (%0)+\n"
+                       "       dbra    %1,5b ; clr.w %1; subq.l #1,%1; jcc 5b\n"
+                       "6:     move.w  %2,%1; btst #1,%1 ; jeq 7f ; clr.w (%0)+\n"
+                       "7:     btst    #0,%1 ; jeq 8f ; clr.b (%0)+\n"
+                       "8:"
+                       : "=a" (s), "=d" (count), "=d" (tmp)
+                       : "0" (s), "1" (count));
+       }
+
+       return 0;
+}
+
+
+static inline void *fb_memset255(void *s, size_t count)
+{
+       if (!count)
+               return 0;
+
+       asm volatile ("\n"
+               "       lsr.l   #1,%1 ; jcc 1f ; move.b %2,-(%0)\n"
+               "1:     lsr.l   #1,%1 ; jcc 1f ; move.w %2,-(%0)\n"
+               "1:     lsr.l   #1,%1 ; jcc 1f ; move.l %2,-(%0)\n"
+               "1:     lsr.l   #1,%1 ; jcc 1f ; move.l %2,-(%0) ; move.l %2,-(%0)\n"
+               "1:"
+               : "=a" (s), "=d" (count)
+               : "d" (-1), "0" ((char *)s+count), "1" (count));
+       asm volatile ("\n"
+               "       subq.l  #1,%1 ; jcs 3f\n"
+               "       move.l  %2,%%d4; move.l %2,%%d5; move.l %2,%%d6\n"
+               "2:     movem.l %2/%%d4/%%d5/%%d6,-(%0)\n"
+               "       dbra    %1,2b\n"
+               "3:"
+               : "=a" (s), "=d" (count)
+               : "d" (-1), "0" (s), "1" (count)
+               : "d4", "d5", "d6");
+
+       return 0;
+}
+
+
+static inline void *fb_memmove(void *d, const void *s, size_t count)
+{
+       if (d < s) {
+               if (count < 16) {
+                       asm volatile ("\n"
+                               "       lsr.l   #1,%2 ; jcc 1f ; move.b (%1)+,(%0)+\n"
+                               "1:     lsr.l   #1,%2 ; jcc 1f ; move.w (%1)+,(%0)+\n"
+                               "1:     lsr.l   #1,%2 ; jcc 1f ; move.l (%1)+,(%0)+\n"
+                               "1:     lsr.l   #1,%2 ; jcc 1f ; move.l (%1)+,(%0)+ ; move.l (%1)+,(%0)+\n"
+                               "1:"
+                               : "=a" (d), "=a" (s), "=d" (count)
+                               : "0" (d), "1" (s), "2" (count));
+               } else {
+                       long tmp;
+                       asm volatile ("\n"
+                               "       move.l  %0,%3\n"
+                               "       lsr.l   #1,%3 ; jcc 1f ; move.b (%1)+,(%0)+ ; subqw #1,%2\n"
+                               "       lsr.l   #1,%3 ; jcs 2f\n"  /* %0 increased=>bit 2 switched*/
+                               "       move.w  (%1)+,(%0)+  ; subqw  #2,%2 ; jra 2f\n"
+                               "1:     lsr.l   #1,%3 ; jcc 2f\n"
+                               "       move.w  (%1)+,(%0)+  ; subqw  #2,%2\n"
+                               "2:     move.w  %2,%-; lsr.l #2,%2 ; jeq 6f\n"
+                               "       lsr.l   #1,%2 ; jcc 3f ; move.l (%1)+,(%0)+\n"
+                               "3:     lsr.l   #1,%2 ; jcc 4f ; move.l (%1)+,(%0)+ ; move.l (%1)+,(%0)+\n"
+                               "4:     subq.l  #1,%2 ; jcs 6f\n"
+                               "5:     move.l  (%1)+,(%0)+; move.l (%1)+,(%0)+\n"
+                               "       move.l  (%1)+,(%0)+; move.l (%1)+,(%0)+\n"
+                               "       dbra    %2,5b ; clr.w %2; subq.l #1,%2; jcc 5b\n"
+                               "6:     move.w  %+,%2; btst #1,%2 ; jeq 7f ; move.w (%1)+,(%0)+\n"
+                               "7:     btst    #0,%2 ; jeq 8f ; move.b (%1)+,(%0)+\n"
+                               "8:"
+                               : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
+                               : "0" (d), "1" (s), "2" (count));
+               }
+       } else {
+               if (count < 16) {
+                       asm volatile ("\n"
+                               "       lsr.l   #1,%2 ; jcc 1f ; move.b -(%1),-(%0)\n"
+                               "1:     lsr.l   #1,%2 ; jcc 1f ; move.w -(%1),-(%0)\n"
+                               "1:     lsr.l   #1,%2 ; jcc 1f ; move.l -(%1),-(%0)\n"
+                               "1:     lsr.l   #1,%2 ; jcc 1f ; move.l -(%1),-(%0) ; move.l -(%1),-(%0)\n"
+                               "1:"
+                               : "=a" (d), "=a" (s), "=d" (count)
+                               : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count));
+               } else {
+                       long tmp;
+
+                       asm volatile ("\n"
+                               "       move.l  %0,%3\n"
+                               "       lsr.l   #1,%3 ; jcc 1f ; move.b -(%1),-(%0) ; subqw #1,%2\n"
+                               "       lsr.l   #1,%3 ; jcs 2f\n"  /* %0 increased=>bit 2 switched*/
+                               "       move.w  -(%1),-(%0) ; subqw  #2,%2 ; jra 2f\n"
+                               "1:     lsr.l   #1,%3 ; jcc 2f\n"
+                               "       move.w  -(%1),-(%0) ; subqw  #2,%2\n"
+                               "2:     move.w  %2,%-; lsr.l #2,%2 ; jeq 6f\n"
+                               "       lsr.l   #1,%2 ; jcc 3f ; move.l -(%1),-(%0)\n"
+                               "3:     lsr.l   #1,%2 ; jcc 4f ; move.l -(%1),-(%0) ; move.l -(%1),-(%0)\n"
+                               "4:     subq.l  #1,%2 ; jcs 6f\n"
+                               "5:     move.l  -(%1),-(%0); move.l -(%1),-(%0)\n"
+                               "       move.l  -(%1),-(%0); move.l -(%1),-(%0)\n"
+                               "       dbra    %2,5b ; clr.w %2; subq.l #1,%2; jcc 5b\n"
+                               "6:     move.w  %+,%2; btst #1,%2 ; jeq 7f ; move.w -(%1),-(%0)\n"
+                               "7:     btst    #0,%2 ; jeq 8f ; move.b -(%1),-(%0)\n"
+                               "8:"
+                               : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
+                               : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count));
+               }
+       }
+
+       return 0;
+}
+
+
+/* ++andreas: Simple and fast version of memmove, assumes size is
+   divisible by 16, suitable for moving the whole screen bitplane */
+static inline void fast_memmove(char *dst, const char *src, size_t size)
+{
+       if (!size)
+               return;
+       if (dst < src)
+               asm volatile ("\n"
+                       "1:     movem.l (%0)+,%%d0/%%d1/%%a0/%%a1\n"
+                       "       movem.l %%d0/%%d1/%%a0/%%a1,%1@\n"
+                       "       addq.l  #8,%1; addq.l #8,%1\n"
+                       "       dbra    %2,1b\n"
+                       "       clr.w   %2; subq.l #1,%2\n"
+                       "       jcc     1b"
+                       : "=a" (src), "=a" (dst), "=d" (size)
+                       : "0" (src), "1" (dst), "2" (size / 16 - 1)
+                       : "d0", "d1", "a0", "a1", "memory");
+       else
+               asm volatile ("\n"
+                       "1:     subq.l  #8,%0; subq.l #8,%0\n"
+                       "       movem.l %0@,%%d0/%%d1/%%a0/%%a1\n"
+                       "       movem.l %%d0/%%d1/%%a0/%%a1,-(%1)\n"
+                       "       dbra    %2,1b\n"
+                       "       clr.w   %2; subq.l #1,%2\n"
+                       "       jcc 1b"
+                       : "=a" (src), "=a" (dst), "=d" (size)
+                       : "0" (src + size), "1" (dst + size), "2" (size / 16 - 1)
+                       : "d0", "d1", "a0", "a1", "memory");
+}
+
+#ifdef BPL
+
+/*
+ * This expands a up to 8 bit color into two longs
+ * for movel operations.
+ */
+static const u32 four2long[] = {
+       0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
+       0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
+       0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
+       0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff,
+};
+
+static inline void expand8_col2mask(u8 c, u32 m[])
+{
+       m[0] = four2long[c & 15];
+#if BPL > 4
+       m[1] = four2long[c >> 4];
+#endif
+}
+
+static inline void expand8_2col2mask(u8 fg, u8 bg, u32 fgm[], u32 bgm[])
+{
+       fgm[0] = four2long[fg & 15] ^ (bgm[0] = four2long[bg & 15]);
+#if BPL > 4
+       fgm[1] = four2long[fg >> 4] ^ (bgm[1] = four2long[bg >> 4]);
+#endif
+}
+
+/*
+ * set an 8bit value to a color
+ */
+static inline void fill8_col(u8 *dst, u32 m[])
+{
+       u32 tmp = m[0];
+       dst[0] = tmp;
+       dst[2] = (tmp >>= 8);
+#if BPL > 2
+       dst[4] = (tmp >>= 8);
+       dst[6] = tmp >> 8;
+#endif
+#if BPL > 4
+       tmp = m[1];
+       dst[8] = tmp;
+       dst[10] = (tmp >>= 8);
+       dst[12] = (tmp >>= 8);
+       dst[14] = tmp >> 8;
+#endif
+}
+
+/*
+ * set an 8bit value according to foreground/background color
+ */
+static inline void fill8_2col(u8 *dst, u8 fg, u8 bg, u32 mask)
+{
+       u32 fgm[2], bgm[2], tmp;
+
+       expand8_2col2mask(fg, bg, fgm, bgm);
+
+       mask |= mask << 8;
+#if BPL > 2
+       mask |= mask << 16;
+#endif
+       tmp = (mask & fgm[0]) ^ bgm[0];
+       dst[0] = tmp;
+       dst[2] = (tmp >>= 8);
+#if BPL > 2
+       dst[4] = (tmp >>= 8);
+       dst[6] = tmp >> 8;
+#endif
+#if BPL > 4
+       tmp = (mask & fgm[1]) ^ bgm[1];
+       dst[8] = tmp;
+       dst[10] = (tmp >>= 8);
+       dst[12] = (tmp >>= 8);
+       dst[14] = tmp >> 8;
+#endif
+}
+
+static const u32 two2word[] = {
+       0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
+};
+
+static inline void expand16_col2mask(u8 c, u32 m[])
+{
+       m[0] = two2word[c & 3];
+#if BPL > 2
+       m[1] = two2word[(c >> 2) & 3];
+#endif
+#if BPL > 4
+       m[2] = two2word[(c >> 4) & 3];
+       m[3] = two2word[c >> 6];
+#endif
+}
+
+static inline void expand16_2col2mask(u8 fg, u8 bg, u32 fgm[], u32 bgm[])
+{
+       bgm[0] = two2word[bg & 3];
+       fgm[0] = two2word[fg & 3] ^ bgm[0];
+#if BPL > 2
+       bgm[1] = two2word[(bg >> 2) & 3];
+       fgm[1] = two2word[(fg >> 2) & 3] ^ bgm[1];
+#endif
+#if BPL > 4
+       bgm[2] = two2word[(bg >> 4) & 3];
+       fgm[2] = two2word[(fg >> 4) & 3] ^ bgm[2];
+       bgm[3] = two2word[bg >> 6];
+       fgm[3] = two2word[fg >> 6] ^ bgm[3];
+#endif
+}
+
+static inline u32 *fill16_col(u32 *dst, int rows, u32 m[])
+{
+       while (rows) {
+               *dst++ = m[0];
+#if BPL > 2
+               *dst++ = m[1];
+#endif
+#if BPL > 4
+               *dst++ = m[2];
+               *dst++ = m[3];
+#endif
+               rows--;
+       }
+       return dst;
+}
+
+static inline void memmove32_col(void *dst, void *src, u32 mask, u32 h, u32 bytes)
+{
+       u32 *s, *d, v;
+
+        s = src;
+        d = dst;
+        do {
+                v = (*s++ & mask) | (*d  & ~mask);
+                *d++ = v;
+#if BPL > 2
+                v = (*s++ & mask) | (*d  & ~mask);
+                *d++ = v;
+#endif
+#if BPL > 4
+                v = (*s++ & mask) | (*d  & ~mask);
+                *d++ = v;
+                v = (*s++ & mask) | (*d  & ~mask);
+                *d++ = v;
+#endif
+                d = (u32 *)((u8 *)d + bytes);
+                s = (u32 *)((u8 *)s + bytes);
+        } while (--h);
+}
+
+#endif
+
+#endif /* _VIDEO_ATAFB_UTILS_H */
index 5084799..7db9de6 100644 (file)
@@ -1,7 +1,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
 #include <linux/fb.h>
 
 
index ca93a75..b7655c0 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/interrupt.h>
 #include <linux/fb.h>
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <asm/io.h>
 #include <asm/jazz.h>
 
index f4ede5f..61e4c87 100644 (file)
@@ -104,7 +104,8 @@ static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo,
 
        chan->dinfo                                     = dinfo;
        chan->reg                                       = reg;
-       snprintf(chan->adapter.name, I2C_NAME_SIZE, "intelfb %s", name);
+       snprintf(chan->adapter.name, sizeof(chan->adapter.name),
+                "intelfb %s", name);
        chan->adapter.owner                     = THIS_MODULE;
        chan->adapter.id                        = I2C_HW_B_INTELFB;
        chan->adapter.algo_data         = &chan->algo;
index 5ec718a..4baab7b 100644 (file)
@@ -111,7 +111,7 @@ static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo,
        b->mask.data = data;
        b->mask.clock = clock;
        b->adapter = matrox_i2c_adapter_template;
-       snprintf(b->adapter.name, I2C_NAME_SIZE, name,
+       snprintf(b->adapter.name, sizeof(b->adapter.name), name,
                minfo->fbcon.node);
        i2c_set_adapdata(&b->adapter, b);
        b->adapter.algo_data = &b->bac;
index 2338716..e64f8b5 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/interrupt.h>
 #include <linux/fb.h>
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <linux/nvram.h>
 #include <asm/io.h>
 #include <asm/prom.h>
index 81e43cd..07d1979 100644 (file)
@@ -32,6 +32,8 @@
 #include <linux/ioctl.h>
 #include <linux/notifier.h>
 #include <linux/reboot.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
 
 #include <asm/uaccess.h>
 #include <linux/fb.h>
@@ -45,7 +47,7 @@
 #include <asm/ps3.h>
 
 #ifdef PS3FB_DEBUG
-#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ##args)
+#define DPRINTK(fmt, args...) printk("%s: " fmt, __func__ , ##args)
 #else
 #define DPRINTK(fmt, args...)
 #endif
@@ -129,7 +131,6 @@ struct ps3fb_priv {
        u64 context_handle, memory_handle;
        void *xdr_ea;
        struct gpu_driver_info *dinfo;
-       struct semaphore sem;
        u32 res_index;
 
        u64 vblank_count;       /* frame count */
@@ -139,6 +140,8 @@ struct ps3fb_priv {
        atomic_t ext_flip;      /* on/off flip with vsync */
        atomic_t f_count;       /* fb_open count */
        int is_blanked;
+       int is_kicked;
+       struct task_struct *task;
 };
 static struct ps3fb_priv ps3fb;
 
@@ -294,10 +297,10 @@ static const struct fb_videomode ps3fb_modedb[] = {
 #define VP_OFF(i)      (WIDTH(i) * Y_OFF(i) * BPP + X_OFF(i) * BPP)
 #define FB_OFF(i)      (GPU_OFFSET - VP_OFF(i) % GPU_OFFSET)
 
-static int ps3fb_mode = 0;
+static int ps3fb_mode;
 module_param(ps3fb_mode, bool, 0);
 
-static char *mode_option __initdata = NULL;
+static char *mode_option __initdata;
 
 
 static int ps3fb_get_res_table(u32 xres, u32 yres)
@@ -393,7 +396,7 @@ static int ps3fb_sync(u32 frame)
 
        if (frame > ps3fb.num_frames - 1) {
                printk(KERN_WARNING "%s: invalid frame number (%u)\n",
-                      __FUNCTION__, frame);
+                      __func__, frame);
                return -EINVAL;
        }
        offset = xres * yres * BPP * frame;
@@ -406,23 +409,26 @@ static int ps3fb_sync(u32 frame)
                                           (xres << 16) | yres,
                                           xres * BPP); /* line_length */
        if (status)
-               printk(KERN_ERR "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n",
-                      __FUNCTION__, status);
+               printk(KERN_ERR
+                      "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n",
+                      __func__, status);
 #ifdef HEAD_A
        status = lv1_gpu_context_attribute(ps3fb.context_handle,
                                           L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
                                           0, offset, 0, 0);
        if (status)
-               printk(KERN_ERR "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
-                      __FUNCTION__, status);
+               printk(KERN_ERR
+                      "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
+                      __func__, status);
 #endif
 #ifdef HEAD_B
        status = lv1_gpu_context_attribute(ps3fb.context_handle,
                                           L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
                                           1, offset, 0, 0);
        if (status)
-               printk(KERN_ERR "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
-                      __FUNCTION__, status);
+               printk(KERN_ERR
+                      "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
+                      __func__, status);
 #endif
        return 0;
 }
@@ -631,7 +637,7 @@ static int ps3fb_blank(int blank, struct fb_info *info)
 {
        int retval;
 
-       DPRINTK("%s: blank:%d\n", __FUNCTION__, blank);
+       DPRINTK("%s: blank:%d\n", __func__, blank);
        switch (blank) {
        case FB_BLANK_POWERDOWN:
        case FB_BLANK_HSYNC_SUSPEND:
@@ -677,13 +683,10 @@ EXPORT_SYMBOL_GPL(ps3fb_wait_for_vsync);
 
 void ps3fb_flip_ctl(int on)
 {
-       if (on) {
-               if (atomic_read(&ps3fb.ext_flip) > 0) {
-                       atomic_dec(&ps3fb.ext_flip);
-               }
-       } else {
+       if (on)
+               atomic_dec_if_positive(&ps3fb.ext_flip);
+       else
                atomic_inc(&ps3fb.ext_flip);
-       }
 }
 
 EXPORT_SYMBOL_GPL(ps3fb_flip_ctl);
@@ -732,6 +735,11 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
                        if (copy_from_user(&val, argp, sizeof(val)))
                                break;
 
+                       if (!(val & PS3AV_MODE_MASK)) {
+                               u32 id = ps3av_get_auto_mode(0);
+                               if (id > 0)
+                                       val = (val & ~PS3AV_MODE_MASK) | id;
+                       }
                        DPRINTK("PS3FB_IOCTL_SETMODE:%x\n", val);
                        retval = -EINVAL;
                        old_mode = ps3fb_mode;
@@ -783,8 +791,7 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
 
        case PS3FB_IOCTL_OFF:
                DPRINTK("PS3FB_IOCTL_OFF:\n");
-               if (atomic_read(&ps3fb.ext_flip) > 0)
-                       atomic_dec(&ps3fb.ext_flip);
+               atomic_dec_if_positive(&ps3fb.ext_flip);
                retval = 0;
                break;
 
@@ -805,11 +812,14 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
 
 static int ps3fbd(void *arg)
 {
-       daemonize("ps3fbd");
-       for (;;) {
-               down(&ps3fb.sem);
-               if (atomic_read(&ps3fb.ext_flip) == 0)
+       while (!kthread_should_stop()) {
+               try_to_freeze();
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (ps3fb.is_kicked) {
+                       ps3fb.is_kicked = 0;
                        ps3fb_sync(0);  /* single buffer */
+               }
+               schedule();
        }
        return 0;
 }
@@ -823,15 +833,18 @@ static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr)
        status = lv1_gpu_context_intr(ps3fb.context_handle, &v1);
        if (status) {
                printk(KERN_ERR "%s: lv1_gpu_context_intr failed: %d\n",
-                      __FUNCTION__, status);
+                      __func__, status);
                return IRQ_NONE;
        }
 
        if (v1 & (1 << GPU_INTR_STATUS_VSYNC_1)) {
                /* VSYNC */
                ps3fb.vblank_count = head->vblank_count;
-               if (!ps3fb.is_blanked)
-                       up(&ps3fb.sem);
+               if (ps3fb.task && !ps3fb.is_blanked &&
+                   !atomic_read(&ps3fb.ext_flip)) {
+                       ps3fb.is_kicked = 1;
+                       wake_up_process(ps3fb.task);
+               }
                wake_up_interruptible(&ps3fb.wait_vsync);
        }
 
@@ -879,7 +892,7 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev)
                dinfo->nvcore_frequency/1000000, dinfo->memory_frequency/1000000);
 
        if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) {
-               printk(KERN_ERR "%s: version_driver err:%x\n", __FUNCTION__,
+               printk(KERN_ERR "%s: version_driver err:%x\n", __func__,
                       dinfo->version_driver);
                return -EINVAL;
        }
@@ -888,7 +901,7 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev)
        error = ps3_alloc_irq(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
                              &ps3fb.irq_no);
        if (error) {
-               printk(KERN_ERR "%s: ps3_alloc_irq failed %d\n", __FUNCTION__,
+               printk(KERN_ERR "%s: ps3_alloc_irq failed %d\n", __func__,
                       error);
                return error;
        }
@@ -896,7 +909,7 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev)
        error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED,
                            "ps3fb vsync", ps3fb.dev);
        if (error) {
-               printk(KERN_ERR "%s: request_irq failed %d\n", __FUNCTION__,
+               printk(KERN_ERR "%s: request_irq failed %d\n", __func__,
                       error);
                ps3_free_irq(ps3fb.irq_no);
                return error;
@@ -915,7 +928,7 @@ static int ps3fb_xdr_settings(u64 xdr_lpar)
                                       xdr_lpar, ps3fb_videomemory.size, 0);
        if (status) {
                printk(KERN_ERR "%s: lv1_gpu_context_iomap failed: %d\n",
-                      __FUNCTION__, status);
+                      __func__, status);
                return -ENXIO;
        }
        DPRINTK("video:%p xdr_ea:%p ioif:%lx lpar:%lx phys:%lx size:%lx\n",
@@ -927,8 +940,9 @@ static int ps3fb_xdr_settings(u64 xdr_lpar)
                                           xdr_lpar, ps3fb_videomemory.size,
                                           GPU_IOIF, 0);
        if (status) {
-               printk(KERN_ERR "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n",
-                      __FUNCTION__, status);
+               printk(KERN_ERR
+                      "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n",
+                      __func__, status);
                return -ENXIO;
        }
        return 0;
@@ -968,13 +982,14 @@ static int __init ps3fb_probe(struct platform_device *dev)
        u64 xdr_lpar;
        int status;
        unsigned long offset;
+       struct task_struct *task;
 
        /* get gpu context handle */
        status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0,
                                         &ps3fb.memory_handle, &ddr_lpar);
        if (status) {
                printk(KERN_ERR "%s: lv1_gpu_memory_allocate failed: %d\n",
-                      __FUNCTION__, status);
+                      __func__, status);
                goto err;
        }
        DPRINTK("ddr:lpar:0x%lx\n", ddr_lpar);
@@ -985,14 +1000,14 @@ static int __init ps3fb_probe(struct platform_device *dev)
                                          &lpar_reports, &lpar_reports_size);
        if (status) {
                printk(KERN_ERR "%s: lv1_gpu_context_attribute failed: %d\n",
-                      __FUNCTION__, status);
+                      __func__, status);
                goto err_gpu_memory_free;
        }
 
        /* vsync interrupt */
        ps3fb.dinfo = ioremap(lpar_driver_info, 128 * 1024);
        if (!ps3fb.dinfo) {
-               printk(KERN_ERR "%s: ioremap failed\n", __FUNCTION__);
+               printk(KERN_ERR "%s: ioremap failed\n", __func__);
                goto err_gpu_context_free;
        }
 
@@ -1050,9 +1065,18 @@ static int __init ps3fb_probe(struct platform_device *dev)
               "fb%d: PS3 frame buffer device, using %ld KiB of video memory\n",
               info->node, ps3fb_videomemory.size >> 10);
 
-       kernel_thread(ps3fbd, info, CLONE_KERNEL);
+       task = kthread_run(ps3fbd, info, "ps3fbd");
+       if (IS_ERR(task)) {
+               retval = PTR_ERR(task);
+               goto err_unregister_framebuffer;
+       }
+
+       ps3fb.task = task;
+
        return 0;
 
+err_unregister_framebuffer:
+       unregister_framebuffer(info);
 err_fb_dealloc:
        fb_dealloc_cmap(&info->cmap);
 err_framebuffer_release:
@@ -1083,6 +1107,11 @@ void ps3fb_cleanup(void)
 {
        int status;
 
+       if (ps3fb.task) {
+               struct task_struct *task = ps3fb.task;
+               ps3fb.task = NULL;
+               kthread_stop(task);
+       }
        if (ps3fb.irq_no) {
                free_irq(ps3fb.irq_no, ps3fb.dev);
                ps3_free_irq(ps3fb.irq_no);
@@ -1137,8 +1166,9 @@ int ps3fb_set_sync(void)
                                           L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
                                           0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
        if (status) {
-               printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n",
-                      __FUNCTION__, status);
+               printk(KERN_ERR
+                      "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n",
+                      __func__, status);
                return -1;
        }
 #endif
@@ -1148,8 +1178,9 @@ int ps3fb_set_sync(void)
                                           1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
 
        if (status) {
-               printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
-                      __FUNCTION__, status);
+               printk(KERN_ERR
+                      "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
+                      __func__, status);
                return -1;
        }
 #endif
@@ -1174,7 +1205,7 @@ static int __init ps3fb_init(void)
 
        error = ps3av_dev_open();
        if (error) {
-               printk(KERN_ERR "%s: ps3av_dev_open failed\n", __FUNCTION__);
+               printk(KERN_ERR "%s: ps3av_dev_open failed\n", __func__);
                goto err;
        }
 
@@ -1195,7 +1226,6 @@ static int __init ps3fb_init(void)
 
        atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */
        atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */
-       init_MUTEX(&ps3fb.sem);
        init_waitqueue_head(&ps3fb.wait_vsync);
        ps3fb.num_frames = 1;
 
index 69f3b26..c97709e 100644 (file)
@@ -64,7 +64,6 @@
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
-#include <linux/pci.h>
 
 #include <asm/grfioctl.h>      /* for HP-UX compatibility */
 #include <asm/uaccess.h>
index 06fc19a..ad66f07 100644 (file)
@@ -51,7 +51,6 @@
 #include <linux/fb.h>
 #include <linux/selection.h>
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <linux/nvram.h>
 #include <linux/adb.h>
 #include <linux/cuda.h>
index b3ce885..2ce4ceb 100644 (file)
@@ -90,8 +90,9 @@ get_zorro_dev_info(char *buf, char **start, off_t pos, int count)
        for (slot = cnt = 0; slot < zorro_num_autocon && count > cnt; slot++) {
                struct zorro_dev *z = &zorro_autocon[slot];
                len = sprintf(buf, "%02x\t%08x\t%08lx\t%08lx\t%02x\n", slot,
-                             z->id, zorro_resource_start(z),
-                             zorro_resource_len(z), z->rom.er_Type);
+                             z->id, (unsigned long)zorro_resource_start(z),
+                             (unsigned long)zorro_resource_len(z),
+                             z->rom.er_Type);
                at += len;
                if (at >= pos) {
                        if (!*start) {
index 87c29d7..c3ba0ec 100644 (file)
@@ -42,7 +42,8 @@ static ssize_t zorro_show_resource(struct device *dev, struct device_attribute *
        struct zorro_dev *z = to_zorro_dev(dev);
 
        return sprintf(buf, "0x%08lx 0x%08lx 0x%08lx\n",
-                      zorro_resource_start(z), zorro_resource_end(z),
+                      (unsigned long)zorro_resource_start(z),
+                      (unsigned long)zorro_resource_end(z),
                       zorro_resource_flags(z));
 }
 
index 0f2b406..4cc42b6 100644 (file)
@@ -164,7 +164,8 @@ static int __init zorro_init(void)
        if (request_resource(zorro_find_parent_resource(z), &z->resource))
            printk(KERN_ERR "Zorro: Address space collision on device %s "
                   "[%lx:%lx]\n",
-                  z->name, zorro_resource_start(z), zorro_resource_end(z));
+                  z->name, (unsigned long)zorro_resource_start(z),
+                  (unsigned long)zorro_resource_end(z));
        sprintf(z->dev.bus_id, "%02x", i);
        z->dev.parent = &zorro_bus.dev;
        z->dev.bus = &zorro_bus_type;
index a42f767..8ea7b04 100644 (file)
@@ -1734,6 +1734,18 @@ config SUNRPC
 config SUNRPC_GSS
        tristate
 
+config SUNRPC_BIND34
+       bool "Support for rpcbind versions 3 & 4 (EXPERIMENTAL)"
+       depends on SUNRPC && EXPERIMENTAL
+       help
+         Provides kernel support for querying rpcbind servers via versions 3
+         and 4 of the rpcbind protocol.  The kernel automatically falls back
+         to version 2 if a remote rpcbind service does not support versions
+         3 or 4.
+
+         If unsure, say N to get traditional behavior (version 2 rpcbind
+         requests only).
+
 config RPCSEC_GSS_KRB5
        tristate "Secure RPC: Kerberos V mechanism (EXPERIMENTAL)"
        depends on SUNRPC && EXPERIMENTAL
@@ -2020,7 +2032,6 @@ config AFS_FS
        tristate "Andrew File System support (AFS) (EXPERIMENTAL)"
        depends on INET && EXPERIMENTAL
        select AF_RXRPC
-       select KEYS
        help
          If you say Y here, you will get an experimental Andrew File System
          driver. It currently only supports unsecured read-only AFS access.
index 01545eb..cf83e5d 100644 (file)
@@ -18,7 +18,7 @@ kafs-objs := \
        security.o \
        server.o \
        super.o \
-       use-rtnetlink.o \
+       netdevices.o \
        vlclient.o \
        vlocation.o \
        vnode.o \
index 639399f..9bdbf36 100644 (file)
@@ -468,7 +468,7 @@ int __init afs_callback_update_init(void)
 /*
  * shut down the callback update process
  */
-void __exit afs_callback_update_kill(void)
+void afs_callback_update_kill(void)
 {
        destroy_workqueue(afs_callback_update_worker);
 }
index 6685f4c..d5b2ad6 100644 (file)
@@ -443,6 +443,7 @@ static void SRXAFSCB_GetCapabilities(struct work_struct *work)
                        reply.ia.netmask[loop] = ifs[loop].netmask.s_addr;
                        reply.ia.mtu[loop] = htonl(ifs[loop].mtu);
                }
+               kfree(ifs);
        }
 
        reply.cap.capcount = htonl(1);
index 2393d2a..e54e6c2 100644 (file)
@@ -266,7 +266,8 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call,
                call->unmarshall++;
 
                if (call->count < PAGE_SIZE) {
-                       buffer = kmap_atomic(call->reply3, KM_USER0);
+                       page = call->reply3;
+                       buffer = kmap_atomic(page, KM_USER0);
                        memset(buffer + PAGE_SIZE - call->count, 0,
                               call->count);
                        kunmap_atomic(buffer, KM_USER0);
index 34665f7..d90c158 100644 (file)
@@ -349,7 +349,6 @@ struct afs_permits {
  * record of one of a system's set of network interfaces
  */
 struct afs_interface {
-       unsigned        index;          /* interface index */
        struct in_addr  address;        /* IPv4 address bound to interface */
        struct in_addr  netmask;        /* netmask applied to address */
        unsigned        mtu;            /* MTU of interface */
@@ -392,7 +391,7 @@ extern void afs_give_up_callback(struct afs_vnode *);
 extern void afs_dispatch_give_up_callbacks(struct work_struct *);
 extern void afs_flush_callback_breaks(struct afs_server *);
 extern int __init afs_callback_update_init(void);
-extern void __exit afs_callback_update_kill(void);
+extern void afs_callback_update_kill(void);
 
 /*
  * cell.c
@@ -564,7 +563,7 @@ extern void afs_fs_exit(void);
  * use-rtnetlink.c
  */
 extern int afs_get_ipv4_interfaces(struct afs_interface *, size_t, bool);
-extern int afs_get_MAC_address(u8 [6]);
+extern int afs_get_MAC_address(u8 *, size_t);
 
 /*
  * vlclient.c
@@ -591,7 +590,7 @@ extern struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *,
                                                  struct key *,
                                                  const char *, size_t);
 extern void afs_put_vlocation(struct afs_vlocation *);
-extern void __exit afs_vlocation_purge(void);
+extern void afs_vlocation_purge(void);
 
 /*
  * vnode.c
index 40c2704..80ec6fd 100644 (file)
@@ -54,7 +54,7 @@ static int __init afs_get_client_UUID(void)
 
        /* read the MAC address of one of the external interfaces and construct
         * a UUID from it */
-       ret = afs_get_MAC_address(afs_uuid.node);
+       ret = afs_get_MAC_address(afs_uuid.node, sizeof(afs_uuid.node));
        if (ret < 0)
                return ret;
 
diff --git a/fs/afs/netdevices.c b/fs/afs/netdevices.c
new file mode 100644 (file)
index 0000000..fc27d4b
--- /dev/null
@@ -0,0 +1,68 @@
+/* AFS network device helpers
+ *
+ * Copyright (c) 2007 Patrick McHardy <kaber@trash.net>
+ */
+
+#include <linux/string.h>
+#include <linux/rtnetlink.h>
+#include <linux/inetdevice.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include "internal.h"
+
+/*
+ * get a MAC address from a random ethernet interface that has a real one
+ * - the buffer will normally be 6 bytes in size
+ */
+int afs_get_MAC_address(u8 *mac, size_t maclen)
+{
+       struct net_device *dev;
+       int ret = -ENODEV;
+
+       if (maclen != ETH_ALEN)
+               BUG();
+
+       rtnl_lock();
+       dev = __dev_getfirstbyhwtype(ARPHRD_ETHER);
+       if (dev) {
+               memcpy(mac, dev->dev_addr, maclen);
+               ret = 0;
+       }
+       rtnl_unlock();
+       return ret;
+}
+
+/*
+ * get a list of this system's interface IPv4 addresses, netmasks and MTUs
+ * - maxbufs must be at least 1
+ * - returns the number of interface records in the buffer
+ */
+int afs_get_ipv4_interfaces(struct afs_interface *bufs, size_t maxbufs,
+                           bool wantloopback)
+{
+       struct net_device *dev;
+       struct in_device *idev;
+       int n = 0;
+
+       ASSERT(maxbufs > 0);
+
+       rtnl_lock();
+       for_each_netdev(dev) {
+               if (dev->type == ARPHRD_LOOPBACK && !wantloopback)
+                       continue;
+               idev = __in_dev_get_rtnl(dev);
+               if (!idev)
+                       continue;
+               for_primary_ifa(idev) {
+                       bufs[n].address.s_addr = ifa->ifa_address;
+                       bufs[n].netmask.s_addr = ifa->ifa_mask;
+                       bufs[n].mtu = dev->mtu;
+                       n++;
+                       if (n >= maxbufs)
+                               goto out;
+               } endfor_ifa(idev);
+       }
+out:
+       rtnl_unlock();
+       return n;
+}
index cebd03c..41173f8 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
+#include <linux/parser.h>
 #include "internal.h"
 
 #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */
@@ -42,7 +43,7 @@ struct file_system_type afs_fs_type = {
        .name           = "afs",
        .get_sb         = afs_get_sb,
        .kill_sb        = kill_anon_super,
-       .fs_flags       = FS_BINARY_MOUNTDATA,
+       .fs_flags       = 0,
 };
 
 static const struct super_operations afs_super_ops = {
@@ -58,6 +59,20 @@ static const struct super_operations afs_super_ops = {
 static struct kmem_cache *afs_inode_cachep;
 static atomic_t afs_count_active_inodes;
 
+enum {
+       afs_no_opt,
+       afs_opt_cell,
+       afs_opt_rwpath,
+       afs_opt_vol,
+};
+
+static const match_table_t afs_options_list = {
+       { afs_opt_cell,         "cell=%s"       },
+       { afs_opt_rwpath,       "rwpath"        },
+       { afs_opt_vol,          "vol=%s"        },
+       { afs_no_opt,           NULL            },
+};
+
 /*
  * initialise the filesystem
  */
@@ -115,31 +130,6 @@ void __exit afs_fs_exit(void)
 }
 
 /*
- * check that an argument has a value
- */
-static int want_arg(char **_value, const char *option)
-{
-       if (!_value || !*_value || !**_value) {
-               printk(KERN_NOTICE "kAFS: %s: argument missing\n", option);
-               return 0;
-       }
-       return 1;
-}
-
-/*
- * check that there's no subsequent value
- */
-static int want_no_value(char *const *_value, const char *option)
-{
-       if (*_value && **_value) {
-               printk(KERN_NOTICE "kAFS: %s: Invalid argument: %s\n",
-                      option, *_value);
-               return 0;
-       }
-       return 1;
-}
-
-/*
  * parse the mount options
  * - this function has been shamelessly adapted from the ext3 fs which
  *   shamelessly adapted it from the msdos fs
@@ -148,48 +138,46 @@ static int afs_parse_options(struct afs_mount_params *params,
                             char *options, const char **devname)
 {
        struct afs_cell *cell;
-       char *key, *value;
-       int ret;
+       substring_t args[MAX_OPT_ARGS];
+       char *p;
+       int token;
 
        _enter("%s", options);
 
        options[PAGE_SIZE - 1] = 0;
 
-       ret = 0;
-       while ((key = strsep(&options, ","))) {
-               value = strchr(key, '=');
-               if (value)
-                       *value++ = 0;
-
-               _debug("kAFS: KEY: %s, VAL:%s", key, value ?: "-");
+       while ((p = strsep(&options, ","))) {
+               if (!*p)
+                       continue;
 
-               if (strcmp(key, "rwpath") == 0) {
-                       if (!want_no_value(&value, "rwpath"))
-                               return -EINVAL;
-                       params->rwpath = 1;
-               } else if (strcmp(key, "vol") == 0) {
-                       if (!want_arg(&value, "vol"))
-                               return -EINVAL;
-                       *devname = value;
-               } else if (strcmp(key, "cell") == 0) {
-                       if (!want_arg(&value, "cell"))
-                               return -EINVAL;
-                       cell = afs_cell_lookup(value, strlen(value));
+               token = match_token(p, afs_options_list, args);
+               switch (token) {
+               case afs_opt_cell:
+                       cell = afs_cell_lookup(args[0].from,
+                                              args[0].to - args[0].from);
                        if (IS_ERR(cell))
                                return PTR_ERR(cell);
                        afs_put_cell(params->cell);
                        params->cell = cell;
-               } else {
-                       printk("kAFS: Unknown mount option: '%s'\n",  key);
-                       ret = -EINVAL;
-                       goto error;
+                       break;
+
+               case afs_opt_rwpath:
+                       params->rwpath = 1;
+                       break;
+
+               case afs_opt_vol:
+                       *devname = args[0].from;
+                       break;
+
+               default:
+                       printk(KERN_ERR "kAFS:"
+                              " Unknown or invalid mount option: '%s'\n", p);
+                       return -EINVAL;
                }
        }
 
-       ret = 0;
-error:
-       _leave(" = %d", ret);
-       return ret;
+       _leave(" = 0");
+       return 0;
 }
 
 /*
@@ -361,7 +349,6 @@ error:
 
 /*
  * get an AFS superblock
- * - TODO: don't use get_sb_nodev(), but rather call sget() directly
  */
 static int afs_get_sb(struct file_system_type *fs_type,
                      int flags,
@@ -386,7 +373,6 @@ static int afs_get_sb(struct file_system_type *fs_type,
                        goto error;
        }
 
-
        ret = afs_parse_device_name(&params, dev_name);
        if (ret < 0)
                goto error;
diff --git a/fs/afs/use-rtnetlink.c b/fs/afs/use-rtnetlink.c
deleted file mode 100644 (file)
index f8991c7..0000000
+++ /dev/null
@@ -1,473 +0,0 @@
-/* RTNETLINK client
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <linux/if_addr.h>
-#include <linux/if_arp.h>
-#include <linux/inetdevice.h>
-#include <net/netlink.h>
-#include "internal.h"
-
-struct afs_rtm_desc {
-       struct socket           *nlsock;
-       struct afs_interface    *bufs;
-       u8                      *mac;
-       size_t                  nbufs;
-       size_t                  maxbufs;
-       void                    *data;
-       ssize_t                 datalen;
-       size_t                  datamax;
-       int                     msg_seq;
-       unsigned                mac_index;
-       bool                    wantloopback;
-       int (*parse)(struct afs_rtm_desc *, struct nlmsghdr *);
-};
-
-/*
- * parse an RTM_GETADDR response
- */
-static int afs_rtm_getaddr_parse(struct afs_rtm_desc *desc,
-                                struct nlmsghdr *nlhdr)
-{
-       struct afs_interface *this;
-       struct ifaddrmsg *ifa;
-       struct rtattr *rtattr;
-       const char *name;
-       size_t len;
-
-       ifa = (struct ifaddrmsg *) NLMSG_DATA(nlhdr);
-
-       _enter("{ix=%d,af=%d}", ifa->ifa_index, ifa->ifa_family);
-
-       if (ifa->ifa_family != AF_INET) {
-               _leave(" = 0 [family %d]", ifa->ifa_family);
-               return 0;
-       }
-       if (desc->nbufs >= desc->maxbufs) {
-               _leave(" = 0 [max %zu/%zu]", desc->nbufs, desc->maxbufs);
-               return 0;
-       }
-
-       this = &desc->bufs[desc->nbufs];
-
-       this->index = ifa->ifa_index;
-       this->netmask.s_addr = inet_make_mask(ifa->ifa_prefixlen);
-       this->mtu = 0;
-
-       rtattr = NLMSG_DATA(nlhdr) + NLMSG_ALIGN(sizeof(struct ifaddrmsg));
-       len = NLMSG_PAYLOAD(nlhdr, sizeof(struct ifaddrmsg));
-
-       name = "unknown";
-       for (; RTA_OK(rtattr, len); rtattr = RTA_NEXT(rtattr, len)) {
-               switch (rtattr->rta_type) {
-               case IFA_ADDRESS:
-                       memcpy(&this->address, RTA_DATA(rtattr), 4);
-                       break;
-               case IFA_LABEL:
-                       name = RTA_DATA(rtattr);
-                       break;
-               }
-       }
-
-       _debug("%s: "NIPQUAD_FMT"/"NIPQUAD_FMT,
-              name, NIPQUAD(this->address), NIPQUAD(this->netmask));
-
-       desc->nbufs++;
-       _leave(" = 0");
-       return 0;
-}
-
-/*
- * parse an RTM_GETLINK response for MTUs
- */
-static int afs_rtm_getlink_if_parse(struct afs_rtm_desc *desc,
-                                   struct nlmsghdr *nlhdr)
-{
-       struct afs_interface *this;
-       struct ifinfomsg *ifi;
-       struct rtattr *rtattr;
-       const char *name;
-       size_t len, loop;
-
-       ifi = (struct ifinfomsg *) NLMSG_DATA(nlhdr);
-
-       _enter("{ix=%d}", ifi->ifi_index);
-
-       for (loop = 0; loop < desc->nbufs; loop++) {
-               this = &desc->bufs[loop];
-               if (this->index == ifi->ifi_index)
-                       goto found;
-       }
-
-       _leave(" = 0 [no match]");
-       return 0;
-
-found:
-       if (ifi->ifi_type == ARPHRD_LOOPBACK && !desc->wantloopback) {
-               _leave(" = 0 [loopback]");
-               return 0;
-       }
-
-       rtattr = NLMSG_DATA(nlhdr) + NLMSG_ALIGN(sizeof(struct ifinfomsg));
-       len = NLMSG_PAYLOAD(nlhdr, sizeof(struct ifinfomsg));
-
-       name = "unknown";
-       for (; RTA_OK(rtattr, len); rtattr = RTA_NEXT(rtattr, len)) {
-               switch (rtattr->rta_type) {
-               case IFLA_MTU:
-                       memcpy(&this->mtu, RTA_DATA(rtattr), 4);
-                       break;
-               case IFLA_IFNAME:
-                       name = RTA_DATA(rtattr);
-                       break;
-               }
-       }
-
-       _debug("%s: "NIPQUAD_FMT"/"NIPQUAD_FMT" mtu %u",
-              name, NIPQUAD(this->address), NIPQUAD(this->netmask),
-              this->mtu);
-
-       _leave(" = 0");
-       return 0;
-}
-
-/*
- * parse an RTM_GETLINK response for the MAC address belonging to the lowest
- * non-internal interface
- */
-static int afs_rtm_getlink_mac_parse(struct afs_rtm_desc *desc,
-                                    struct nlmsghdr *nlhdr)
-{
-       struct ifinfomsg *ifi;
-       struct rtattr *rtattr;
-       const char *name;
-       size_t remain, len;
-       bool set;
-
-       ifi = (struct ifinfomsg *) NLMSG_DATA(nlhdr);
-
-       _enter("{ix=%d}", ifi->ifi_index);
-
-       if (ifi->ifi_index >= desc->mac_index) {
-               _leave(" = 0 [high]");
-               return 0;
-       }
-       if (ifi->ifi_type == ARPHRD_LOOPBACK) {
-               _leave(" = 0 [loopback]");
-               return 0;
-       }
-
-       rtattr = NLMSG_DATA(nlhdr) + NLMSG_ALIGN(sizeof(struct ifinfomsg));
-       remain = NLMSG_PAYLOAD(nlhdr, sizeof(struct ifinfomsg));
-
-       name = "unknown";
-       set = false;
-       for (; RTA_OK(rtattr, remain); rtattr = RTA_NEXT(rtattr, remain)) {
-               switch (rtattr->rta_type) {
-               case IFLA_ADDRESS:
-                       len = RTA_PAYLOAD(rtattr);
-                       memcpy(desc->mac, RTA_DATA(rtattr),
-                              min_t(size_t, len, 6));
-                       desc->mac_index = ifi->ifi_index;
-                       set = true;
-                       break;
-               case IFLA_IFNAME:
-                       name = RTA_DATA(rtattr);
-                       break;
-               }
-       }
-
-       if (set)
-               _debug("%s: %02x:%02x:%02x:%02x:%02x:%02x",
-                      name,
-                      desc->mac[0], desc->mac[1], desc->mac[2],
-                      desc->mac[3], desc->mac[4], desc->mac[5]);
-
-       _leave(" = 0");
-       return 0;
-}
-
-/*
- * read the rtnetlink response and pass to parsing routine
- */
-static int afs_read_rtm(struct afs_rtm_desc *desc)
-{
-       struct nlmsghdr *nlhdr, tmphdr;
-       struct msghdr msg;
-       struct kvec iov[1];
-       void *data;
-       bool last = false;
-       int len, ret, remain;
-
-       _enter("");
-
-       do {
-               /* first of all peek to see how big the packet is */
-               memset(&msg, 0, sizeof(msg));
-               iov[0].iov_base = &tmphdr;
-               iov[0].iov_len = sizeof(tmphdr);
-               len = kernel_recvmsg(desc->nlsock, &msg, iov, 1,
-                                    sizeof(tmphdr), MSG_PEEK | MSG_TRUNC);
-               if (len < 0) {
-                       _leave(" = %d [peek]", len);
-                       return len;
-               }
-               if (len == 0)
-                       continue;
-               if (len < sizeof(tmphdr) || len < NLMSG_PAYLOAD(&tmphdr, 0)) {
-                       _leave(" = -EMSGSIZE");
-                       return -EMSGSIZE;
-               }
-
-               if (desc->datamax < len) {
-                       kfree(desc->data);
-                       desc->data = NULL;
-                       data = kmalloc(len, GFP_KERNEL);
-                       if (!data)
-                               return -ENOMEM;
-                       desc->data = data;
-               }
-               desc->datamax = len;
-
-               /* read all the data from this packet */
-               iov[0].iov_base = desc->data;
-               iov[0].iov_len = desc->datamax;
-               desc->datalen = kernel_recvmsg(desc->nlsock, &msg, iov, 1,
-                                              desc->datamax, 0);
-               if (desc->datalen < 0) {
-                       _leave(" = %zd [recv]", desc->datalen);
-                       return desc->datalen;
-               }
-
-               nlhdr = desc->data;
-
-               /* check if the header is valid */
-               if (!NLMSG_OK(nlhdr, desc->datalen) ||
-                   nlhdr->nlmsg_type == NLMSG_ERROR) {
-                       _leave(" = -EIO");
-                       return -EIO;
-               }
-
-               /* see if this is the last message */
-               if (nlhdr->nlmsg_type == NLMSG_DONE ||
-                   !(nlhdr->nlmsg_flags & NLM_F_MULTI))
-                       last = true;
-
-               /* parse the bits we got this time */
-               nlmsg_for_each_msg(nlhdr, desc->data, desc->datalen, remain) {
-                       ret = desc->parse(desc, nlhdr);
-                       if (ret < 0) {
-                               _leave(" = %d [parse]", ret);
-                               return ret;
-                       }
-               }
-
-       } while (!last);
-
-       _leave(" = 0");
-       return 0;
-}
-
-/*
- * list the interface bound addresses to get the address and netmask
- */
-static int afs_rtm_getaddr(struct afs_rtm_desc *desc)
-{
-       struct msghdr msg;
-       struct kvec iov[1];
-       int ret;
-
-       struct {
-               struct nlmsghdr nl_msg __attribute__((aligned(NLMSG_ALIGNTO)));
-               struct ifaddrmsg addr_msg __attribute__((aligned(NLMSG_ALIGNTO)));
-       } request;
-
-       _enter("");
-
-       memset(&request, 0, sizeof(request));
-
-       request.nl_msg.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
-       request.nl_msg.nlmsg_type = RTM_GETADDR;
-       request.nl_msg.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
-       request.nl_msg.nlmsg_seq = desc->msg_seq++;
-       request.nl_msg.nlmsg_pid = 0;
-
-       memset(&msg, 0, sizeof(msg));
-       iov[0].iov_base = &request;
-       iov[0].iov_len = sizeof(request);
-
-       ret = kernel_sendmsg(desc->nlsock, &msg, iov, 1, iov[0].iov_len);
-       _leave(" = %d", ret);
-       return ret;
-}
-
-/*
- * list the interface link statuses to get the MTUs
- */
-static int afs_rtm_getlink(struct afs_rtm_desc *desc)
-{
-       struct msghdr msg;
-       struct kvec iov[1];
-       int ret;
-
-       struct {
-               struct nlmsghdr nl_msg __attribute__((aligned(NLMSG_ALIGNTO)));
-               struct ifinfomsg link_msg __attribute__((aligned(NLMSG_ALIGNTO)));
-       } request;
-
-       _enter("");
-
-       memset(&request, 0, sizeof(request));
-
-       request.nl_msg.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
-       request.nl_msg.nlmsg_type = RTM_GETLINK;
-       request.nl_msg.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
-       request.nl_msg.nlmsg_seq = desc->msg_seq++;
-       request.nl_msg.nlmsg_pid = 0;
-
-       memset(&msg, 0, sizeof(msg));
-       iov[0].iov_base = &request;
-       iov[0].iov_len = sizeof(request);
-
-       ret = kernel_sendmsg(desc->nlsock, &msg, iov, 1, iov[0].iov_len);
-       _leave(" = %d", ret);
-       return ret;
-}
-
-/*
- * cull any interface records for which there isn't an MTU value
- */
-static void afs_cull_interfaces(struct afs_rtm_desc *desc)
-{
-       struct afs_interface *bufs = desc->bufs;
-       size_t nbufs = desc->nbufs;
-       int loop, point = 0;
-
-       _enter("{%zu}", nbufs);
-
-       for (loop = 0; loop < nbufs; loop++) {
-               if (desc->bufs[loop].mtu != 0) {
-                       if (loop != point) {
-                               ASSERTCMP(loop, >, point);
-                               bufs[point] = bufs[loop];
-                       }
-                       point++;
-               }
-       }
-
-       desc->nbufs = point;
-       _leave(" [%zu/%zu]", desc->nbufs, nbufs);
-}
-
-/*
- * get a list of this system's interface IPv4 addresses, netmasks and MTUs
- * - returns the number of interface records in the buffer
- */
-int afs_get_ipv4_interfaces(struct afs_interface *bufs, size_t maxbufs,
-                           bool wantloopback)
-{
-       struct afs_rtm_desc desc;
-       int ret, loop;
-
-       _enter("");
-
-       memset(&desc, 0, sizeof(desc));
-       desc.bufs = bufs;
-       desc.maxbufs = maxbufs;
-       desc.wantloopback = wantloopback;
-
-       ret = sock_create_kern(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE,
-                              &desc.nlsock);
-       if (ret < 0) {
-               _leave(" = %d [sock]", ret);
-               return ret;
-       }
-
-       /* issue RTM_GETADDR */
-       desc.parse = afs_rtm_getaddr_parse;
-       ret = afs_rtm_getaddr(&desc);
-       if (ret < 0)
-               goto error;
-       ret = afs_read_rtm(&desc);
-       if (ret < 0)
-               goto error;
-
-       /* issue RTM_GETLINK */
-       desc.parse = afs_rtm_getlink_if_parse;
-       ret = afs_rtm_getlink(&desc);
-       if (ret < 0)
-               goto error;
-       ret = afs_read_rtm(&desc);
-       if (ret < 0)
-               goto error;
-
-       afs_cull_interfaces(&desc);
-       ret = desc.nbufs;
-
-       for (loop = 0; loop < ret; loop++)
-               _debug("[%d] "NIPQUAD_FMT"/"NIPQUAD_FMT" mtu %u",
-                      bufs[loop].index,
-                      NIPQUAD(bufs[loop].address),
-                      NIPQUAD(bufs[loop].netmask),
-                      bufs[loop].mtu);
-
-error:
-       kfree(desc.data);
-       sock_release(desc.nlsock);
-       _leave(" = %d", ret);
-       return ret;
-}
-
-/*
- * get a MAC address from a random ethernet interface that has a real one
- * - the buffer should be 6 bytes in size
- */
-int afs_get_MAC_address(u8 mac[6])
-{
-       struct afs_rtm_desc desc;
-       int ret;
-
-       _enter("");
-
-       memset(&desc, 0, sizeof(desc));
-       desc.mac = mac;
-       desc.mac_index = UINT_MAX;
-
-       ret = sock_create_kern(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE,
-                              &desc.nlsock);
-       if (ret < 0) {
-               _leave(" = %d [sock]", ret);
-               return ret;
-       }
-
-       /* issue RTM_GETLINK */
-       desc.parse = afs_rtm_getlink_mac_parse;
-       ret = afs_rtm_getlink(&desc);
-       if (ret < 0)
-               goto error;
-       ret = afs_read_rtm(&desc);
-       if (ret < 0)
-               goto error;
-
-       if (desc.mac_index < UINT_MAX) {
-               /* got a MAC address */
-               _debug("[%d] %02x:%02x:%02x:%02x:%02x:%02x",
-                      desc.mac_index,
-                      mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
-       } else {
-               ret = -ENONET;
-       }
-
-error:
-       sock_release(desc.nlsock);
-       _leave(" = %d", ret);
-       return ret;
-}
index 6c8e95a..3370cdb 100644 (file)
@@ -602,7 +602,7 @@ int __init afs_vlocation_update_init(void)
 /*
  * discard all the volume location records for rmmod
  */
-void __exit afs_vlocation_purge(void)
+void afs_vlocation_purge(void)
 {
        afs_vlocation_timeout = 0;
 
index 6f57300..b00d962 100644 (file)
@@ -140,7 +140,7 @@ static int __init configfs_init(void)
        if (!configfs_dir_cachep)
                goto out;
 
-       kset_set_kset_s(&config_subsys, kernel_subsys);
+       kobj_set_kset_s(&config_subsys, kernel_subsys);
        err = subsystem_register(&config_subsys);
        if (err) {
                kmem_cache_destroy(configfs_dir_cachep);
index 7b324cf..ec8896b 100644 (file)
@@ -374,7 +374,7 @@ static int __init debugfs_init(void)
 {
        int retval;
 
-       kset_set_kset_s(&debug_subsys, kernel_subsys);
+       kobj_set_kset_s(&debug_subsys, kernel_subsys);
        retval = subsystem_register(&debug_subsys);
        if (retval)
                return retval;
index f40817b..8e6ad76 100644 (file)
@@ -167,7 +167,6 @@ static struct kobj_type dlm_ktype = {
 };
 
 static struct kset dlm_kset = {
-       .subsys = &kernel_subsys,
        .kobj   = {.name = "dlm",},
        .ktype  = &dlm_ktype,
 };
@@ -218,6 +217,7 @@ int dlm_lockspace_init(void)
        INIT_LIST_HEAD(&lslist);
        spin_lock_init(&lslist_lock);
 
+       kobj_set_kset_s(&dlm_kset, kernel_subsys);
        error = kset_register(&dlm_kset);
        if (error)
                printk("dlm_lockspace_init: cannot register kset %d\n", error);
index fc4a3a2..6acc8f4 100644 (file)
@@ -793,7 +793,7 @@ static int do_sysfs_registration(void)
                       "Unable to register ecryptfs sysfs subsystem\n");
                goto out;
        }
-       rc = sysfs_create_file(&ecryptfs_subsys.kset.kobj,
+       rc = sysfs_create_file(&ecryptfs_subsys.kobj,
                               &sysfs_attr_version.attr);
        if (rc) {
                printk(KERN_ERR
@@ -801,12 +801,12 @@ static int do_sysfs_registration(void)
                subsystem_unregister(&ecryptfs_subsys);
                goto out;
        }
-       rc = sysfs_create_file(&ecryptfs_subsys.kset.kobj,
+       rc = sysfs_create_file(&ecryptfs_subsys.kobj,
                               &sysfs_attr_version_str.attr);
        if (rc) {
                printk(KERN_ERR
                       "Unable to create ecryptfs version_str attribute\n");
-               sysfs_remove_file(&ecryptfs_subsys.kset.kobj,
+               sysfs_remove_file(&ecryptfs_subsys.kobj,
                                  &sysfs_attr_version.attr);
                subsystem_unregister(&ecryptfs_subsys);
                goto out;
@@ -841,7 +841,7 @@ static int __init ecryptfs_init(void)
                ecryptfs_free_kmem_caches();
                goto out;
        }
-       kset_set_kset_s(&ecryptfs_subsys, fs_subsys);
+       kobj_set_kset_s(&ecryptfs_subsys, fs_subsys);
        sysfs_attr_version.attr.owner = THIS_MODULE;
        sysfs_attr_version_str.attr.owner = THIS_MODULE;
        rc = do_sysfs_registration();
@@ -862,9 +862,9 @@ out:
 
 static void __exit ecryptfs_exit(void)
 {
-       sysfs_remove_file(&ecryptfs_subsys.kset.kobj,
+       sysfs_remove_file(&ecryptfs_subsys.kobj,
                          &sysfs_attr_version.attr);
-       sysfs_remove_file(&ecryptfs_subsys.kset.kobj,
+       sysfs_remove_file(&ecryptfs_subsys.kobj,
                          &sysfs_attr_version_str.attr);
        subsystem_unregister(&ecryptfs_subsys);
        ecryptfs_release_messaging(ecryptfs_transport);
index 608db81..bdffe0c 100644 (file)
@@ -731,12 +731,12 @@ static int fuse_sysfs_init(void)
 {
        int err;
 
-       kset_set_kset_s(&fuse_subsys, fs_subsys);
+       kobj_set_kset_s(&fuse_subsys, fs_subsys);
        err = subsystem_register(&fuse_subsys);
        if (err)
                goto out_err;
 
-       kset_set_kset_s(&connections_subsys, fuse_subsys);
+       kobj_set_kset_s(&connections_subsys, fuse_subsys);
        err = subsystem_register(&connections_subsys);
        if (err)
                goto out_fuse_unregister;
index 4746b88..d9fe3ca 100644 (file)
@@ -190,7 +190,6 @@ static struct kobj_type gdlm_ktype = {
 };
 
 static struct kset gdlm_kset = {
-       .subsys = &kernel_subsys,
        .kobj   = {.name = "lock_dlm",},
        .ktype  = &gdlm_ktype,
 };
@@ -225,6 +224,7 @@ int gdlm_sysfs_init(void)
 {
        int error;
 
+       kobj_set_kset_s(&gdlm_kset, kernel_subsys);
        error = kset_register(&gdlm_kset);
        if (error)
                printk("lock_dlm: cannot register kset %d\n", error);
index d01f9f0..c26c21b 100644 (file)
@@ -222,7 +222,6 @@ static struct kobj_type gfs2_ktype = {
 };
 
 static struct kset gfs2_kset = {
-       .subsys = &fs_subsys,
        .kobj   = {.name = "gfs2"},
        .ktype  = &gfs2_ktype,
 };
@@ -554,6 +553,7 @@ int gfs2_sys_init(void)
 {
        gfs2_sys_margs = NULL;
        spin_lock_init(&gfs2_sys_margs_lock);
+       kobj_set_kset_s(&gfs2_kset, fs_subsys);
        return kset_register(&gfs2_kset);
 }
 
index eb243ed..2102e2d 100644 (file)
@@ -225,16 +225,13 @@ xdr_decode_stat(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp)
 #define SM_monres_sz   2
 #define SM_unmonres_sz 1
 
-#ifndef MAX
-# define MAX(a, b)     (((a) > (b))? (a) : (b))
-#endif
-
 static struct rpc_procinfo     nsm_procedures[] = {
 [SM_MON] = {
                .p_proc         = SM_MON,
                .p_encode       = (kxdrproc_t) xdr_encode_mon,
                .p_decode       = (kxdrproc_t) xdr_decode_stat_res,
-               .p_bufsiz       = MAX(SM_mon_sz, SM_monres_sz) << 2,
+               .p_arglen       = SM_mon_sz,
+               .p_replen       = SM_monres_sz,
                .p_statidx      = SM_MON,
                .p_name         = "MONITOR",
        },
@@ -242,7 +239,8 @@ static struct rpc_procinfo  nsm_procedures[] = {
                .p_proc         = SM_UNMON,
                .p_encode       = (kxdrproc_t) xdr_encode_unmon,
                .p_decode       = (kxdrproc_t) xdr_decode_stat,
-               .p_bufsiz       = MAX(SM_mon_id_sz, SM_unmonres_sz) << 2,
+               .p_arglen       = SM_mon_id_sz,
+               .p_replen       = SM_unmonres_sz,
                .p_statidx      = SM_UNMON,
                .p_name         = "UNMONITOR",
        },
index 34dae5d..9702956 100644 (file)
@@ -510,17 +510,20 @@ nlmclt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
        return 0;
 }
 
+#if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ)
+#  error "NLM host name cannot be larger than XDR_MAX_NETOBJ!"
+#endif
+
 /*
  * Buffer requirements for NLM
  */
 #define NLM_void_sz            0
 #define NLM_cookie_sz          1+XDR_QUADLEN(NLM_MAXCOOKIELEN)
-#define NLM_caller_sz          1+XDR_QUADLEN(sizeof(utsname()->nodename))
-#define NLM_netobj_sz          1+XDR_QUADLEN(XDR_MAX_NETOBJ)
-/* #define NLM_owner_sz                1+XDR_QUADLEN(NLM_MAXOWNER) */
+#define NLM_caller_sz          1+XDR_QUADLEN(NLMCLNT_OHSIZE)
+#define NLM_owner_sz           1+XDR_QUADLEN(NLMCLNT_OHSIZE)
 #define NLM_fhandle_sz         1+XDR_QUADLEN(NFS2_FHSIZE)
-#define NLM_lock_sz            3+NLM_caller_sz+NLM_netobj_sz+NLM_fhandle_sz
-#define NLM_holder_sz          4+NLM_netobj_sz
+#define NLM_lock_sz            3+NLM_caller_sz+NLM_owner_sz+NLM_fhandle_sz
+#define NLM_holder_sz          4+NLM_owner_sz
 
 #define NLM_testargs_sz                NLM_cookie_sz+1+NLM_lock_sz
 #define NLM_lockargs_sz                NLM_cookie_sz+4+NLM_lock_sz
@@ -531,10 +534,6 @@ nlmclt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
 #define NLM_res_sz             NLM_cookie_sz+1
 #define NLM_norep_sz           0
 
-#ifndef MAX
-# define MAX(a, b)             (((a) > (b))? (a) : (b))
-#endif
-
 /*
  * For NLM, a void procedure really returns nothing
  */
@@ -545,7 +544,8 @@ nlmclt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
        .p_proc      = NLMPROC_##proc,                                  \
        .p_encode    = (kxdrproc_t) nlmclt_encode_##argtype,            \
        .p_decode    = (kxdrproc_t) nlmclt_decode_##restype,            \
-       .p_bufsiz    = MAX(NLM_##argtype##_sz, NLM_##restype##_sz) << 2,        \
+       .p_arglen    = NLM_##argtype##_sz,                              \
+       .p_replen    = NLM_##restype##_sz,                              \
        .p_statidx   = NLMPROC_##proc,                                  \
        .p_name      = #proc,                                           \
        }
index a782405..ce1efdb 100644 (file)
@@ -516,17 +516,24 @@ nlm4clt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
        return 0;
 }
 
+#if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ)
+#  error "NLM host name cannot be larger than XDR_MAX_NETOBJ!"
+#endif
+
+#if (NLMCLNT_OHSIZE > NLM_MAXSTRLEN)
+#  error "NLM host name cannot be larger than NLM's maximum string length!"
+#endif
+
 /*
  * Buffer requirements for NLM
  */
 #define NLM4_void_sz           0
 #define NLM4_cookie_sz         1+XDR_QUADLEN(NLM_MAXCOOKIELEN)
-#define NLM4_caller_sz         1+XDR_QUADLEN(NLM_MAXSTRLEN)
-#define NLM4_netobj_sz         1+XDR_QUADLEN(XDR_MAX_NETOBJ)
-/* #define NLM4_owner_sz               1+XDR_QUADLEN(NLM4_MAXOWNER) */
+#define NLM4_caller_sz         1+XDR_QUADLEN(NLMCLNT_OHSIZE)
+#define NLM4_owner_sz          1+XDR_QUADLEN(NLMCLNT_OHSIZE)
 #define NLM4_fhandle_sz                1+XDR_QUADLEN(NFS3_FHSIZE)
-#define NLM4_lock_sz           5+NLM4_caller_sz+NLM4_netobj_sz+NLM4_fhandle_sz
-#define NLM4_holder_sz         6+NLM4_netobj_sz
+#define NLM4_lock_sz           5+NLM4_caller_sz+NLM4_owner_sz+NLM4_fhandle_sz
+#define NLM4_holder_sz         6+NLM4_owner_sz
 
 #define NLM4_testargs_sz       NLM4_cookie_sz+1+NLM4_lock_sz
 #define NLM4_lockargs_sz       NLM4_cookie_sz+4+NLM4_lock_sz
@@ -537,10 +544,6 @@ nlm4clt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
 #define NLM4_res_sz            NLM4_cookie_sz+1
 #define NLM4_norep_sz          0
 
-#ifndef MAX
-# define MAX(a,b)              (((a) > (b))? (a) : (b))
-#endif
-
 /*
  * For NLM, a void procedure really returns nothing
  */
@@ -551,7 +554,8 @@ nlm4clt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp)
        .p_proc      = NLMPROC_##proc,                                  \
        .p_encode    = (kxdrproc_t) nlm4clt_encode_##argtype,           \
        .p_decode    = (kxdrproc_t) nlm4clt_decode_##restype,           \
-       .p_bufsiz    = MAX(NLM4_##argtype##_sz, NLM4_##restype##_sz) << 2,      \
+       .p_arglen    = NLM4_##argtype##_sz,                             \
+       .p_replen    = NLM4_##restype##_sz,                             \
        .p_statidx   = NLMPROC_##proc,                                  \
        .p_name      = #proc,                                           \
        }
index 2190e6c..5bd03b9 100644 (file)
@@ -618,7 +618,8 @@ static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_dat
        if (clp->cl_nfsversion == 3) {
                if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
                        server->namelen = NFS3_MAXNAMLEN;
-               server->caps |= NFS_CAP_READDIRPLUS;
+               if (!(data->flags & NFS_MOUNT_NORDIRPLUS))
+                       server->caps |= NFS_CAP_READDIRPLUS;
        } else {
                if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)
                        server->namelen = NFS2_MAXNAMLEN;
index cd34697..e59fd31 100644 (file)
@@ -154,6 +154,8 @@ typedef struct {
        decode_dirent_t decode;
        int             plus;
        int             error;
+       unsigned long   timestamp;
+       int             timestamp_valid;
 } nfs_readdir_descriptor_t;
 
 /* Now we cache directories properly, by stuffing the dirent
@@ -195,6 +197,8 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
                }
                goto error;
        }
+       desc->timestamp = timestamp;
+       desc->timestamp_valid = 1;
        SetPageUptodate(page);
        spin_lock(&inode->i_lock);
        NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME;
@@ -225,6 +229,10 @@ int dir_decode(nfs_readdir_descriptor_t *desc)
        if (IS_ERR(p))
                return PTR_ERR(p);
        desc->ptr = p;
+       if (desc->timestamp_valid)
+               desc->entry->fattr->time_start = desc->timestamp;
+       else
+               desc->entry->fattr->valid &= ~NFS_ATTR_FATTR;
        return 0;
 }
 
@@ -316,6 +324,10 @@ int find_dirent_page(nfs_readdir_descriptor_t *desc)
                        __FUNCTION__, desc->page_index,
                        (long long) *desc->dir_cookie);
 
+       /* If we find the page in the page_cache, we cannot be sure
+        * how fresh the data is, so we will ignore readdir_plus attributes.
+        */
+       desc->timestamp_valid = 0;
        page = read_cache_page(inode->i_mapping, desc->page_index,
                               (filler_t *)nfs_readdir_filler, desc);
        if (IS_ERR(page)) {
@@ -468,6 +480,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
        struct rpc_cred *cred = nfs_file_cred(file);
        struct page     *page = NULL;
        int             status;
+       unsigned long   timestamp;
 
        dfprintk(DIRCACHE, "NFS: uncached_readdir() searching for cookie %Lu\n",
                        (unsigned long long)*desc->dir_cookie);
@@ -477,6 +490,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
                status = -ENOMEM;
                goto out;
        }
+       timestamp = jiffies;
        desc->error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, *desc->dir_cookie,
                                                page,
                                                NFS_SERVER(inode)->dtsize,
@@ -487,6 +501,8 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
        desc->page = page;
        desc->ptr = kmap(page);         /* matching kunmap in nfs_do_filldir */
        if (desc->error >= 0) {
+               desc->timestamp = timestamp;
+               desc->timestamp_valid = 1;
                if ((status = dir_decode(desc)) == 0)
                        desc->entry->prev_cookie = *desc->dir_cookie;
        } else
@@ -849,6 +865,10 @@ static int nfs_dentry_delete(struct dentry *dentry)
 static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
 {
        nfs_inode_return_delegation(inode);
+       if (S_ISDIR(inode->i_mode))
+               /* drop any readdir cache as it could easily be old */
+               NFS_I(inode)->cache_validity |= NFS_INO_INVALID_DATA;
+
        if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
                lock_kernel();
                drop_nlink(inode);
index 2877744..889de60 100644 (file)
@@ -54,6 +54,7 @@
 #include <asm/uaccess.h>
 #include <asm/atomic.h>
 
+#include "internal.h"
 #include "iostat.h"
 
 #define NFSDBG_FACILITY                NFSDBG_VFS
@@ -271,7 +272,7 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo
                bytes = min(rsize,count);
 
                result = -ENOMEM;
-               data = nfs_readdata_alloc(pgbase + bytes);
+               data = nfs_readdata_alloc(nfs_page_array_len(pgbase, bytes));
                if (unlikely(!data))
                        break;
 
@@ -602,7 +603,7 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l
                bytes = min(wsize,count);
 
                result = -ENOMEM;
-               data = nfs_writedata_alloc(pgbase + bytes);
+               data = nfs_writedata_alloc(nfs_page_array_len(pgbase, bytes));
                if (unlikely(!data))
                        break;
 
index 6610f2b..ad2b40d 100644 (file)
@@ -231,3 +231,15 @@ unsigned int nfs_page_length(struct page *page)
        }
        return 0;
 }
+
+/*
+ * Determine the number of pages in an array of length 'len' and
+ * with a base offset of 'base'
+ */
+static inline
+unsigned int nfs_page_array_len(unsigned int base, size_t len)
+{
+       return ((unsigned long)len + (unsigned long)base +
+               PAGE_SIZE - 1) >> PAGE_SHIFT;
+}
+
index f75fe72..ca5a266 100644 (file)
@@ -133,13 +133,15 @@ xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p, struct mnt_fhstatus *res)
 
 #define MNT_dirpath_sz         (1 + 256)
 #define MNT_fhstatus_sz                (1 + 8)
+#define MNT_fhstatus3_sz       (1 + 16)
 
 static struct rpc_procinfo     mnt_procedures[] = {
 [MNTPROC_MNT] = {
          .p_proc               = MNTPROC_MNT,
          .p_encode             = (kxdrproc_t) xdr_encode_dirpath,      
          .p_decode             = (kxdrproc_t) xdr_decode_fhstatus,
-         .p_bufsiz             = MNT_dirpath_sz << 2,
+         .p_arglen             = MNT_dirpath_sz,
+         .p_replen             = MNT_fhstatus_sz,
          .p_statidx            = MNTPROC_MNT,
          .p_name               = "MOUNT",
        },
@@ -150,7 +152,8 @@ static struct rpc_procinfo mnt3_procedures[] = {
          .p_proc               = MOUNTPROC3_MNT,
          .p_encode             = (kxdrproc_t) xdr_encode_dirpath,
          .p_decode             = (kxdrproc_t) xdr_decode_fhstatus3,
-         .p_bufsiz             = MNT_dirpath_sz << 2,
+         .p_arglen             = MNT_dirpath_sz,
+         .p_replen             = MNT_fhstatus3_sz,
          .p_statidx            = MOUNTPROC3_MNT,
          .p_name               = "MOUNT",
        },
index 3be4e72..abd9f8b 100644 (file)
@@ -687,16 +687,13 @@ nfs_stat_to_errno(int stat)
        return nfs_errtbl[i].errno;
 }
 
-#ifndef MAX
-# define MAX(a, b)     (((a) > (b))? (a) : (b))
-#endif
-
 #define PROC(proc, argtype, restype, timer)                            \
 [NFSPROC_##proc] = {                                                   \
        .p_proc     =  NFSPROC_##proc,                                  \
        .p_encode   =  (kxdrproc_t) nfs_xdr_##argtype,                  \
        .p_decode   =  (kxdrproc_t) nfs_xdr_##restype,                  \
-       .p_bufsiz   =  MAX(NFS_##argtype##_sz,NFS_##restype##_sz) << 2, \
+       .p_arglen   =  NFS_##argtype##_sz,                              \
+       .p_replen   =  NFS_##restype##_sz,                              \
        .p_timer    =  timer,                                           \
        .p_statidx  =  NFSPROC_##proc,                                  \
        .p_name     =  #proc,                                           \
index 0ace092..b51df8e 100644 (file)
@@ -1102,16 +1102,13 @@ nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
 }
 #endif  /* CONFIG_NFS_V3_ACL */
 
-#ifndef MAX
-# define MAX(a, b)     (((a) > (b))? (a) : (b))
-#endif
-
 #define PROC(proc, argtype, restype, timer)                            \
 [NFS3PROC_##proc] = {                                                  \
        .p_proc      = NFS3PROC_##proc,                                 \
        .p_encode    = (kxdrproc_t) nfs3_xdr_##argtype,                 \
        .p_decode    = (kxdrproc_t) nfs3_xdr_##restype,                 \
-       .p_bufsiz    = MAX(NFS3_##argtype##_sz,NFS3_##restype##_sz) << 2,       \
+       .p_arglen    = NFS3_##argtype##_sz,                             \
+       .p_replen    = NFS3_##restype##_sz,                             \
        .p_timer     = timer,                                           \
        .p_statidx   = NFS3PROC_##proc,                                 \
        .p_name      = #proc,                                           \
@@ -1153,7 +1150,8 @@ static struct rpc_procinfo        nfs3_acl_procedures[] = {
                .p_proc = ACLPROC3_GETACL,
                .p_encode = (kxdrproc_t) nfs3_xdr_getaclargs,
                .p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
-               .p_bufsiz = MAX(ACL3_getaclargs_sz, ACL3_getaclres_sz) << 2,
+               .p_arglen = ACL3_getaclargs_sz,
+               .p_replen = ACL3_getaclres_sz,
                .p_timer = 1,
                .p_name = "GETACL",
        },
@@ -1161,7 +1159,8 @@ static struct rpc_procinfo        nfs3_acl_procedures[] = {
                .p_proc = ACLPROC3_SETACL,
                .p_encode = (kxdrproc_t) nfs3_xdr_setaclargs,
                .p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
-               .p_bufsiz = MAX(ACL3_setaclargs_sz, ACL3_setaclres_sz) << 2,
+               .p_arglen = ACL3_setaclargs_sz,
+               .p_replen = ACL3_setaclres_sz,
                .p_timer = 0,
                .p_name = "SETACL",
        },
index f52cf5c..3b5ca1b 100644 (file)
@@ -2647,8 +2647,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
        nfs_inode_return_delegation(inode);
        buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
        ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
-       if (ret == 0)
-               nfs4_write_cached_acl(inode, buf, buflen);
+       nfs_zap_caches(inode);
        return ret;
 }
 
index f02d522..b8c28f2 100644 (file)
@@ -4546,16 +4546,13 @@ nfs4_stat_to_errno(int stat)
        return stat;
 }
 
-#ifndef MAX
-# define MAX(a, b)     (((a) > (b))? (a) : (b))
-#endif
-
 #define PROC(proc, argtype, restype)                           \
 [NFSPROC4_CLNT_##proc] = {                                     \
        .p_proc   = NFSPROC4_COMPOUND,                          \
        .p_encode = (kxdrproc_t) nfs4_xdr_##argtype,            \
        .p_decode = (kxdrproc_t) nfs4_xdr_##restype,            \
-       .p_bufsiz = MAX(NFS4_##argtype##_sz,NFS4_##restype##_sz) << 2,  \
+       .p_arglen = NFS4_##argtype##_sz,                        \
+       .p_replen = NFS4_##restype##_sz,                        \
        .p_statidx = NFSPROC4_CLNT_##proc,                      \
        .p_name   = #proc,                                      \
     }
index 75f819d..49d1008 100644 (file)
@@ -428,7 +428,7 @@ static int __init root_nfs_getport(int program, int version, int proto)
        printk(KERN_NOTICE "Looking up port of RPC %d/%d on %u.%u.%u.%u\n",
                program, version, NIPQUAD(servaddr));
        set_sockaddr(&sin, servaddr, 0);
-       return rpc_getport_external(&sin, program, version, proto);
+       return rpcb_getport_external(&sin, program, version, proto);
 }
 
 
index ca4b1d4..3889501 100644 (file)
@@ -17,7 +17,8 @@
 #include <linux/nfs_page.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_mount.h>
-#include <linux/writeback.h>
+
+#include "internal.h"
 
 #define NFS_PARANOIA 1
 
@@ -50,9 +51,7 @@ nfs_page_free(struct nfs_page *p)
  * @count: number of bytes to read/write
  *
  * The page must be locked by the caller. This makes sure we never
- * create two different requests for the same page, and avoids
- * a possible deadlock when we reach the hard limit on the number
- * of dirty pages.
+ * create two different requests for the same page.
  * User should ensure it is safe to sleep in this function.
  */
 struct nfs_page *
@@ -63,16 +62,12 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
        struct nfs_server *server = NFS_SERVER(inode);
        struct nfs_page         *req;
 
-       /* Deal with hard limits.  */
        for (;;) {
                /* try to allocate the request struct */
                req = nfs_page_alloc();
                if (req != NULL)
                        break;
 
-               /* Try to free up at least one request in order to stay
-                * below the hard limit
-                */
                if (signalled() && (server->flags & NFS_MOUNT_INTR))
                        return ERR_PTR(-ERESTARTSYS);
                yield();
@@ -223,124 +218,151 @@ out:
 }
 
 /**
- * nfs_coalesce_requests - Split coalesced requests out from a list.
- * @head: source list
- * @dst: destination list
- * @nmax: maximum number of requests to coalesce
- *
- * Moves a maximum of 'nmax' elements from one list to another.
- * The elements are checked to ensure that they form a contiguous set
- * of pages, and that the RPC credentials are the same.
+ * nfs_pageio_init - initialise a page io descriptor
+ * @desc: pointer to descriptor
+ * @inode: pointer to inode
+ * @doio: pointer to io function
+ * @bsize: io block size
+ * @io_flags: extra parameters for the io function
  */
-int
-nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
-                     unsigned int nmax)
+void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
+                    struct inode *inode,
+                    int (*doio)(struct inode *, struct list_head *, unsigned int, size_t, int),
+                    size_t bsize,
+                    int io_flags)
 {
-       struct nfs_page         *req = NULL;
-       unsigned int            npages = 0;
-
-       while (!list_empty(head)) {
-               struct nfs_page *prev = req;
-
-               req = nfs_list_entry(head->next);
-               if (prev) {
-                       if (req->wb_context->cred != prev->wb_context->cred)
-                               break;
-                       if (req->wb_context->lockowner != prev->wb_context->lockowner)
-                               break;
-                       if (req->wb_context->state != prev->wb_context->state)
-                               break;
-                       if (req->wb_index != (prev->wb_index + 1))
-                               break;
-
-                       if (req->wb_pgbase != 0)
-                               break;
-               }
-               nfs_list_remove_request(req);
-               nfs_list_add_request(req, dst);
-               npages++;
-               if (req->wb_pgbase + req->wb_bytes != PAGE_CACHE_SIZE)
-                       break;
-               if (npages >= nmax)
-                       break;
-       }
-       return npages;
+       INIT_LIST_HEAD(&desc->pg_list);
+       desc->pg_bytes_written = 0;
+       desc->pg_count = 0;
+       desc->pg_bsize = bsize;
+       desc->pg_base = 0;
+       desc->pg_inode = inode;
+       desc->pg_doio = doio;
+       desc->pg_ioflags = io_flags;
+       desc->pg_error = 0;
 }
 
-#define NFS_SCAN_MAXENTRIES 16
 /**
- * nfs_scan_dirty - Scan the radix tree for dirty requests
- * @mapping: pointer to address space
- * @wbc: writeback_control structure
- * @dst: Destination list
+ * nfs_can_coalesce_requests - test two requests for compatibility
+ * @prev: pointer to nfs_page
+ * @req: pointer to nfs_page
  *
- * Moves elements from one of the inode request lists.
- * If the number of requests is set to 0, the entire address_space
- * starting at index idx_start, is scanned.
- * The requests are *not* checked to ensure that they form a contiguous set.
- * You must be holding the inode's req_lock when calling this function
+ * The nfs_page structures 'prev' and 'req' are compared to ensure that the
+ * page data area they describe is contiguous, and that their RPC
+ * credentials, NFSv4 open state, and lockowners are the same.
+ *
+ * Return 'true' if this is the case, else return 'false'.
  */
-long nfs_scan_dirty(struct address_space *mapping,
-                       struct writeback_control *wbc,
-                       struct list_head *dst)
+static int nfs_can_coalesce_requests(struct nfs_page *prev,
+                                    struct nfs_page *req)
 {
-       struct nfs_inode *nfsi = NFS_I(mapping->host);
-       struct nfs_page *pgvec[NFS_SCAN_MAXENTRIES];
-       struct nfs_page *req;
-       pgoff_t idx_start, idx_end;
-       long res = 0;
-       int found, i;
-
-       if (nfsi->ndirty == 0)
+       if (req->wb_context->cred != prev->wb_context->cred)
                return 0;
-       if (wbc->range_cyclic) {
-               idx_start = 0;
-               idx_end = ULONG_MAX;
-       } else if (wbc->range_end == 0) {
-               idx_start = wbc->range_start >> PAGE_CACHE_SHIFT;
-               idx_end = ULONG_MAX;
-       } else {
-               idx_start = wbc->range_start >> PAGE_CACHE_SHIFT;
-               idx_end = wbc->range_end >> PAGE_CACHE_SHIFT;
-       }
+       if (req->wb_context->lockowner != prev->wb_context->lockowner)
+               return 0;
+       if (req->wb_context->state != prev->wb_context->state)
+               return 0;
+       if (req->wb_index != (prev->wb_index + 1))
+               return 0;
+       if (req->wb_pgbase != 0)
+               return 0;
+       if (prev->wb_pgbase + prev->wb_bytes != PAGE_CACHE_SIZE)
+               return 0;
+       return 1;
+}
 
-       for (;;) {
-               unsigned int toscan = NFS_SCAN_MAXENTRIES;
+/**
+ * nfs_pageio_do_add_request - Attempt to coalesce a request into a page list.
+ * @desc: destination io descriptor
+ * @req: request
+ *
+ * Returns true if the request 'req' was successfully coalesced into the
+ * existing list of pages 'desc'.
+ */
+static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc,
+                                    struct nfs_page *req)
+{
+       size_t newlen = req->wb_bytes;
 
-               found = radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree,
-                               (void **)&pgvec[0], idx_start, toscan,
-                               NFS_PAGE_TAG_DIRTY);
+       if (desc->pg_count != 0) {
+               struct nfs_page *prev;
 
-               /* Did we make progress? */
-               if (found <= 0)
-                       break;
+               /*
+                * FIXME: ideally we should be able to coalesce all requests
+                * that are not block boundary aligned, but currently this
+                * is problematic for the case of bsize < PAGE_CACHE_SIZE,
+                * since nfs_flush_multi and nfs_pagein_multi assume you
+                * can have only one struct nfs_page.
+                */
+               if (desc->pg_bsize < PAGE_SIZE)
+                       return 0;
+               newlen += desc->pg_count;
+               if (newlen > desc->pg_bsize)
+                       return 0;
+               prev = nfs_list_entry(desc->pg_list.prev);
+               if (!nfs_can_coalesce_requests(prev, req))
+                       return 0;
+       } else
+               desc->pg_base = req->wb_pgbase;
+       nfs_list_remove_request(req);
+       nfs_list_add_request(req, &desc->pg_list);
+       desc->pg_count = newlen;
+       return 1;
+}
 
-               for (i = 0; i < found; i++) {
-                       req = pgvec[i];
-                       if (!wbc->range_cyclic && req->wb_index > idx_end)
-                               goto out;
+/*
+ * Helper for nfs_pageio_add_request and nfs_pageio_complete
+ */
+static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc)
+{
+       if (!list_empty(&desc->pg_list)) {
+               int error = desc->pg_doio(desc->pg_inode,
+                                         &desc->pg_list,
+                                         nfs_page_array_len(desc->pg_base,
+                                                            desc->pg_count),
+                                         desc->pg_count,
+                                         desc->pg_ioflags);
+               if (error < 0)
+                       desc->pg_error = error;
+               else
+                       desc->pg_bytes_written += desc->pg_count;
+       }
+       if (list_empty(&desc->pg_list)) {
+               desc->pg_count = 0;
+               desc->pg_base = 0;
+       }
+}
 
-                       /* Try to lock request and mark it for writeback */
-                       if (!nfs_set_page_writeback_locked(req))
-                               goto next;
-                       radix_tree_tag_clear(&nfsi->nfs_page_tree,
-                                       req->wb_index, NFS_PAGE_TAG_DIRTY);
-                       nfsi->ndirty--;
-                       nfs_list_remove_request(req);
-                       nfs_list_add_request(req, dst);
-                       res++;
-                       if (res == LONG_MAX)
-                               goto out;
-next:
-                       idx_start = req->wb_index + 1;
-               }
+/**
+ * nfs_pageio_add_request - Attempt to coalesce a request into a page list.
+ * @desc: destination io descriptor
+ * @req: request
+ *
+ * Returns true if the request 'req' was successfully coalesced into the
+ * existing list of pages 'desc'.
+ */
+int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
+                          struct nfs_page *req)
+{
+       while (!nfs_pageio_do_add_request(desc, req)) {
+               nfs_pageio_doio(desc);
+               if (desc->pg_error < 0)
+                       return 0;
        }
-out:
-       WARN_ON ((nfsi->ndirty == 0) != list_empty(&nfsi->dirty));
-       return res;
+       return 1;
 }
 
 /**
+ * nfs_pageio_complete - Complete I/O on an nfs_pageio_descriptor
+ * @desc: pointer to io descriptor
+ */
+void nfs_pageio_complete(struct nfs_pageio_descriptor *desc)
+{
+       nfs_pageio_doio(desc);
+}
+
+#define NFS_SCAN_MAXENTRIES 16
+/**
  * nfs_scan_list - Scan a list for matching requests
  * @nfsi: NFS inode
  * @head: One of the NFS inode request lists
@@ -355,12 +377,12 @@ out:
  * You must be holding the inode's req_lock when calling this function
  */
 int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head,
-               struct list_head *dst, unsigned long idx_start,
+               struct list_head *dst, pgoff_t idx_start,
                unsigned int npages)
 {
        struct nfs_page *pgvec[NFS_SCAN_MAXENTRIES];
        struct nfs_page *req;
-       unsigned long idx_end;
+       pgoff_t idx_end;
        int found, i;
        int res;
 
index 6ab4d5a..9a55807 100644 (file)
@@ -27,7 +27,8 @@
 
 #define NFSDBG_FACILITY                NFSDBG_PAGECACHE
 
-static int nfs_pagein_one(struct list_head *, struct inode *);
+static int nfs_pagein_multi(struct inode *, struct list_head *, unsigned int, size_t, int);
+static int nfs_pagein_one(struct inode *, struct list_head *, unsigned int, size_t, int);
 static const struct rpc_call_ops nfs_read_partial_ops;
 static const struct rpc_call_ops nfs_read_full_ops;
 
@@ -36,9 +37,8 @@ static mempool_t *nfs_rdata_mempool;
 
 #define MIN_POOL_READ  (32)
 
-struct nfs_read_data *nfs_readdata_alloc(size_t len)
+struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
 {
-       unsigned int pagecount = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
        struct nfs_read_data *p = mempool_alloc(nfs_rdata_mempool, GFP_NOFS);
 
        if (p) {
@@ -133,7 +133,10 @@ static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
                memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len);
 
        nfs_list_add_request(new, &one_request);
-       nfs_pagein_one(&one_request, inode);
+       if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE)
+               nfs_pagein_multi(inode, &one_request, 1, len, 0);
+       else
+               nfs_pagein_one(inode, &one_request, 1, len, 0);
        return 0;
 }
 
@@ -230,7 +233,7 @@ static void nfs_execute_read(struct nfs_read_data *data)
  * won't see the new data until our attribute cache is updated.  This is more
  * or less conventional NFS client behavior.
  */
-static int nfs_pagein_multi(struct list_head *head, struct inode *inode)
+static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int flags)
 {
        struct nfs_page *req = nfs_list_entry(head->next);
        struct page *page = req->wb_page;
@@ -242,11 +245,11 @@ static int nfs_pagein_multi(struct list_head *head, struct inode *inode)
 
        nfs_list_remove_request(req);
 
-       nbytes = req->wb_bytes;
+       nbytes = count;
        do {
                size_t len = min(nbytes,rsize);
 
-               data = nfs_readdata_alloc(len);
+               data = nfs_readdata_alloc(1);
                if (!data)
                        goto out_bad;
                INIT_LIST_HEAD(&data->pages);
@@ -258,23 +261,19 @@ static int nfs_pagein_multi(struct list_head *head, struct inode *inode)
 
        ClearPageError(page);
        offset = 0;
-       nbytes = req->wb_bytes;
+       nbytes = count;
        do {
                data = list_entry(list.next, struct nfs_read_data, pages);
                list_del_init(&data->pages);
 
                data->pagevec[0] = page;
 
-               if (nbytes > rsize) {
-                       nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
-                                       rsize, offset);
-                       offset += rsize;
-                       nbytes -= rsize;
-               } else {
-                       nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
-                                       nbytes, offset);
-                       nbytes = 0;
-               }
+               if (nbytes < rsize)
+                       rsize = nbytes;
+               nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
+                                 rsize, offset);
+               offset += rsize;
+               nbytes -= rsize;
                nfs_execute_read(data);
        } while (nbytes != 0);
 
@@ -291,30 +290,24 @@ out_bad:
        return -ENOMEM;
 }
 
-static int nfs_pagein_one(struct list_head *head, struct inode *inode)
+static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int flags)
 {
        struct nfs_page         *req;
        struct page             **pages;
        struct nfs_read_data    *data;
-       unsigned int            count;
 
-       if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE)
-               return nfs_pagein_multi(head, inode);
-
-       data = nfs_readdata_alloc(NFS_SERVER(inode)->rsize);
+       data = nfs_readdata_alloc(npages);
        if (!data)
                goto out_bad;
 
        INIT_LIST_HEAD(&data->pages);
        pages = data->pagevec;
-       count = 0;
        while (!list_empty(head)) {
                req = nfs_list_entry(head->next);
                nfs_list_remove_request(req);
                nfs_list_add_request(req, &data->pages);
                ClearPageError(req->wb_page);
                *pages++ = req->wb_page;
-               count += req->wb_bytes;
        }
        req = nfs_list_entry(data->pages.next);
 
@@ -327,28 +320,6 @@ out_bad:
        return -ENOMEM;
 }
 
-static int
-nfs_pagein_list(struct list_head *head, int rpages)
-{
-       LIST_HEAD(one_request);
-       struct nfs_page         *req;
-       int                     error = 0;
-       unsigned int            pages = 0;
-
-       while (!list_empty(head)) {
-               pages += nfs_coalesce_requests(head, &one_request, rpages);
-               req = nfs_list_entry(one_request.next);
-               error = nfs_pagein_one(&one_request, req->wb_context->dentry->d_inode);
-               if (error < 0)
-                       break;
-       }
-       if (error >= 0)
-               return pages;
-
-       nfs_async_read_error(head);
-       return error;
-}
-
 /*
  * This is the callback from RPC telling us whether a reply was
  * received or some error occurred (timeout or socket shutdown).
@@ -538,7 +509,7 @@ out_error:
 }
 
 struct nfs_readdesc {
-       struct list_head *head;
+       struct nfs_pageio_descriptor *pgio;
        struct nfs_open_context *ctx;
 };
 
@@ -562,19 +533,21 @@ readpage_async_filler(void *data, struct page *page)
        }
        if (len < PAGE_CACHE_SIZE)
                memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len);
-       nfs_list_add_request(new, desc->head);
+       nfs_pageio_add_request(desc->pgio, new);
        return 0;
 }
 
 int nfs_readpages(struct file *filp, struct address_space *mapping,
                struct list_head *pages, unsigned nr_pages)
 {
-       LIST_HEAD(head);
+       struct nfs_pageio_descriptor pgio;
        struct nfs_readdesc desc = {
-               .head           = &head,
+               .pgio = &pgio,
        };
        struct inode *inode = mapping->host;
        struct nfs_server *server = NFS_SERVER(inode);
+       size_t rsize = server->rsize;
+       unsigned long npages;
        int ret = -ESTALE;
 
        dprintk("NFS: nfs_readpages (%s/%Ld %d)\n",
@@ -593,13 +566,16 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
        } else
                desc.ctx = get_nfs_open_context((struct nfs_open_context *)
                                filp->private_data);
+       if (rsize < PAGE_CACHE_SIZE)
+               nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0);
+       else
+               nfs_pageio_init(&pgio, inode, nfs_pagein_one, rsize, 0);
+
        ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc);
-       if (!list_empty(&head)) {
-               int err = nfs_pagein_list(&head, server->rpages);
-               if (!ret)
-                       nfs_add_stats(inode, NFSIOS_READPAGES, err);
-                       ret = err;
-       }
+
+       nfs_pageio_complete(&pgio);
+       npages = (pgio.pg_bytes_written + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+       nfs_add_stats(inode, NFSIOS_READPAGES, npages);
        put_nfs_open_context(desc.ctx);
 out:
        return ret;
index f1eae44..ca20d3c 100644 (file)
@@ -204,9 +204,9 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
        lock_kernel();
 
        error = server->nfs_client->rpc_ops->statfs(server, fh, &res);
-       buf->f_type = NFS_SUPER_MAGIC;
        if (error < 0)
                goto out_err;
+       buf->f_type = NFS_SUPER_MAGIC;
 
        /*
         * Current versions of glibc do not correctly handle the
@@ -233,15 +233,14 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_ffree = res.afiles;
 
        buf->f_namelen = server->namelen;
- out:
+
        unlock_kernel();
        return 0;
 
  out_err:
        dprintk("%s: statfs error = %d\n", __FUNCTION__, -error);
-       buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1;
-       goto out;
-
+       unlock_kernel();
+       return error;
 }
 
 /*
@@ -291,6 +290,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
                { NFS_MOUNT_NOAC, ",noac", "" },
                { NFS_MOUNT_NONLM, ",nolock", "" },
                { NFS_MOUNT_NOACL, ",noacl", "" },
+               { NFS_MOUNT_NORDIRPLUS, ",nordirplus", "" },
                { 0, NULL, NULL }
        };
        const struct proc_nfs_info *nfs_infop;
index 7975589..5d44b8b 100644 (file)
@@ -38,7 +38,8 @@
 static struct nfs_page * nfs_update_request(struct nfs_open_context*,
                                            struct page *,
                                            unsigned int, unsigned int);
-static long nfs_flush_mapping(struct address_space *mapping, struct writeback_control *wbc, int how);
+static void nfs_pageio_init_write(struct nfs_pageio_descriptor *desc,
+                                 struct inode *inode, int ioflags);
 static const struct rpc_call_ops nfs_write_partial_ops;
 static const struct rpc_call_ops nfs_write_full_ops;
 static const struct rpc_call_ops nfs_commit_ops;
@@ -71,9 +72,8 @@ void nfs_commit_free(struct nfs_write_data *wdata)
        call_rcu_bh(&wdata->task.u.tk_rcu, nfs_commit_rcu_free);
 }
 
-struct nfs_write_data *nfs_writedata_alloc(size_t len)
+struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
 {
-       unsigned int pagecount = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
        struct nfs_write_data *p = mempool_alloc(nfs_wdata_mempool, GFP_NOFS);
 
        if (p) {
@@ -139,7 +139,7 @@ static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int c
 {
        struct inode *inode = page->mapping->host;
        loff_t end, i_size = i_size_read(inode);
-       unsigned long end_index = (i_size - 1) >> PAGE_CACHE_SHIFT;
+       pgoff_t end_index = (i_size - 1) >> PAGE_CACHE_SHIFT;
 
        if (i_size > 0 && page->index < end_index)
                return;
@@ -201,7 +201,7 @@ static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page,
 static int wb_priority(struct writeback_control *wbc)
 {
        if (wbc->for_reclaim)
-               return FLUSH_HIGHPRI;
+               return FLUSH_HIGHPRI | FLUSH_STABLE;
        if (wbc->for_kupdate)
                return FLUSH_LOWPRI;
        return 0;
@@ -251,7 +251,8 @@ static void nfs_end_page_writeback(struct page *page)
  * was not tagged.
  * May also return an error if the user signalled nfs_wait_on_request().
  */
-static int nfs_page_mark_flush(struct page *page)
+static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
+                               struct page *page)
 {
        struct nfs_page *req;
        struct nfs_inode *nfsi = NFS_I(page->mapping->host);
@@ -273,6 +274,8 @@ static int nfs_page_mark_flush(struct page *page)
                 *       request as dirty (in which case we don't care).
                 */
                spin_unlock(req_lock);
+               /* Prevent deadlock! */
+               nfs_pageio_complete(pgio);
                ret = nfs_wait_on_request(req);
                nfs_release_request(req);
                if (ret != 0)
@@ -283,21 +286,18 @@ static int nfs_page_mark_flush(struct page *page)
                /* This request is marked for commit */
                spin_unlock(req_lock);
                nfs_unlock_request(req);
+               nfs_pageio_complete(pgio);
                return 1;
        }
-       if (nfs_set_page_writeback(page) == 0) {
-               nfs_list_remove_request(req);
-               /* add the request to the inode's dirty list. */
-               radix_tree_tag_set(&nfsi->nfs_page_tree,
-                               req->wb_index, NFS_PAGE_TAG_DIRTY);
-               nfs_list_add_request(req, &nfsi->dirty);
-               nfsi->ndirty++;
-               spin_unlock(req_lock);
-               __mark_inode_dirty(page->mapping->host, I_DIRTY_PAGES);
-       } else
+       if (nfs_set_page_writeback(page) != 0) {
                spin_unlock(req_lock);
+               BUG();
+       }
+       radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index,
+                       NFS_PAGE_TAG_WRITEBACK);
        ret = test_bit(PG_NEED_FLUSH, &req->wb_flags);
-       nfs_unlock_request(req);
+       spin_unlock(req_lock);
+       nfs_pageio_add_request(pgio, req);
        return ret;
 }
 
@@ -306,6 +306,7 @@ static int nfs_page_mark_flush(struct page *page)
  */
 static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc)
 {
+       struct nfs_pageio_descriptor mypgio, *pgio;
        struct nfs_open_context *ctx;
        struct inode *inode = page->mapping->host;
        unsigned offset;
@@ -314,7 +315,14 @@ static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc
        nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE);
        nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1);
 
-       err = nfs_page_mark_flush(page);
+       if (wbc->for_writepages)
+               pgio = wbc->fs_private;
+       else {
+               nfs_pageio_init_write(&mypgio, inode, wb_priority(wbc));
+               pgio = &mypgio;
+       }
+
+       err = nfs_page_async_flush(pgio, page);
        if (err <= 0)
                goto out;
        err = 0;
@@ -331,12 +339,12 @@ static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc
        put_nfs_open_context(ctx);
        if (err != 0)
                goto out;
-       err = nfs_page_mark_flush(page);
+       err = nfs_page_async_flush(pgio, page);
        if (err > 0)
                err = 0;
 out:
        if (!wbc->for_writepages)
-               nfs_flush_mapping(page->mapping, wbc, FLUSH_STABLE|wb_priority(wbc));
+               nfs_pageio_complete(pgio);
        return err;
 }
 
@@ -352,20 +360,20 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc)
 int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
 {
        struct inode *inode = mapping->host;
+       struct nfs_pageio_descriptor pgio;
        int err;
 
        nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES);
 
+       nfs_pageio_init_write(&pgio, inode, wb_priority(wbc));
+       wbc->fs_private = &pgio;
        err = generic_writepages(mapping, wbc);
+       nfs_pageio_complete(&pgio);
        if (err)
                return err;
-       err = nfs_flush_mapping(mapping, wbc, wb_priority(wbc));
-       if (err < 0)
-               goto out;
-       nfs_add_stats(inode, NFSIOS_WRITEPAGES, err);
-       err = 0;
-out:
-       return err;
+       if (pgio.pg_error)
+               return pgio.pg_error;
+       return 0;
 }
 
 /*
@@ -503,11 +511,11 @@ int nfs_reschedule_unstable_write(struct nfs_page *req)
  *
  * Interruptible by signals only if mounted with intr flag.
  */
-static int nfs_wait_on_requests_locked(struct inode *inode, unsigned long idx_start, unsigned int npages)
+static int nfs_wait_on_requests_locked(struct inode *inode, pgoff_t idx_start, unsigned int npages)
 {
        struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_page *req;
-       unsigned long           idx_end, next;
+       pgoff_t idx_end, next;
        unsigned int            res = 0;
        int                     error;
 
@@ -536,18 +544,6 @@ static int nfs_wait_on_requests_locked(struct inode *inode, unsigned long idx_st
        return res;
 }
 
-static void nfs_cancel_dirty_list(struct list_head *head)
-{
-       struct nfs_page *req;
-       while(!list_empty(head)) {
-               req = nfs_list_entry(head->next);
-               nfs_list_remove_request(req);
-               nfs_end_page_writeback(req->wb_page);
-               nfs_inode_remove_request(req);
-               nfs_clear_page_writeback(req);
-       }
-}
-
 static void nfs_cancel_commit_list(struct list_head *head)
 {
        struct nfs_page *req;
@@ -574,7 +570,7 @@ static void nfs_cancel_commit_list(struct list_head *head)
  * The requests are *not* checked to ensure that they form a contiguous set.
  */
 static int
-nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)
+nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, unsigned int npages)
 {
        struct nfs_inode *nfsi = NFS_I(inode);
        int res = 0;
@@ -588,40 +584,12 @@ nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_st
        return res;
 }
 #else
-static inline int nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)
+static inline int nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, unsigned int npages)
 {
        return 0;
 }
 #endif
 
-static int nfs_wait_on_write_congestion(struct address_space *mapping)
-{
-       struct inode *inode = mapping->host;
-       struct backing_dev_info *bdi = mapping->backing_dev_info;
-       int ret = 0;
-
-       might_sleep();
-
-       if (!bdi_write_congested(bdi))
-               return 0;
-
-       nfs_inc_stats(inode, NFSIOS_CONGESTIONWAIT);
-
-       do {
-               struct rpc_clnt *clnt = NFS_CLIENT(inode);
-               sigset_t oldset;
-
-               rpc_clnt_sigmask(clnt, &oldset);
-               ret = congestion_wait_interruptible(WRITE, HZ/10);
-               rpc_clnt_sigunmask(clnt, &oldset);
-               if (ret == -ERESTARTSYS)
-                       break;
-               ret = 0;
-       } while (bdi_write_congested(bdi));
-
-       return ret;
-}
-
 /*
  * Try to update any existing write request, or create one if there is none.
  * In order to match, the request's credentials must match those of
@@ -636,12 +604,10 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
        struct inode *inode = mapping->host;
        struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_page         *req, *new = NULL;
-       unsigned long           rqend, end;
+       pgoff_t         rqend, end;
 
        end = offset + bytes;
 
-       if (nfs_wait_on_write_congestion(mapping))
-               return ERR_PTR(-ERESTARTSYS);
        for (;;) {
                /* Loop over all inode entries and see if we find
                 * A request for the page we wish to update
@@ -865,7 +831,7 @@ static void nfs_execute_write(struct nfs_write_data *data)
  * Generate multiple small requests to write out a single
  * contiguous dirty area on one page.
  */
-static int nfs_flush_multi(struct inode *inode, struct list_head *head, int how)
+static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int how)
 {
        struct nfs_page *req = nfs_list_entry(head->next);
        struct page *page = req->wb_page;
@@ -877,11 +843,11 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, int how)
 
        nfs_list_remove_request(req);
 
-       nbytes = req->wb_bytes;
+       nbytes = count;
        do {
                size_t len = min(nbytes, wsize);
 
-               data = nfs_writedata_alloc(len);
+               data = nfs_writedata_alloc(1);
                if (!data)
                        goto out_bad;
                list_add(&data->pages, &list);
@@ -892,23 +858,19 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, int how)
 
        ClearPageError(page);
        offset = 0;
-       nbytes = req->wb_bytes;
+       nbytes = count;
        do {
                data = list_entry(list.next, struct nfs_write_data, pages);
                list_del_init(&data->pages);
 
                data->pagevec[0] = page;
 
-               if (nbytes > wsize) {
-                       nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
-                                       wsize, offset, how);
-                       offset += wsize;
-                       nbytes -= wsize;
-               } else {
-                       nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
-                                       nbytes, offset, how);
-                       nbytes = 0;
-               }
+               if (nbytes < wsize)
+                       wsize = nbytes;
+               nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
+                                  wsize, offset, how);
+               offset += wsize;
+               nbytes -= wsize;
                nfs_execute_write(data);
        } while (nbytes != 0);
 
@@ -934,26 +896,23 @@ out_bad:
  * This is the case if nfs_updatepage detects a conflicting request
  * that has been written but not committed.
  */
-static int nfs_flush_one(struct inode *inode, struct list_head *head, int how)
+static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int how)
 {
        struct nfs_page         *req;
        struct page             **pages;
        struct nfs_write_data   *data;
-       unsigned int            count;
 
-       data = nfs_writedata_alloc(NFS_SERVER(inode)->wsize);
+       data = nfs_writedata_alloc(npages);
        if (!data)
                goto out_bad;
 
        pages = data->pagevec;
-       count = 0;
        while (!list_empty(head)) {
                req = nfs_list_entry(head->next);
                nfs_list_remove_request(req);
                nfs_list_add_request(req, &data->pages);
                ClearPageError(req->wb_page);
                *pages++ = req->wb_page;
-               count += req->wb_bytes;
        }
        req = nfs_list_entry(data->pages.next);
 
@@ -973,40 +932,15 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, int how)
        return -ENOMEM;
 }
 
-static int nfs_flush_list(struct inode *inode, struct list_head *head, int npages, int how)
+static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
+                                 struct inode *inode, int ioflags)
 {
-       LIST_HEAD(one_request);
-       int (*flush_one)(struct inode *, struct list_head *, int);
-       struct nfs_page *req;
-       int wpages = NFS_SERVER(inode)->wpages;
        int wsize = NFS_SERVER(inode)->wsize;
-       int error;
 
-       flush_one = nfs_flush_one;
        if (wsize < PAGE_CACHE_SIZE)
-               flush_one = nfs_flush_multi;
-       /* For single writes, FLUSH_STABLE is more efficient */
-       if (npages <= wpages && npages == NFS_I(inode)->npages
-                       && nfs_list_entry(head->next)->wb_bytes <= wsize)
-               how |= FLUSH_STABLE;
-
-       do {
-               nfs_coalesce_requests(head, &one_request, wpages);
-               req = nfs_list_entry(one_request.next);
-               error = flush_one(inode, &one_request, how);
-               if (error < 0)
-                       goto out_err;
-       } while (!list_empty(head));
-       return 0;
-out_err:
-       while (!list_empty(head)) {
-               req = nfs_list_entry(head->next);
-               nfs_list_remove_request(req);
-               nfs_redirty_request(req);
-               nfs_end_page_writeback(req->wb_page);
-               nfs_clear_page_writeback(req);
-       }
-       return error;
+               nfs_pageio_init(pgio, inode, nfs_flush_multi, wsize, ioflags);
+       else
+               nfs_pageio_init(pgio, inode, nfs_flush_one, wsize, ioflags);
 }
 
 /*
@@ -1330,31 +1264,7 @@ static const struct rpc_call_ops nfs_commit_ops = {
        .rpc_call_done = nfs_commit_done,
        .rpc_release = nfs_commit_release,
 };
-#else
-static inline int nfs_commit_list(struct inode *inode, struct list_head *head, int how)
-{
-       return 0;
-}
-#endif
-
-static long nfs_flush_mapping(struct address_space *mapping, struct writeback_control *wbc, int how)
-{
-       struct nfs_inode *nfsi = NFS_I(mapping->host);
-       LIST_HEAD(head);
-       long res;
-
-       spin_lock(&nfsi->req_lock);
-       res = nfs_scan_dirty(mapping, wbc, &head);
-       spin_unlock(&nfsi->req_lock);
-       if (res) {
-               int error = nfs_flush_list(mapping->host, &head, res, how);
-               if (error < 0)
-                       return error;
-       }
-       return res;
-}
 
-#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
 int nfs_commit_inode(struct inode *inode, int how)
 {
        struct nfs_inode *nfsi = NFS_I(inode);
@@ -1371,13 +1281,18 @@ int nfs_commit_inode(struct inode *inode, int how)
        }
        return res;
 }
+#else
+static inline int nfs_commit_list(struct inode *inode, struct list_head *head, int how)
+{
+       return 0;
+}
 #endif
 
 long nfs_sync_mapping_wait(struct address_space *mapping, struct writeback_control *wbc, int how)
 {
        struct inode *inode = mapping->host;
        struct nfs_inode *nfsi = NFS_I(inode);
-       unsigned long idx_start, idx_end;
+       pgoff_t idx_start, idx_end;
        unsigned int npages = 0;
        LIST_HEAD(head);
        int nocommit = how & FLUSH_NOCOMMIT;
@@ -1390,41 +1305,24 @@ long nfs_sync_mapping_wait(struct address_space *mapping, struct writeback_contr
                idx_start = wbc->range_start >> PAGE_CACHE_SHIFT;
                idx_end = wbc->range_end >> PAGE_CACHE_SHIFT;
                if (idx_end > idx_start) {
-                       unsigned long l_npages = 1 + idx_end - idx_start;
+                       pgoff_t l_npages = 1 + idx_end - idx_start;
                        npages = l_npages;
                        if (sizeof(npages) != sizeof(l_npages) &&
-                                       (unsigned long)npages != l_npages)
+                                       (pgoff_t)npages != l_npages)
                                npages = 0;
                }
        }
        how &= ~FLUSH_NOCOMMIT;
        spin_lock(&nfsi->req_lock);
        do {
-               wbc->pages_skipped = 0;
                ret = nfs_wait_on_requests_locked(inode, idx_start, npages);
                if (ret != 0)
                        continue;
-               pages = nfs_scan_dirty(mapping, wbc, &head);
-               if (pages != 0) {
-                       spin_unlock(&nfsi->req_lock);
-                       if (how & FLUSH_INVALIDATE) {
-                               nfs_cancel_dirty_list(&head);
-                               ret = pages;
-                       } else
-                               ret = nfs_flush_list(inode, &head, pages, how);
-                       spin_lock(&nfsi->req_lock);
-                       continue;
-               }
-               if (wbc->pages_skipped != 0)
-                       continue;
                if (nocommit)
                        break;
                pages = nfs_scan_commit(inode, &head, idx_start, npages);
-               if (pages == 0) {
-                       if (wbc->pages_skipped != 0)
-                               continue;
+               if (pages == 0)
                        break;
-               }
                if (how & FLUSH_INVALIDATE) {
                        spin_unlock(&nfsi->req_lock);
                        nfs_cancel_commit_list(&head);
@@ -1456,7 +1354,7 @@ int nfs_wb_all(struct inode *inode)
        };
        int ret;
 
-       ret = generic_writepages(mapping, &wbc);
+       ret = nfs_writepages(mapping, &wbc);
        if (ret < 0)
                goto out;
        ret = nfs_sync_mapping_wait(mapping, &wbc, 0);
@@ -1479,11 +1377,9 @@ int nfs_sync_mapping_range(struct address_space *mapping, loff_t range_start, lo
        };
        int ret;
 
-       if (!(how & FLUSH_NOWRITEPAGE)) {
-               ret = generic_writepages(mapping, &wbc);
-               if (ret < 0)
-                       goto out;
-       }
+       ret = nfs_writepages(mapping, &wbc);
+       if (ret < 0)
+               goto out;
        ret = nfs_sync_mapping_wait(mapping, &wbc, how);
        if (ret >= 0)
                return 0;
@@ -1506,7 +1402,7 @@ int nfs_wb_page_priority(struct inode *inode, struct page *page, int how)
        int ret;
 
        BUG_ON(!PageLocked(page));
-       if (!(how & FLUSH_NOWRITEPAGE) && clear_page_dirty_for_io(page)) {
+       if (clear_page_dirty_for_io(page)) {
                ret = nfs_writepage_locked(page, &wbc);
                if (ret < 0)
                        goto out;
@@ -1531,10 +1427,18 @@ int nfs_wb_page(struct inode *inode, struct page* page)
 
 int nfs_set_page_dirty(struct page *page)
 {
-       spinlock_t *req_lock = &NFS_I(page->mapping->host)->req_lock;
+       struct address_space *mapping = page->mapping;
+       struct inode *inode;
+       spinlock_t *req_lock;
        struct nfs_page *req;
        int ret;
 
+       if (!mapping)
+               goto out_raced;
+       inode = mapping->host;
+       if (!inode)
+               goto out_raced;
+       req_lock = &NFS_I(inode)->req_lock;
        spin_lock(req_lock);
        req = nfs_page_find_request_locked(page);
        if (req != NULL) {
@@ -1547,6 +1451,8 @@ int nfs_set_page_dirty(struct page *page)
        ret = __set_page_dirty_nobuffers(page);
        spin_unlock(req_lock);
        return ret;
+out_raced:
+       return !TestSetPageDirty(page);
 }
 
 
index fb14d68..32ffea0 100644 (file)
@@ -315,16 +315,13 @@ out:
 /*
  * RPC procedure tables
  */
-#ifndef MAX
-# define MAX(a, b)      (((a) > (b))? (a) : (b))
-#endif
-
 #define PROC(proc, call, argtype, restype)                              \
 [NFSPROC4_CLNT_##proc] = {                                             \
         .p_proc   = NFSPROC4_CB_##call,                                        \
         .p_encode = (kxdrproc_t) nfs4_xdr_##argtype,                    \
         .p_decode = (kxdrproc_t) nfs4_xdr_##restype,                    \
-        .p_bufsiz = MAX(NFS4_##argtype##_sz,NFS4_##restype##_sz) << 2,  \
+        .p_arglen = NFS4_##argtype##_sz,                                \
+        .p_replen = NFS4_##restype##_sz,                                \
         .p_statidx = NFSPROC4_CB_##call,                               \
        .p_name   = #proc,                                              \
 }
index a0c8667..19712a7 100644 (file)
@@ -2869,7 +2869,7 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,
        tl = &tl_copy->id2.i_dealloc;
        num_recs = le16_to_cpu(tl->tl_used);
        mlog(0, "cleanup %u records from %llu\n", num_recs,
-            (unsigned long long)tl_copy->i_blkno);
+            (unsigned long long)le64_to_cpu(tl_copy->i_blkno));
 
        mutex_lock(&tl_inode->i_mutex);
        for(i = 0; i < num_recs; i++) {
@@ -3801,8 +3801,8 @@ int ocfs2_prepare_truncate(struct ocfs2_super *osb,
        fe = (struct ocfs2_dinode *) fe_bh->b_data;
 
        mlog(0, "fe->i_clusters = %u, new_i_clusters = %u, fe->i_size ="
-            "%llu\n", fe->i_clusters, new_i_clusters,
-            (unsigned long long)fe->i_size);
+            "%llu\n", le32_to_cpu(fe->i_clusters), new_i_clusters,
+            (unsigned long long)le64_to_cpu(fe->i_size));
 
        *tc = kzalloc(sizeof(struct ocfs2_truncate_context), GFP_KERNEL);
        if (!(*tc)) {
index 56963e6..8e7cafb 100644 (file)
@@ -78,7 +78,8 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock,
 
        if (!OCFS2_IS_VALID_DINODE(fe)) {
                mlog(ML_ERROR, "Invalid dinode #%llu: signature = %.*s\n",
-                    (unsigned long long)fe->i_blkno, 7, fe->i_signature);
+                    (unsigned long long)le64_to_cpu(fe->i_blkno), 7,
+                    fe->i_signature);
                goto bail;
        }
 
@@ -939,9 +940,9 @@ out:
  * Returns a negative error code or the number of bytes copied into
  * the page.
  */
-int ocfs2_write_data_page(struct inode *inode, handle_t *handle,
-                         u64 *p_blkno, struct page *page,
-                         struct ocfs2_write_ctxt *wc, int new)
+static int ocfs2_write_data_page(struct inode *inode, handle_t *handle,
+                                u64 *p_blkno, struct page *page,
+                                struct ocfs2_write_ctxt *wc, int new)
 {
        int ret, copied = 0;
        unsigned int from = 0, to = 0;
@@ -1086,7 +1087,7 @@ static ssize_t ocfs2_write(struct file *file, u32 phys, handle_t *handle,
        for(i = 0; i < numpages; i++) {
                index = start + i;
 
-               cpages[i] = grab_cache_page(mapping, index);
+               cpages[i] = find_or_create_page(mapping, index, GFP_NOFS);
                if (!cpages[i]) {
                        ret = -ENOMEM;
                        mlog_errno(ret);
index eba282d..9791134 100644 (file)
@@ -438,7 +438,7 @@ static inline void o2hb_prepare_block(struct o2hb_region *reg,
                                                                   hb_block));
 
        mlog(ML_HB_BIO, "our node generation = 0x%llx, cksum = 0x%x\n",
-            (long long)cpu_to_le64(generation),
+            (long long)generation,
             le32_to_cpu(hb_block->hb_cksum));
 }
 
index 636593b..2e975c0 100644 (file)
@@ -147,7 +147,7 @@ static struct kset mlog_kset = {
        .kobj   = {.name = "logmask", .ktype = &mlog_ktype},
 };
 
-int mlog_sys_init(struct subsystem *o2cb_subsys)
+int mlog_sys_init(struct kset *o2cb_subsys)
 {
        int i = 0;
 
@@ -157,7 +157,7 @@ int mlog_sys_init(struct subsystem *o2cb_subsys)
        }
        mlog_attr_ptrs[i] = NULL;
 
-       mlog_kset.subsys = o2cb_subsys;
+       kobj_set_kset_s(&mlog_kset, o2cb_subsys);
        return kset_register(&mlog_kset);
 }
 
index a42628b..75cd877 100644 (file)
@@ -278,7 +278,7 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits;
 
 #include <linux/kobject.h>
 #include <linux/sysfs.h>
-int mlog_sys_init(struct subsystem *o2cb_subsys);
+int mlog_sys_init(struct kset *o2cb_subsys);
 void mlog_sys_shutdown(void);
 
 #endif /* O2CLUSTER_MASKLOG_H */
index 1d9f6ac..64f6f37 100644 (file)
@@ -42,7 +42,6 @@ struct o2cb_attribute {
 #define O2CB_ATTR(_name, _mode, _show, _store) \
 struct o2cb_attribute o2cb_attr_##_name = __ATTR(_name, _mode, _show, _store)
 
-#define to_o2cb_subsys(k) container_of(to_kset(k), struct subsystem, kset)
 #define to_o2cb_attr(_attr) container_of(_attr, struct o2cb_attribute, attr)
 
 static ssize_t o2cb_interface_revision_show(char *buf)
@@ -79,7 +78,7 @@ static ssize_t
 o2cb_show(struct kobject * kobj, struct attribute * attr, char * buffer)
 {
        struct o2cb_attribute *o2cb_attr = to_o2cb_attr(attr);
-       struct subsystem *sbs = to_o2cb_subsys(kobj);
+       struct kset *sbs = to_kset(kobj);
 
        BUG_ON(sbs != &o2cb_subsys);
 
@@ -93,7 +92,7 @@ o2cb_store(struct kobject * kobj, struct attribute * attr,
             const char * buffer, size_t count)
 {
        struct o2cb_attribute *o2cb_attr = to_o2cb_attr(attr);
-       struct subsystem *sbs = to_o2cb_subsys(kobj);
+       struct kset *sbs = to_kset(kobj);
 
        BUG_ON(sbs != &o2cb_subsys);
 
@@ -112,7 +111,7 @@ int o2cb_sys_init(void)
 {
        int ret;
 
-       o2cb_subsys.kset.kobj.ktype = &o2cb_subsys_type;
+       o2cb_subsys.kobj.ktype = &o2cb_subsys_type;
        ret = subsystem_register(&o2cb_subsys);
        if (ret)
                return ret;
index 69caf3e..0b229a9 100644 (file)
@@ -1496,7 +1496,7 @@ static void o2net_start_connect(struct work_struct *work)
        sock->sk->sk_allocation = GFP_ATOMIC;
 
        myaddr.sin_family = AF_INET;
-       myaddr.sin_addr.s_addr = (__force u32)mynode->nd_ipv4_address;
+       myaddr.sin_addr.s_addr = mynode->nd_ipv4_address;
        myaddr.sin_port = (__force u16)htons(0); /* any port */
 
        ret = sock->ops->bind(sock, (struct sockaddr *)&myaddr,
@@ -1521,8 +1521,8 @@ static void o2net_start_connect(struct work_struct *work)
        spin_unlock(&nn->nn_lock);
 
        remoteaddr.sin_family = AF_INET;
-       remoteaddr.sin_addr.s_addr = (__force u32)node->nd_ipv4_address;
-       remoteaddr.sin_port = (__force u16)node->nd_ipv4_port;
+       remoteaddr.sin_addr.s_addr = node->nd_ipv4_address;
+       remoteaddr.sin_port = node->nd_ipv4_port;
 
        ret = sc->sc_sock->ops->connect(sc->sc_sock,
                                        (struct sockaddr *)&remoteaddr,
@@ -1810,8 +1810,8 @@ static int o2net_open_listening_sock(__be32 addr, __be16 port)
        int ret;
        struct sockaddr_in sin = {
                .sin_family = PF_INET,
-               .sin_addr = { .s_addr = (__force u32)addr },
-               .sin_port = (__force u16)port,
+               .sin_addr = { .s_addr = addr },
+               .sin_port = port,
        };
 
        ret = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
index 67e6866..c441ef1 100644 (file)
@@ -403,7 +403,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
                            struct buffer_head **new_de_bh)
 {
        int status = 0;
-       int credits, num_free_extents;
+       int credits, num_free_extents, drop_alloc_sem = 0;
        loff_t dir_i_size;
        struct ocfs2_dinode *fe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
        struct ocfs2_alloc_context *data_ac = NULL;
@@ -452,6 +452,9 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
                credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS;
        }
 
+       down_write(&OCFS2_I(dir)->ip_alloc_sem);
+       drop_alloc_sem = 1;
+
        handle = ocfs2_start_trans(osb, credits);
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
@@ -497,6 +500,8 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
        *new_de_bh = new_bh;
        get_bh(*new_de_bh);
 bail:
+       if (drop_alloc_sem)
+               up_write(&OCFS2_I(dir)->ip_alloc_sem);
        if (handle)
                ocfs2_commit_trans(osb, handle);
 
index 241cad3..2fd8bde 100644 (file)
@@ -312,8 +312,8 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data,
            past->type != DLM_BAST) {
                mlog(ML_ERROR, "Unknown ast type! %d, cookie=%u:%llu"
                     "name=%.*s\n", past->type, 
-                    dlm_get_lock_cookie_node(be64_to_cpu(cookie)),
-                    dlm_get_lock_cookie_seq(be64_to_cpu(cookie)),
+                    dlm_get_lock_cookie_node(cookie),
+                    dlm_get_lock_cookie_seq(cookie),
                     locklen, name);
                ret = DLM_IVLOCKID;
                goto leave;
@@ -324,8 +324,8 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data,
                mlog(0, "got %sast for unknown lockres! "
                     "cookie=%u:%llu, name=%.*s, namelen=%u\n",
                     past->type == DLM_AST ? "" : "b",
-                    dlm_get_lock_cookie_node(be64_to_cpu(cookie)),
-                    dlm_get_lock_cookie_seq(be64_to_cpu(cookie)),
+                    dlm_get_lock_cookie_node(cookie),
+                    dlm_get_lock_cookie_seq(cookie),
                     locklen, name, locklen);
                ret = DLM_IVLOCKID;
                goto leave;
@@ -370,8 +370,8 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data,
 
        mlog(0, "got %sast for unknown lock!  cookie=%u:%llu, "
             "name=%.*s, namelen=%u\n", past->type == DLM_AST ? "" : "b", 
-            dlm_get_lock_cookie_node(be64_to_cpu(cookie)),
-            dlm_get_lock_cookie_seq(be64_to_cpu(cookie)),
+            dlm_get_lock_cookie_node(cookie),
+            dlm_get_lock_cookie_seq(cookie),
             locklen, name, locklen);
 
        ret = DLM_NORMAL;
index c1807a4..671c4ed 100644 (file)
@@ -1769,7 +1769,7 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm,
                        /* lock is always created locally first, and
                         * destroyed locally last.  it must be on the list */
                        if (!lock) {
-                               u64 c = ml->cookie;
+                               __be64 c = ml->cookie;
                                mlog(ML_ERROR, "could not find local lock "
                                               "with cookie %u:%llu!\n",
                                     dlm_get_lock_cookie_node(be64_to_cpu(c)),
@@ -1878,7 +1878,7 @@ skip_lvb:
                spin_lock(&res->spinlock);
                list_for_each_entry(lock, queue, list) {
                        if (lock->ml.cookie == ml->cookie) {
-                               u64 c = lock->ml.cookie;
+                               __be64 c = lock->ml.cookie;
                                mlog(ML_ERROR, "%s:%.*s: %u:%llu: lock already "
                                     "exists on this lockres!\n", dlm->name,
                                     res->lockname.len, res->lockname.name,
index 2b264c6..cebd089 100644 (file)
@@ -76,7 +76,7 @@ repeat:
                goto repeat;
        }
        remove_wait_queue(&res->wq, &wait);
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
 }
 
 int __dlm_lockres_has_locks(struct dlm_lock_resource *res)
index 27e43b0..024777a 100644 (file)
@@ -104,6 +104,35 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres,
 static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb,
                                     struct ocfs2_lock_res *lockres);
 
+
+#define mlog_meta_lvb(__level, __lockres) ocfs2_dump_meta_lvb_info(__level, __PRETTY_FUNCTION__, __LINE__, __lockres)
+
+/* This aids in debugging situations where a bad LVB might be involved. */
+static void ocfs2_dump_meta_lvb_info(u64 level,
+                                    const char *function,
+                                    unsigned int line,
+                                    struct ocfs2_lock_res *lockres)
+{
+       struct ocfs2_meta_lvb *lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb;
+
+       mlog(level, "LVB information for %s (called from %s:%u):\n",
+            lockres->l_name, function, line);
+       mlog(level, "version: %u, clusters: %u, generation: 0x%x\n",
+            lvb->lvb_version, be32_to_cpu(lvb->lvb_iclusters),
+            be32_to_cpu(lvb->lvb_igeneration));
+       mlog(level, "size: %llu, uid %u, gid %u, mode 0x%x\n",
+            (unsigned long long)be64_to_cpu(lvb->lvb_isize),
+            be32_to_cpu(lvb->lvb_iuid), be32_to_cpu(lvb->lvb_igid),
+            be16_to_cpu(lvb->lvb_imode));
+       mlog(level, "nlink %u, atime_packed 0x%llx, ctime_packed 0x%llx, "
+            "mtime_packed 0x%llx iattr 0x%x\n", be16_to_cpu(lvb->lvb_inlink),
+            (long long)be64_to_cpu(lvb->lvb_iatime_packed),
+            (long long)be64_to_cpu(lvb->lvb_ictime_packed),
+            (long long)be64_to_cpu(lvb->lvb_imtime_packed),
+            be32_to_cpu(lvb->lvb_iattr));
+}
+
+
 /*
  * OCFS2 Lock Resource Operations
  *
@@ -3078,28 +3107,3 @@ static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb,
 
        mlog_exit_void();
 }
-
-/* This aids in debugging situations where a bad LVB might be involved. */
-void ocfs2_dump_meta_lvb_info(u64 level,
-                             const char *function,
-                             unsigned int line,
-                             struct ocfs2_lock_res *lockres)
-{
-       struct ocfs2_meta_lvb *lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb;
-
-       mlog(level, "LVB information for %s (called from %s:%u):\n",
-            lockres->l_name, function, line);
-       mlog(level, "version: %u, clusters: %u, generation: 0x%x\n",
-            lvb->lvb_version, be32_to_cpu(lvb->lvb_iclusters),
-            be32_to_cpu(lvb->lvb_igeneration));
-       mlog(level, "size: %llu, uid %u, gid %u, mode 0x%x\n",
-            (unsigned long long)be64_to_cpu(lvb->lvb_isize),
-            be32_to_cpu(lvb->lvb_iuid), be32_to_cpu(lvb->lvb_igid),
-            be16_to_cpu(lvb->lvb_imode));
-       mlog(level, "nlink %u, atime_packed 0x%llx, ctime_packed 0x%llx, "
-            "mtime_packed 0x%llx iattr 0x%x\n", be16_to_cpu(lvb->lvb_inlink),
-            (long long)be64_to_cpu(lvb->lvb_iatime_packed),
-            (long long)be64_to_cpu(lvb->lvb_ictime_packed),
-            (long long)be64_to_cpu(lvb->lvb_imtime_packed),
-            be32_to_cpu(lvb->lvb_iattr));
-}
index 59cb566..492bad3 100644 (file)
@@ -119,11 +119,4 @@ void ocfs2_process_blocked_lock(struct ocfs2_super *osb,
 struct ocfs2_dlm_debug *ocfs2_new_dlm_debug(void);
 void ocfs2_put_dlm_debug(struct ocfs2_dlm_debug *dlm_debug);
 
-/* aids in debugging and tracking lvbs */
-void ocfs2_dump_meta_lvb_info(u64 level,
-                             const char *function,
-                             unsigned int line,
-                             struct ocfs2_lock_res *lockres);
-#define mlog_meta_lvb(__level, __lockres) ocfs2_dump_meta_lvb_info(__level, __PRETTY_FUNCTION__, __LINE__, __lockres)
-
 #endif /* DLMGLUE_H */
index 56e1fef..bc48177 100644 (file)
@@ -140,7 +140,7 @@ bail:
        return parent;
 }
 
-static int ocfs2_encode_fh(struct dentry *dentry, __be32 *fh, int *max_len,
+static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len,
                           int connectable)
 {
        struct inode *inode = dentry->d_inode;
@@ -148,6 +148,7 @@ static int ocfs2_encode_fh(struct dentry *dentry, __be32 *fh, int *max_len,
        int type = 1;
        u64 blkno;
        u32 generation;
+       __le32 *fh = (__force __le32 *) fh_in;
 
        mlog_entry("(0x%p, '%.*s', 0x%p, %d, %d)\n", dentry,
                   dentry->d_name.len, dentry->d_name.name,
@@ -199,7 +200,7 @@ bail:
        return type;
 }
 
-static struct dentry *ocfs2_decode_fh(struct super_block *sb, __be32 *fh,
+static struct dentry *ocfs2_decode_fh(struct super_block *sb, u32 *fh_in,
                                      int fh_len, int fileid_type,
                                      int (*acceptable)(void *context,
                                                        struct dentry *de),
@@ -207,6 +208,7 @@ static struct dentry *ocfs2_decode_fh(struct super_block *sb, __be32 *fh,
 {
        struct ocfs2_inode_handle handle, parent;
        struct dentry *ret = NULL;
+       __le32 *fh = (__force __le32 *) fh_in;
 
        mlog_entry("(0x%p, 0x%p, %d, %d, 0x%p, 0x%p)\n",
                   sb, fh, fh_len, fileid_type, acceptable, context);
index 520a2a6..9395b4f 100644 (file)
@@ -207,10 +207,10 @@ out:
        return ret;
 }
 
-int ocfs2_set_inode_size(handle_t *handle,
-                        struct inode *inode,
-                        struct buffer_head *fe_bh,
-                        u64 new_i_size)
+static int ocfs2_set_inode_size(handle_t *handle,
+                               struct inode *inode,
+                               struct buffer_head *fe_bh,
+                               u64 new_i_size)
 {
        int status;
 
@@ -713,7 +713,8 @@ restarted_transaction:
        }
 
        mlog(0, "fe: i_clusters = %u, i_size=%llu\n",
-            fe->i_clusters, (unsigned long long)fe->i_size);
+            le32_to_cpu(fe->i_clusters),
+            (unsigned long long)le64_to_cpu(fe->i_size));
        mlog(0, "inode: ip_clusters=%u, i_size=%lld\n",
             OCFS2_I(inode)->ip_clusters, i_size_read(inode));
 
@@ -1853,6 +1854,9 @@ const struct file_operations ocfs2_fops = {
        .aio_read       = ocfs2_file_aio_read,
        .aio_write      = ocfs2_file_aio_write,
        .ioctl          = ocfs2_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = ocfs2_compat_ioctl,
+#endif
        .splice_read    = ocfs2_file_splice_read,
        .splice_write   = ocfs2_file_splice_write,
 };
@@ -1862,4 +1866,7 @@ const struct file_operations ocfs2_dops = {
        .readdir        = ocfs2_readdir,
        .fsync          = ocfs2_sync_file,
        .ioctl          = ocfs2_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = ocfs2_compat_ioctl,
+#endif
 };
index 2c4460f..a4dd1fa 100644 (file)
@@ -56,11 +56,6 @@ int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
 int ocfs2_permission(struct inode *inode, int mask,
                     struct nameidata *nd);
 
-int ocfs2_set_inode_size(handle_t *handle,
-                        struct inode *inode,
-                        struct buffer_head *fe_bh,
-                        u64 new_i_size);
-
 int ocfs2_should_update_atime(struct inode *inode,
                              struct vfsmount *vfsmnt);
 int ocfs2_update_inode_atime(struct inode *inode,
index 21a6050..bc844bf 100644 (file)
@@ -89,6 +89,25 @@ void ocfs2_set_inode_flags(struct inode *inode)
                inode->i_flags |= S_DIRSYNC;
 }
 
+/* Propagate flags from i_flags to OCFS2_I(inode)->ip_attr */
+void ocfs2_get_inode_flags(struct ocfs2_inode_info *oi)
+{
+       unsigned int flags = oi->vfs_inode.i_flags;
+
+       oi->ip_attr &= ~(OCFS2_SYNC_FL|OCFS2_APPEND_FL|
+                       OCFS2_IMMUTABLE_FL|OCFS2_NOATIME_FL|OCFS2_DIRSYNC_FL);
+       if (flags & S_SYNC)
+               oi->ip_attr |= OCFS2_SYNC_FL;
+       if (flags & S_APPEND)
+               oi->ip_attr |= OCFS2_APPEND_FL;
+       if (flags & S_IMMUTABLE)
+               oi->ip_attr |= OCFS2_IMMUTABLE_FL;
+       if (flags & S_NOATIME)
+               oi->ip_attr |= OCFS2_NOATIME_FL;
+       if (flags & S_DIRSYNC)
+               oi->ip_attr |= OCFS2_DIRSYNC_FL;
+}
+
 struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, int flags)
 {
        struct inode *inode = NULL;
@@ -196,7 +215,7 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
        int status = -EINVAL;
 
        mlog_entry("(0x%p, size:%llu)\n", inode,
-                  (unsigned long long)fe->i_size);
+                  (unsigned long long)le64_to_cpu(fe->i_size));
 
        sb = inode->i_sb;
        osb = OCFS2_SB(sb);
@@ -248,7 +267,7 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
                mlog(ML_ERROR,
                     "ip_blkno %llu != i_blkno %llu!\n",
                     (unsigned long long)OCFS2_I(inode)->ip_blkno,
-                    (unsigned long long)fe->i_blkno);
+                    (unsigned long long)le64_to_cpu(fe->i_blkno));
 
        inode->i_nlink = le16_to_cpu(fe->i_links_count);
 
@@ -301,7 +320,7 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
                 * the generation argument to
                 * ocfs2_inode_lock_res_init() will have to change.
                 */
-               BUG_ON(fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL));
+               BUG_ON(le32_to_cpu(fe->i_flags) & OCFS2_SYSTEM_FL);
 
                ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_meta_lockres,
                                          OCFS2_LOCK_TYPE_META, 0, inode);
@@ -437,7 +456,8 @@ static int ocfs2_read_locked_inode(struct inode *inode,
        fe = (struct ocfs2_dinode *) bh->b_data;
        if (!OCFS2_IS_VALID_DINODE(fe)) {
                mlog(ML_ERROR, "Invalid dinode #%llu: signature = %.*s\n",
-                    (unsigned long long)fe->i_blkno, 7, fe->i_signature);
+                    (unsigned long long)le64_to_cpu(fe->i_blkno), 7,
+                    fe->i_signature);
                goto bail;
        }
 
@@ -812,8 +832,8 @@ static int ocfs2_query_inode_wipe(struct inode *inode,
                     "Inode %llu (on-disk %llu) not orphaned! "
                     "Disk flags  0x%x, inode flags 0x%x\n",
                     (unsigned long long)oi->ip_blkno,
-                    (unsigned long long)di->i_blkno, di->i_flags,
-                    oi->ip_flags);
+                    (unsigned long long)le64_to_cpu(di->i_blkno),
+                    le32_to_cpu(di->i_flags), oi->ip_flags);
                goto bail;
        }
 
@@ -1106,8 +1126,10 @@ struct buffer_head *ocfs2_bread(struct inode *inode,
                return NULL;
        }
 
+       down_read(&OCFS2_I(inode)->ip_alloc_sem);
        tmperr = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL,
                                             NULL);
+       up_read(&OCFS2_I(inode)->ip_alloc_sem);
        if (tmperr < 0) {
                mlog_errno(tmperr);
                goto fail;
@@ -1197,6 +1219,7 @@ int ocfs2_mark_inode_dirty(handle_t *handle,
 
        spin_lock(&OCFS2_I(inode)->ip_lock);
        fe->i_clusters = cpu_to_le32(OCFS2_I(inode)->ip_clusters);
+       ocfs2_get_inode_flags(OCFS2_I(inode));
        fe->i_attr = cpu_to_le32(OCFS2_I(inode)->ip_attr);
        spin_unlock(&OCFS2_I(inode)->ip_lock);
 
index 03ae075..a41d081 100644 (file)
@@ -141,6 +141,7 @@ int ocfs2_aio_read(struct file *file, struct kiocb *req, struct iocb *iocb);
 int ocfs2_aio_write(struct file *file, struct kiocb *req, struct iocb *iocb);
 
 void ocfs2_set_inode_flags(struct inode *inode);
+void ocfs2_get_inode_flags(struct ocfs2_inode_info *oi);
 
 static inline blkcnt_t ocfs2_inode_sector_count(struct inode *inode)
 {
index 4768be5..f3ad21a 100644 (file)
@@ -31,6 +31,7 @@ static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags)
                mlog_errno(status);
                return status;
        }
+       ocfs2_get_inode_flags(OCFS2_I(inode));
        *flags = OCFS2_I(inode)->ip_attr;
        ocfs2_meta_unlock(inode, 0);
 
@@ -134,3 +135,26 @@ int ocfs2_ioctl(struct inode * inode, struct file * filp,
        }
 }
 
+#ifdef CONFIG_COMPAT
+long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+{
+       struct inode *inode = file->f_path.dentry->d_inode;
+       int ret;
+
+       switch (cmd) {
+       case OCFS2_IOC32_GETFLAGS:
+               cmd = OCFS2_IOC_GETFLAGS;
+               break;
+       case OCFS2_IOC32_SETFLAGS:
+               cmd = OCFS2_IOC_SETFLAGS;
+               break;
+       default:
+               return -ENOIOCTLCMD;
+       }
+
+       lock_kernel();
+       ret = ocfs2_ioctl(inode, file, cmd, arg);
+       unlock_kernel();
+       return ret;
+}
+#endif
index 4a7c829..4d6c4f4 100644 (file)
@@ -12,5 +12,6 @@
 
 int ocfs2_ioctl(struct inode * inode, struct file * filp,
        unsigned int cmd, unsigned long arg);
+long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg);
 
 #endif /* OCFS2_IOCTL_H */
index 5a8a90d..dc11880 100644 (file)
@@ -435,7 +435,8 @@ static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb,
                 * handle the errors in a specific manner, so no need
                 * to call ocfs2_error() here. */
                mlog(ML_ERROR, "Journal dinode %llu  has invalid "
-                    "signature: %.*s", (unsigned long long)fe->i_blkno, 7,
+                    "signature: %.*s",
+                    (unsigned long long)le64_to_cpu(fe->i_blkno), 7,
                     fe->i_signature);
                status = -EIO;
                goto out;
@@ -742,7 +743,7 @@ void ocfs2_complete_recovery(struct work_struct *work)
                la_dinode = item->lri_la_dinode;
                if (la_dinode) {
                        mlog(0, "Clean up local alloc %llu\n",
-                            (unsigned long long)la_dinode->i_blkno);
+                            (unsigned long long)le64_to_cpu(la_dinode->i_blkno));
 
                        ret = ocfs2_complete_local_alloc_recovery(osb,
                                                                  la_dinode);
@@ -755,7 +756,7 @@ void ocfs2_complete_recovery(struct work_struct *work)
                tl_dinode = item->lri_tl_dinode;
                if (tl_dinode) {
                        mlog(0, "Clean up truncate log %llu\n",
-                            (unsigned long long)tl_dinode->i_blkno);
+                            (unsigned long long)le64_to_cpu(tl_dinode->i_blkno));
 
                        ret = ocfs2_complete_truncate_log_recovery(osb,
                                                                   tl_dinode);
index 2bcf353..36289e6 100644 (file)
@@ -578,8 +578,9 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
        if (ocfs2_populate_inode(inode, fe, 1) < 0) {
                mlog(ML_ERROR, "populate inode failed! bh->b_blocknr=%llu, "
                     "i_blkno=%llu, i_ino=%lu\n",
-                    (unsigned long long) (*new_fe_bh)->b_blocknr,
-                    (unsigned long long)fe->i_blkno, inode->i_ino);
+                    (unsigned long long)(*new_fe_bh)->b_blocknr,
+                    (unsigned long long)le64_to_cpu(fe->i_blkno),
+                    inode->i_ino);
                BUG();
        }
 
index 82cc92d..a860633 100644 (file)
@@ -363,9 +363,9 @@ static inline int ocfs2_mount_local(struct ocfs2_super *osb)
        typeof(__di) ____di = (__di);                                   \
        ocfs2_error((__sb),                                             \
                "Dinode # %llu has bad signature %.*s",                 \
-               (unsigned long long)(____di)->i_blkno, 7,               \
+               (unsigned long long)le64_to_cpu((____di)->i_blkno), 7,  \
                (____di)->i_signature);                                 \
-} while (0);
+} while (0)
 
 #define OCFS2_IS_VALID_EXTENT_BLOCK(ptr)                               \
        (!strcmp((ptr)->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE))
@@ -374,9 +374,9 @@ static inline int ocfs2_mount_local(struct ocfs2_super *osb)
        typeof(__eb) ____eb = (__eb);                                   \
        ocfs2_error((__sb),                                             \
                "Extent Block # %llu has bad signature %.*s",           \
-               (unsigned long long)(____eb)->h_blkno, 7,               \
+               (unsigned long long)le64_to_cpu((____eb)->h_blkno), 7,  \
                (____eb)->h_signature);                                 \
-} while (0);
+} while (0)
 
 #define OCFS2_IS_VALID_GROUP_DESC(ptr)                                 \
        (!strcmp((ptr)->bg_signature, OCFS2_GROUP_DESC_SIGNATURE))
@@ -385,9 +385,9 @@ static inline int ocfs2_mount_local(struct ocfs2_super *osb)
        typeof(__gd) ____gd = (__gd);                                   \
                ocfs2_error((__sb),                                     \
                "Group Descriptor # %llu has bad signature %.*s",       \
-               (unsigned long long)(____gd)->bg_blkno, 7,              \
+               (unsigned long long)le64_to_cpu((____gd)->bg_blkno), 7, \
                (____gd)->bg_signature);                                \
-} while (0);
+} while (0)
 
 static inline unsigned long ino_from_blkno(struct super_block *sb,
                                           u64 blkno)
index 7130647..f0d9eb0 100644 (file)
  */
 #define OCFS2_IOC_GETFLAGS     _IOR('f', 1, long)
 #define OCFS2_IOC_SETFLAGS     _IOW('f', 2, long)
+#define OCFS2_IOC32_GETFLAGS   _IOR('f', 1, int)
+#define OCFS2_IOC32_SETFLAGS   _IOW('f', 2, int)
 
 /*
  * Journal Flags (ocfs2_dinode.id1.journal1.i_flags)
index 0da655a..e343762 100644 (file)
@@ -849,9 +849,9 @@ static int ocfs2_relink_block_group(handle_t *handle,
        }
 
        mlog(0, "Suballoc %llu, chain %u, move group %llu to top, prev = %llu\n",
-            (unsigned long long)fe->i_blkno, chain,
-            (unsigned long long)bg->bg_blkno,
-            (unsigned long long)prev_bg->bg_blkno);
+            (unsigned long long)le64_to_cpu(fe->i_blkno), chain,
+            (unsigned long long)le64_to_cpu(bg->bg_blkno),
+            (unsigned long long)le64_to_cpu(prev_bg->bg_blkno));
 
        fe_ptr = le64_to_cpu(fe->id2.i_chain.cl_recs[chain].c_blkno);
        bg_ptr = le64_to_cpu(bg->bg_next_group);
@@ -1162,7 +1162,7 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
        }
 
        mlog(0, "alloc succeeds: we give %u bits from block group %llu\n",
-            tmp_bits, (unsigned long long)bg->bg_blkno);
+            tmp_bits, (unsigned long long)le64_to_cpu(bg->bg_blkno));
 
        *num_bits = tmp_bits;
 
@@ -1227,7 +1227,7 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
        }
 
        mlog(0, "Allocated %u bits from suballocator %llu\n", *num_bits,
-            (unsigned long long)fe->i_blkno);
+            (unsigned long long)le64_to_cpu(fe->i_blkno));
 
        *bg_blkno = le64_to_cpu(bg->bg_blkno);
        *bits_left = le16_to_cpu(bg->bg_free_bits_count);
index 5c9e824..f549354 100644 (file)
@@ -1538,7 +1538,7 @@ static int ocfs2_verify_volume(struct ocfs2_dinode *di,
                } else if (bh->b_blocknr != le64_to_cpu(di->i_blkno)) {
                        mlog(ML_ERROR, "bad block number on superblock: "
                             "found %llu, should be %llu\n",
-                            (unsigned long long)di->i_blkno,
+                            (unsigned long long)le64_to_cpu(di->i_blkno),
                             (unsigned long long)bh->b_blocknr);
                } else if (le32_to_cpu(di->id2.i_super.s_clustersize_bits) < 12 ||
                            le32_to_cpu(di->id2.i_super.s_clustersize_bits) > 20) {
index 8a7d003..f01572f 100644 (file)
@@ -312,7 +312,7 @@ static struct attribute * default_attrs[] = {
        NULL,
 };
 
-extern struct subsystem block_subsys;
+extern struct kset block_subsys;
 
 static void part_release(struct kobject *kobj)
 {
@@ -388,7 +388,7 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len,
        kobject_add(&p->kobj);
        if (!disk->part_uevent_suppress)
                kobject_uevent(&p->kobj, KOBJ_ADD);
-       sysfs_create_link(&p->kobj, &block_subsys.kset.kobj, "subsystem");
+       sysfs_create_link(&p->kobj, &block_subsys.kobj, "subsystem");
        if (flags & ADDPART_FLAG_WHOLEDISK) {
                static struct attribute addpartattr = {
                        .name = "whole_disk",
@@ -444,7 +444,7 @@ static int disk_sysfs_symlinks(struct gendisk *disk)
                        goto err_out_dev_link;
        }
 
-       err = sysfs_create_link(&disk->kobj, &block_subsys.kset.kobj,
+       err = sysfs_create_link(&disk->kobj, &block_subsys.kobj,
                                "subsystem");
        if (err)
                goto err_out_disk_name_lnk;
index 8ea2a51..d3b9f5f 100644 (file)
@@ -59,7 +59,7 @@ read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
        if (copy_to_user(userbuf, buffer, count))
                return -EFAULT;
 
-       pr_debug("offs = %lld, *off = %lld, count = %d\n", offs, *off, count);
+       pr_debug("offs = %lld, *off = %lld, count = %zd\n", offs, *off, count);
 
        *off = offs + count;
 
index db0413a..0e637ad 100644 (file)
@@ -13,8 +13,7 @@
 
 #include "sysfs.h"
 
-#define to_subsys(k) container_of(k,struct subsystem,kset.kobj)
-#define to_sattr(a) container_of(a,struct subsys_attribute,attr)
+#define to_sattr(a) container_of(a,struct subsys_attribute, attr)
 
 /*
  * Subsystem file operations.
 static ssize_t 
 subsys_attr_show(struct kobject * kobj, struct attribute * attr, char * page)
 {
-       struct subsystem * s = to_subsys(kobj);
+       struct kset *kset = to_kset(kobj);
        struct subsys_attribute * sattr = to_sattr(attr);
        ssize_t ret = -EIO;
 
        if (sattr->show)
-               ret = sattr->show(s,page);
+               ret = sattr->show(kset, page);
        return ret;
 }
 
@@ -37,12 +36,12 @@ static ssize_t
 subsys_attr_store(struct kobject * kobj, struct attribute * attr, 
                  const char * page, size_t count)
 {
-       struct subsystem * s = to_subsys(kobj);
+       struct kset *kset = to_kset(kobj);
        struct subsys_attribute * sattr = to_sattr(attr);
        ssize_t ret = -EIO;
 
        if (sattr->store)
-               ret = sattr->store(s,page,count);
+               ret = sattr->store(kset, page, count);
        return ret;
 }
 
index 0d9f984..16c3c44 100644 (file)
@@ -316,7 +316,7 @@ struct acpi_bus_event {
        u32 data;
 };
 
-extern struct subsystem acpi_subsys;
+extern struct kset acpi_subsys;
 
 /*
  * External Functions
index 6afb8bd..9173654 100644 (file)
@@ -2,6 +2,7 @@
 #define _ALPHA_SCATTERLIST_H
 
 #include <asm/page.h>
+#include <asm/types.h>
   
 struct scatterlist {
        struct page *page;
index 1937151..84c7269 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef ASMARM_ARCH_MMC_H
 #define ASMARM_ARCH_MMC_H
 
-#include <linux/mmc/protocol.h>
+#include <linux/mmc/host.h>
 
 struct imxmmc_platform_data {
        int (*card_present)(void);
index 789f7f5..2c7f532 100644 (file)
@@ -12,7 +12,6 @@
 #define __ASM_ARCH_DMA_H
 
 #include <linux/device.h>
-#include <linux/pci.h>
 #include <asm/page.h>
 #include <asm/sizes.h>
 #include <asm/hardware.h>
index a38a28c..ef4f570 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef ASMARM_ARCH_MMC_H
 #define ASMARM_ARCH_MMC_H
 
-#include <linux/mmc/protocol.h>
+#include <linux/mmc/host.h>
 #include <linux/interrupt.h>
 
 struct device;
diff --git a/include/asm-arm/arch-pxa/pxa27x_keyboard.h b/include/asm-arm/arch-pxa/pxa27x_keyboard.h
new file mode 100644 (file)
index 0000000..3aaff92
--- /dev/null
@@ -0,0 +1,13 @@
+#define PXAKBD_MAXROW          8
+#define PXAKBD_MAXCOL          8
+
+struct pxa27x_keyboard_platform_data {
+       int nr_rows, nr_cols;
+       int keycodes[PXAKBD_MAXROW][PXAKBD_MAXCOL];
+       int gpio_modes[PXAKBD_MAXROW + PXAKBD_MAXCOL];
+
+#ifdef CONFIG_PM
+       u32 reg_kpc;
+       u32 reg_kprec;
+#endif
+};
index 1b3555d..eb91145 100644 (file)
@@ -4,7 +4,7 @@
 #ifndef ASMARM_MACH_MMC_H
 #define ASMARM_MACH_MMC_H
 
-#include <linux/mmc/protocol.h>
+#include <linux/mmc/host.h>
 
 struct mmc_platform_data {
        unsigned int ocr_mask;                  /* available voltages */
index bfe7d75..c6d5ce3 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASM_AVR32_SCATTERLIST_H
 #define __ASM_AVR32_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
     struct page                *page;
     unsigned int       offset;
index fb38fd3..8e827fa 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _ASM_SCATTERLIST_H
 #define _ASM_SCATTERLIST_H
 
+#include <asm/types.h>
+
 /*
  * Drivers must set either ->address or (preferred) ->page and ->offset
  * to indicate where data must be transferred to/from.
index 7627f0c..985fdf5 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _H8300_SCATTERLIST_H
 #define _H8300_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
        struct page     *page;
        unsigned int    offset;
index 9075083..6af173d 100644 (file)
  * data corruption on some CPUs.
  */
 
-int map_page_into_agp(struct page *page);
-int unmap_page_from_agp(struct page *page);
+/* Caller's responsibility to call global_flush_tlb() for
+ * performance reasons */
+#define map_page_into_agp(page) change_page_attr(page, 1, PAGE_KERNEL_NOCACHE)
+#define unmap_page_from_agp(page) change_page_attr(page, 1, PAGE_KERNEL)
 #define flush_agp_mappings() global_flush_tlb()
 
 /* Could use CLFLUSH here if the cpu supports it. But then it would
index 55d6c95..d7e45a8 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _I386_SCATTERLIST_H
 #define _I386_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
     struct page                *page;
     unsigned int       offset;
index 5b27838..91a9932 100644 (file)
@@ -487,15 +487,11 @@ extern struct voyager_qic_cpi *voyager_quad_cpi_addr[NR_CPUS];
 extern struct voyager_SUS *voyager_SUS;
 
 /* variables exported always */
+extern struct task_struct *voyager_thread;
 extern int voyager_level;
-extern int kvoyagerd_running;
-extern struct semaphore kvoyagerd_sem;
 extern struct voyager_status voyager_status;
 
-
-
 /* functions exported by the voyager and voyager_smp modules */
-
 extern int voyager_cat_readb(__u8 module, __u8 asic, int reg);
 extern void voyager_cat_init(void);
 extern void voyager_detect(struct voyager_bios_info *);
index 9dbea88..a452ea2 100644 (file)
@@ -6,6 +6,8 @@
  *     David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
+#include <asm/types.h>
+
 struct scatterlist {
        struct page *page;
        unsigned int offset;
index c2de96c..352415f 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _ASM_M32R_SCATTERLIST_H
 #define _ASM_M32R_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
     char *  address;    /* Location data is to be transferred to, NULL for
                          * highmem page */
diff --git a/include/asm-m68k/adb.h b/include/asm-m68k/adb.h
deleted file mode 100644 (file)
index 9176b55..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Definitions for talking to ADB and CUDA.  The CUDA is a microcontroller
- * which controls the ADB, system power, RTC, and various other things on
- * later Macintoshes
- *
- * Copyright (C) 1996 Paul Mackerras.
- */
-
-/* First byte sent to or received from CUDA */
-#define ADB_PACKET     0
-#define CUDA_PACKET    1
-#define ERROR_PACKET   2
-#define TIMER_PACKET   3
-#define POWER_PACKET   4
-#define MACIIC_PACKET  5
-
-/* ADB commands (2nd byte) */
-#define ADB_BUSRESET           0
-#define ADB_FLUSH(id)          (1 + ((id) << 4))
-#define ADB_WRITEREG(id, reg)  (8 + (reg) + ((id) << 4))
-#define ADB_READREG(id, reg)   (0xc + (reg) + ((id) << 4))
-
-/* ADB default device IDs (upper 4 bits of 2nd byte) */
-#define ADB_DONGLE     1       /* "software execution control" devices */
-#define ADB_KEYBOARD   2
-#define ADB_MOUSE      3
-#define ADB_TABLET     4
-#define ADB_MODEM      5
-#define ADB_MISC       7       /* maybe a monitor */
-
-/* CUDA commands (2nd byte) */
-#define CUDA_WARM_START                0
-#define CUDA_AUTOPOLL          1
-#define CUDA_GET_6805_ADDR     2
-#define CUDA_GET_TIME          3
-#define CUDA_GET_PRAM          7
-#define CUDA_SET_6805_ADDR     8
-#define CUDA_SET_TIME          9
-#define CUDA_POWERDOWN         0xa
-#define CUDA_POWERUP_TIME      0xb
-#define CUDA_SET_PRAM          0xc
-#define CUDA_MS_RESET          0xd
-#define CUDA_SEND_DFAC         0xe
-#define CUDA_RESET_SYSTEM      0x11
-#define CUDA_SET_IPL           0x12
-#define CUDA_SET_AUTO_RATE     0x14
-#define CUDA_GET_AUTO_RATE     0x16
-#define CUDA_SET_DEVICE_LIST   0x19
-#define CUDA_GET_DEVICE_LIST   0x1a
-#define CUDA_GET_SET_IIC       0x22
-
-#ifdef __KERNEL__
-
-struct adb_request {
-    unsigned char data[16];
-    int nbytes;
-    unsigned char reply[16];
-    int reply_len;
-    unsigned char reply_expected;
-    unsigned char sent;
-    unsigned char got_reply;
-    void (*done)(struct adb_request *);
-    void *arg;
-    struct adb_request *next;
-};
-
-void via_adb_init(void);
-int adb_request(struct adb_request *req,
-                void (*done)(struct adb_request *), int nbytes, ...);
-int adb_send_request(struct adb_request *req);
-void adb_poll(void);
-int adb_register(int default_id,
-                void (*handler)(unsigned char *, int, struct pt_regs *));
-
-#endif /* __KERNEL */
index 1892605..546e7da 100644 (file)
@@ -36,5 +36,11 @@ void ikbd_joystick_disable(void);
 extern void (*atari_MIDI_interrupt_hook) (void);
 /* Hook for mouse driver */
 extern void (*atari_mouse_interrupt_hook) (char *);
+/* Hook for keyboard inputdev  driver */
+extern void (*atari_input_keyboard_interrupt_hook) (unsigned char, char);
+/* Hook for mouse inputdev  driver */
+extern void (*atari_input_mouse_interrupt_hook) (char *);
+
+int atari_keyb_init(void);
 
 #endif /* _LINUX_ATARIKB_H */
index 2085d6f..4da79d3 100644 (file)
@@ -2,6 +2,7 @@
 #define _M68KNOMMU_SCATTERLIST_H
 
 #include <linux/mm.h>
+#include <asm/types.h>
 
 struct scatterlist {
        struct page     *page;
index 2263470..7af104c 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASM_SCATTERLIST_H
 #define __ASM_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
        struct page *   page;
        unsigned int    offset;
index 236c1d0..e7211c7 100644 (file)
@@ -2,6 +2,7 @@
 #define _ASM_PARISC_SCATTERLIST_H
 
 #include <asm/page.h>
+#include <asm/types.h>
 
 struct scatterlist {
        struct page *page;
index 43e90ea..9efc40f 100644 (file)
@@ -18,8 +18,6 @@
 #ifndef _ASM_POWERPC_PS3AV_H_
 #define _ASM_POWERPC_PS3AV_H_
 
-#include <linux/mutex.h>
-
 /** command for ioctl() **/
 #define PS3AV_VERSION 0x205    /* version of ps3av command */
 
@@ -643,24 +641,6 @@ struct ps3av_pkt_avb_param {
        u8 buf[PS3AV_PKT_AVB_PARAM_MAX_BUF_SIZE];
 };
 
-struct ps3av {
-       int available;
-       struct semaphore sem;
-       struct semaphore ping;
-       struct semaphore pong;
-       struct mutex mutex;
-       int open_count;
-       struct ps3_vuart_port_device *dev;
-
-       int region;
-       struct ps3av_pkt_av_get_hw_conf av_hw_conf;
-       u32 av_port[PS3AV_AV_PORT_MAX + PS3AV_OPT_PORT_MAX];
-       u32 opt_port[PS3AV_OPT_PORT_MAX];
-       u32 head[PS3AV_HEAD_MAX];
-       u32 audio_port;
-       int ps3av_mode;
-       int ps3av_mode_old;
-};
 
 /** command status **/
 #define PS3AV_STATUS_SUCCESS                   0x0000  /* success */
@@ -718,6 +698,7 @@ static inline void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_
 extern int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *,
                                            u32);
 
+struct ps3_vuart_port_device;
 extern int ps3av_vuart_write(struct ps3_vuart_port_device *dev,
                             const void *buf, unsigned long size);
 extern int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
@@ -725,6 +706,7 @@ extern int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
 
 extern int ps3av_set_video_mode(u32, int);
 extern int ps3av_set_audio_mode(u32, u32, u32, u32, u32);
+extern int ps3av_get_auto_mode(int);
 extern int ps3av_set_mode(u32, int);
 extern int ps3av_get_mode(void);
 extern int ps3av_get_scanmode(int);
index cfc8153..6795ece 100644 (file)
@@ -164,9 +164,9 @@ extern int ccw_device_resume(struct ccw_device *);
 extern int ccw_device_halt(struct ccw_device *, unsigned long);
 extern int ccw_device_clear(struct ccw_device *, unsigned long);
 
-extern int read_dev_chars(struct ccw_device *cdev, void **buffer, int length);
-extern int read_conf_data(struct ccw_device *cdev, void **buffer, int *length);
-extern int read_conf_data_lpm(struct ccw_device *cdev, void **buffer,
+extern int __deprecated read_dev_chars(struct ccw_device *cdev, void **buffer, int length);
+extern int __deprecated read_conf_data(struct ccw_device *cdev, void **buffer, int *length);
+extern int __deprecated read_conf_data_lpm(struct ccw_device *cdev, void **buffer,
                              int *length, __u8 lpm);
 
 extern int ccw_device_set_online(struct ccw_device *cdev);
index c0d629d..91d0632 100644 (file)
@@ -188,7 +188,8 @@ static inline int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
 /* This yields a mask that user programs can use to figure out what
    instruction set this CPU supports. */
 
-#define ELF_HWCAP (0)
+extern unsigned long elf_hwcap;
+#define ELF_HWCAP (elf_hwcap)
 
 /* This yields a string that ld.so will use to load implementation
    specific libraries for optimization.  This is more specific in
@@ -197,7 +198,9 @@ static inline int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
    For the moment, we have only optimizations for the Intel generations,
    but that could change... */
 
-#define ELF_PLATFORM (NULL)
+#define ELF_PLATFORM_SIZE 8
+extern char elf_platform[];
+#define ELF_PLATFORM (elf_platform)
 
 #ifndef __s390x__
 #define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
index 1b50f89..d2d7ad2 100644 (file)
@@ -22,8 +22,21 @@ struct die_args {
  */
 extern int register_die_notifier(struct notifier_block *);
 extern int unregister_die_notifier(struct notifier_block *);
-extern int register_page_fault_notifier(struct notifier_block *);
-extern int unregister_page_fault_notifier(struct notifier_block *);
+
+/*
+ * These are only here because kprobes.c wants them to implement a
+ * blatant layering violation. Will hopefully go away soon once all
+ * architectures are updated.
+ */
+static inline int register_page_fault_notifier(struct notifier_block *nb)
+{
+       return 0;
+}
+static inline int unregister_page_fault_notifier(struct notifier_block *nb)
+{
+       return 0;
+}
+
 extern struct atomic_notifier_head s390die_chain;
 
 enum die_val {
@@ -39,7 +52,6 @@ enum die_val {
        DIE_GPF,
        DIE_CALL,
        DIE_NMI_IPI,
-       DIE_PAGE_FAULT,
 };
 
 static inline int notify_die(enum die_val val, const char *str,
index b847ff0..830fe4c 100644 (file)
@@ -97,18 +97,10 @@ void kretprobe_trampoline(void);
 int  is_prohibited_opcode(kprobe_opcode_t *instruction);
 void get_instruction_type(struct arch_specific_insn *ainsn);
 
+int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
+int kprobe_exceptions_notify(struct notifier_block *self,
+       unsigned long val, void *data);
+
 #define flush_insn_slot(p)     do { } while (0)
 
 #endif /* _ASM_S390_KPROBES_H */
-
-#ifdef CONFIG_KPROBES
-
-extern int kprobe_exceptions_notify(struct notifier_block *self,
-                                       unsigned long val, void *data);
-#else  /* !CONFIG_KPROBES */
-static inline int kprobe_exceptions_notify(struct notifier_block *self,
-                                               unsigned long val, void *data)
-{
-       return 0;
-}
-#endif
index ffc9788..801a6fd 100644 (file)
@@ -229,17 +229,19 @@ struct _lowcore
        __u16        subchannel_nr;            /* 0x0ba */
        __u32        io_int_parm;              /* 0x0bc */
        __u32        io_int_word;              /* 0x0c0 */
-        __u8         pad3[0xD4-0xC4];          /* 0x0c4 */
+       __u8         pad3[0xc8-0xc4];          /* 0x0c4 */
+       __u32        stfl_fac_list;            /* 0x0c8 */
+       __u8         pad4[0xd4-0xcc];          /* 0x0cc */
        __u32        extended_save_area_addr;  /* 0x0d4 */
        __u32        cpu_timer_save_area[2];   /* 0x0d8 */
        __u32        clock_comp_save_area[2];  /* 0x0e0 */
        __u32        mcck_interruption_code[2]; /* 0x0e8 */
-       __u8         pad4[0xf4-0xf0];          /* 0x0f0 */
+       __u8         pad5[0xf4-0xf0];          /* 0x0f0 */
        __u32        external_damage_code;     /* 0x0f4 */
        __u32        failing_storage_address;  /* 0x0f8 */
-       __u8         pad5[0x100-0xfc];         /* 0x0fc */
+       __u8         pad6[0x100-0xfc];         /* 0x0fc */
        __u32        st_status_fixed_logout[4];/* 0x100 */
-       __u8         pad6[0x120-0x110];        /* 0x110 */
+       __u8         pad7[0x120-0x110];        /* 0x110 */
        __u32        access_regs_save_area[16];/* 0x120 */
        __u32        floating_pt_save_area[8]; /* 0x160 */
        __u32        gpregs_save_area[16];     /* 0x180 */
index d19e7cd..b9ae53c 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASM_SH_SCATTERLIST_H
 #define __ASM_SH_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
     struct page * page; /* Location for highmem page, if any */
     unsigned int offset;/* for highmem, page offset */
index 5d8fa32..1c723f2 100644 (file)
@@ -11,6 +11,8 @@
 #ifndef __ASM_SH64_SCATTERLIST_H
 #define __ASM_SH64_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
     struct page * page; /* Location for highmem page, if any */
     unsigned int offset;/* for highmem, page offset */
index ec4f3c6..048fdb4 100644 (file)
@@ -3,6 +3,7 @@
 #define _SPARC64_SCATTERLIST_H
 
 #include <asm/page.h>
+#include <asm/types.h>
 
 struct scatterlist {
        struct page     *page;
index af1cba6..56f4029 100644 (file)
@@ -14,6 +14,8 @@
 #ifndef __V850_SCATTERLIST_H__
 #define __V850_SCATTERLIST_H__
 
+#include <asm/types.h>
+
 struct scatterlist {
        struct page     *page;
        unsigned        offset;
index 06c52ee..de33866 100644 (file)
  * with different cachability attributes for the same page.
  */
 
-int map_page_into_agp(struct page *page);
-int unmap_page_from_agp(struct page *page);
+/* Caller's responsibility to call global_flush_tlb() for
+ * performance reasons */
+#define map_page_into_agp(page) change_page_attr(page, 1, PAGE_KERNEL_NOCACHE)
+#define unmap_page_from_agp(page) change_page_attr(page, 1, PAGE_KERNEL)
 #define flush_agp_mappings() global_flush_tlb()
 
 /* Could use CLFLUSH here if the cpu supports it. But then it would
index 49d89f8..eaf7ada 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _X8664_SCATTERLIST_H
 #define _X8664_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
     struct page                *page;
     unsigned int       offset;
index 38a2b9a..ca337a2 100644 (file)
@@ -11,6 +11,8 @@
 #ifndef _XTENSA_SCATTERLIST_H
 #define _XTENSA_SCATTERLIST_H
 
+#include <asm/types.h>
+
 struct scatterlist {
        struct page     *page;
        unsigned int    offset;
index 4e05e93..b2b1e6e 100644 (file)
 #define _CRYPTO_ALGAPI_H
 
 #include <linux/crypto.h>
+#include <linux/list.h>
+#include <linux/kernel.h>
 
 struct module;
+struct rtattr;
 struct seq_file;
 
 struct crypto_type {
@@ -38,7 +41,7 @@ struct crypto_template {
        struct hlist_head instances;
        struct module *module;
 
-       struct crypto_instance *(*alloc)(void *param, unsigned int len);
+       struct crypto_instance *(*alloc)(struct rtattr **tb);
        void (*free)(struct crypto_instance *inst);
 
        char name[CRYPTO_MAX_ALG_NAME];
@@ -48,6 +51,15 @@ struct crypto_spawn {
        struct list_head list;
        struct crypto_alg *alg;
        struct crypto_instance *inst;
+       u32 mask;
+};
+
+struct crypto_queue {
+       struct list_head list;
+       struct list_head *backlog;
+
+       unsigned int qlen;
+       unsigned int max_qlen;
 };
 
 struct scatter_walk {
@@ -81,6 +93,7 @@ struct blkcipher_walk {
        int flags;
 };
 
+extern const struct crypto_type crypto_ablkcipher_type;
 extern const struct crypto_type crypto_blkcipher_type;
 extern const struct crypto_type crypto_hash_type;
 
@@ -91,16 +104,23 @@ void crypto_unregister_template(struct crypto_template *tmpl);
 struct crypto_template *crypto_lookup_template(const char *name);
 
 int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
-                     struct crypto_instance *inst);
+                     struct crypto_instance *inst, u32 mask);
 void crypto_drop_spawn(struct crypto_spawn *spawn);
 struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
                                    u32 mask);
 
-struct crypto_alg *crypto_get_attr_alg(void *param, unsigned int len,
-                                      u32 type, u32 mask);
+struct crypto_attr_type *crypto_get_attr_type(struct rtattr **tb);
+int crypto_check_attr_type(struct rtattr **tb, u32 type);
+struct crypto_alg *crypto_get_attr_alg(struct rtattr **tb, u32 type, u32 mask);
 struct crypto_instance *crypto_alloc_instance(const char *name,
                                              struct crypto_alg *alg);
 
+void crypto_init_queue(struct crypto_queue *queue, unsigned int max_qlen);
+int crypto_enqueue_request(struct crypto_queue *queue,
+                          struct crypto_async_request *request);
+struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue);
+int crypto_tfm_in_queue(struct crypto_queue *queue, struct crypto_tfm *tfm);
+
 int blkcipher_walk_done(struct blkcipher_desc *desc,
                        struct blkcipher_walk *walk, int err);
 int blkcipher_walk_virt(struct blkcipher_desc *desc,
@@ -118,11 +138,37 @@ static inline void *crypto_tfm_ctx_aligned(struct crypto_tfm *tfm)
        return (void *)ALIGN(addr, align);
 }
 
+static inline struct crypto_instance *crypto_tfm_alg_instance(
+       struct crypto_tfm *tfm)
+{
+       return container_of(tfm->__crt_alg, struct crypto_instance, alg);
+}
+
 static inline void *crypto_instance_ctx(struct crypto_instance *inst)
 {
        return inst->__ctx;
 }
 
+static inline struct ablkcipher_alg *crypto_ablkcipher_alg(
+       struct crypto_ablkcipher *tfm)
+{
+       return &crypto_ablkcipher_tfm(tfm)->__crt_alg->cra_ablkcipher;
+}
+
+static inline void *crypto_ablkcipher_ctx(struct crypto_ablkcipher *tfm)
+{
+       return crypto_tfm_ctx(&tfm->base);
+}
+
+static inline struct crypto_blkcipher *crypto_spawn_blkcipher(
+       struct crypto_spawn *spawn)
+{
+       u32 type = CRYPTO_ALG_TYPE_BLKCIPHER;
+       u32 mask = CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC;
+
+       return __crypto_blkcipher_cast(crypto_spawn_tfm(spawn, type, mask));
+}
+
 static inline void *crypto_blkcipher_ctx(struct crypto_blkcipher *tfm)
 {
        return crypto_tfm_ctx(&tfm->base);
@@ -170,5 +216,35 @@ static inline void blkcipher_walk_init(struct blkcipher_walk *walk,
        walk->total = nbytes;
 }
 
+static inline struct crypto_async_request *crypto_get_backlog(
+       struct crypto_queue *queue)
+{
+       return queue->backlog == &queue->list ? NULL :
+              container_of(queue->backlog, struct crypto_async_request, list);
+}
+
+static inline int ablkcipher_enqueue_request(struct ablkcipher_alg *alg,
+                                            struct ablkcipher_request *request)
+{
+       return crypto_enqueue_request(alg->queue, &request->base);
+}
+
+static inline struct ablkcipher_request *ablkcipher_dequeue_request(
+       struct ablkcipher_alg *alg)
+{
+       return ablkcipher_request_cast(crypto_dequeue_request(alg->queue));
+}
+
+static inline void *ablkcipher_request_ctx(struct ablkcipher_request *req)
+{
+       return req->__ctx;
+}
+
+static inline int ablkcipher_tfm_in_queue(struct crypto_ablkcipher *tfm)
+{
+       return crypto_tfm_in_queue(crypto_ablkcipher_alg(tfm)->queue,
+                                  crypto_ablkcipher_tfm(tfm));
+}
+
 #endif /* _CRYPTO_ALGAPI_H */
 
index cb9b2ec..963051a 100644 (file)
@@ -265,7 +265,6 @@ struct freq_attr {
 /*********************************************************************
  *                        CPUFREQ 2.6. INTERFACE                     *
  *********************************************************************/
-int cpufreq_set_policy(struct cpufreq_policy *policy);
 int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu);
 int cpufreq_update_policy(unsigned int cpu);
 
index 779aa78..0de7e2a 100644 (file)
@@ -56,6 +56,7 @@
 
 #define CRYPTO_TFM_REQ_WEAK_KEY                0x00000100
 #define CRYPTO_TFM_REQ_MAY_SLEEP       0x00000200
+#define CRYPTO_TFM_REQ_MAY_BACKLOG     0x00000400
 #define CRYPTO_TFM_RES_WEAK_KEY                0x00100000
 #define CRYPTO_TFM_RES_BAD_KEY_LEN     0x00200000
 #define CRYPTO_TFM_RES_BAD_KEY_SCHED   0x00400000
 #endif
 
 struct scatterlist;
+struct crypto_ablkcipher;
+struct crypto_async_request;
 struct crypto_blkcipher;
 struct crypto_hash;
+struct crypto_queue;
 struct crypto_tfm;
 struct crypto_type;
 
+typedef void (*crypto_completion_t)(struct crypto_async_request *req, int err);
+
+struct crypto_async_request {
+       struct list_head list;
+       crypto_completion_t complete;
+       void *data;
+       struct crypto_tfm *tfm;
+
+       u32 flags;
+};
+
+struct ablkcipher_request {
+       struct crypto_async_request base;
+
+       unsigned int nbytes;
+
+       void *info;
+
+       struct scatterlist *src;
+       struct scatterlist *dst;
+
+       void *__ctx[] CRYPTO_MINALIGN_ATTR;
+};
+
 struct blkcipher_desc {
        struct crypto_blkcipher *tfm;
        void *info;
@@ -116,6 +144,19 @@ struct hash_desc {
  * Algorithms: modular crypto algorithm implementations, managed
  * via crypto_register_alg() and crypto_unregister_alg().
  */
+struct ablkcipher_alg {
+       int (*setkey)(struct crypto_ablkcipher *tfm, const u8 *key,
+                     unsigned int keylen);
+       int (*encrypt)(struct ablkcipher_request *req);
+       int (*decrypt)(struct ablkcipher_request *req);
+
+       struct crypto_queue *queue;
+
+       unsigned int min_keysize;
+       unsigned int max_keysize;
+       unsigned int ivsize;
+};
+
 struct blkcipher_alg {
        int (*setkey)(struct crypto_tfm *tfm, const u8 *key,
                      unsigned int keylen);
@@ -170,6 +211,7 @@ struct compress_alg {
                              unsigned int slen, u8 *dst, unsigned int *dlen);
 };
 
+#define cra_ablkcipher cra_u.ablkcipher
 #define cra_blkcipher  cra_u.blkcipher
 #define cra_cipher     cra_u.cipher
 #define cra_digest     cra_u.digest
@@ -194,6 +236,7 @@ struct crypto_alg {
        const struct crypto_type *cra_type;
 
        union {
+               struct ablkcipher_alg ablkcipher;
                struct blkcipher_alg blkcipher;
                struct cipher_alg cipher;
                struct digest_alg digest;
@@ -232,6 +275,15 @@ static inline int crypto_has_alg(const char *name, u32 type, u32 mask)
  * crypto_free_*(), as well as the various helpers below.
  */
 
+struct ablkcipher_tfm {
+       int (*setkey)(struct crypto_ablkcipher *tfm, const u8 *key,
+                     unsigned int keylen);
+       int (*encrypt)(struct ablkcipher_request *req);
+       int (*decrypt)(struct ablkcipher_request *req);
+       unsigned int ivsize;
+       unsigned int reqsize;
+};
+
 struct blkcipher_tfm {
        void *iv;
        int (*setkey)(struct crypto_tfm *tfm, const u8 *key,
@@ -290,6 +342,7 @@ struct compress_tfm {
                              u8 *dst, unsigned int *dlen);
 };
 
+#define crt_ablkcipher crt_u.ablkcipher
 #define crt_blkcipher  crt_u.blkcipher
 #define crt_cipher     crt_u.cipher
 #define crt_hash       crt_u.hash
@@ -300,6 +353,7 @@ struct crypto_tfm {
        u32 crt_flags;
        
        union {
+               struct ablkcipher_tfm ablkcipher;
                struct blkcipher_tfm blkcipher;
                struct cipher_tfm cipher;
                struct hash_tfm hash;
@@ -311,6 +365,10 @@ struct crypto_tfm {
        void *__crt_ctx[] CRYPTO_MINALIGN_ATTR;
 };
 
+struct crypto_ablkcipher {
+       struct crypto_tfm base;
+};
+
 struct crypto_blkcipher {
        struct crypto_tfm base;
 };
@@ -330,12 +388,21 @@ struct crypto_hash {
 enum {
        CRYPTOA_UNSPEC,
        CRYPTOA_ALG,
+       CRYPTOA_TYPE,
+       __CRYPTOA_MAX,
 };
 
+#define CRYPTOA_MAX (__CRYPTOA_MAX - 1)
+
 struct crypto_attr_alg {
        char name[CRYPTO_MAX_ALG_NAME];
 };
 
+struct crypto_attr_type {
+       u32 type;
+       u32 mask;
+};
+
 /* 
  * Transform user interface.
  */
@@ -411,6 +478,167 @@ static inline unsigned int crypto_tfm_ctx_alignment(void)
 /*
  * API wrappers.
  */
+static inline struct crypto_ablkcipher *__crypto_ablkcipher_cast(
+       struct crypto_tfm *tfm)
+{
+       return (struct crypto_ablkcipher *)tfm;
+}
+
+static inline struct crypto_ablkcipher *crypto_alloc_ablkcipher(
+       const char *alg_name, u32 type, u32 mask)
+{
+       type &= ~CRYPTO_ALG_TYPE_MASK;
+       type |= CRYPTO_ALG_TYPE_BLKCIPHER;
+       mask |= CRYPTO_ALG_TYPE_MASK;
+
+       return __crypto_ablkcipher_cast(
+               crypto_alloc_base(alg_name, type, mask));
+}
+
+static inline struct crypto_tfm *crypto_ablkcipher_tfm(
+       struct crypto_ablkcipher *tfm)
+{
+       return &tfm->base;
+}
+
+static inline void crypto_free_ablkcipher(struct crypto_ablkcipher *tfm)
+{
+       crypto_free_tfm(crypto_ablkcipher_tfm(tfm));
+}
+
+static inline int crypto_has_ablkcipher(const char *alg_name, u32 type,
+                                       u32 mask)
+{
+       type &= ~CRYPTO_ALG_TYPE_MASK;
+       type |= CRYPTO_ALG_TYPE_BLKCIPHER;
+       mask |= CRYPTO_ALG_TYPE_MASK;
+
+       return crypto_has_alg(alg_name, type, mask);
+}
+
+static inline struct ablkcipher_tfm *crypto_ablkcipher_crt(
+       struct crypto_ablkcipher *tfm)
+{
+       return &crypto_ablkcipher_tfm(tfm)->crt_ablkcipher;
+}
+
+static inline unsigned int crypto_ablkcipher_ivsize(
+       struct crypto_ablkcipher *tfm)
+{
+       return crypto_ablkcipher_crt(tfm)->ivsize;
+}
+
+static inline unsigned int crypto_ablkcipher_blocksize(
+       struct crypto_ablkcipher *tfm)
+{
+       return crypto_tfm_alg_blocksize(crypto_ablkcipher_tfm(tfm));
+}
+
+static inline unsigned int crypto_ablkcipher_alignmask(
+       struct crypto_ablkcipher *tfm)
+{
+       return crypto_tfm_alg_alignmask(crypto_ablkcipher_tfm(tfm));
+}
+
+static inline u32 crypto_ablkcipher_get_flags(struct crypto_ablkcipher *tfm)
+{
+       return crypto_tfm_get_flags(crypto_ablkcipher_tfm(tfm));
+}
+
+static inline void crypto_ablkcipher_set_flags(struct crypto_ablkcipher *tfm,
+                                              u32 flags)
+{
+       crypto_tfm_set_flags(crypto_ablkcipher_tfm(tfm), flags);
+}
+
+static inline void crypto_ablkcipher_clear_flags(struct crypto_ablkcipher *tfm,
+                                                u32 flags)
+{
+       crypto_tfm_clear_flags(crypto_ablkcipher_tfm(tfm), flags);
+}
+
+static inline int crypto_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
+                                          const u8 *key, unsigned int keylen)
+{
+       return crypto_ablkcipher_crt(tfm)->setkey(tfm, key, keylen);
+}
+
+static inline struct crypto_ablkcipher *crypto_ablkcipher_reqtfm(
+       struct ablkcipher_request *req)
+{
+       return __crypto_ablkcipher_cast(req->base.tfm);
+}
+
+static inline int crypto_ablkcipher_encrypt(struct ablkcipher_request *req)
+{
+       struct ablkcipher_tfm *crt =
+               crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req));
+       return crt->encrypt(req);
+}
+
+static inline int crypto_ablkcipher_decrypt(struct ablkcipher_request *req)
+{
+       struct ablkcipher_tfm *crt =
+               crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req));
+       return crt->decrypt(req);
+}
+
+static inline int crypto_ablkcipher_reqsize(struct crypto_ablkcipher *tfm)
+{
+       return crypto_ablkcipher_crt(tfm)->reqsize;
+}
+
+static inline void ablkcipher_request_set_tfm(
+       struct ablkcipher_request *req, struct crypto_ablkcipher *tfm)
+{
+       req->base.tfm = crypto_ablkcipher_tfm(tfm);
+}
+
+static inline struct ablkcipher_request *ablkcipher_request_cast(
+       struct crypto_async_request *req)
+{
+       return container_of(req, struct ablkcipher_request, base);
+}
+
+static inline struct ablkcipher_request *ablkcipher_request_alloc(
+       struct crypto_ablkcipher *tfm, gfp_t gfp)
+{
+       struct ablkcipher_request *req;
+
+       req = kmalloc(sizeof(struct ablkcipher_request) +
+                     crypto_ablkcipher_reqsize(tfm), gfp);
+
+       if (likely(req))
+               ablkcipher_request_set_tfm(req, tfm);
+
+       return req;
+}
+
+static inline void ablkcipher_request_free(struct ablkcipher_request *req)
+{
+       kfree(req);
+}
+
+static inline void ablkcipher_request_set_callback(
+       struct ablkcipher_request *req,
+       u32 flags, crypto_completion_t complete, void *data)
+{
+       req->base.complete = complete;
+       req->base.data = data;
+       req->base.flags = flags;
+}
+
+static inline void ablkcipher_request_set_crypt(
+       struct ablkcipher_request *req,
+       struct scatterlist *src, struct scatterlist *dst,
+       unsigned int nbytes, void *iv)
+{
+       req->src = src;
+       req->dst = dst;
+       req->nbytes = nbytes;
+       req->info = iv;
+}
+
 static inline struct crypto_blkcipher *__crypto_blkcipher_cast(
        struct crypto_tfm *tfm)
 {
@@ -427,9 +655,9 @@ static inline struct crypto_blkcipher *crypto_blkcipher_cast(
 static inline struct crypto_blkcipher *crypto_alloc_blkcipher(
        const char *alg_name, u32 type, u32 mask)
 {
-       type &= ~CRYPTO_ALG_TYPE_MASK;
+       type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
        type |= CRYPTO_ALG_TYPE_BLKCIPHER;
-       mask |= CRYPTO_ALG_TYPE_MASK;
+       mask |= CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC;
 
        return __crypto_blkcipher_cast(crypto_alloc_base(alg_name, type, mask));
 }
@@ -447,9 +675,9 @@ static inline void crypto_free_blkcipher(struct crypto_blkcipher *tfm)
 
 static inline int crypto_has_blkcipher(const char *alg_name, u32 type, u32 mask)
 {
-       type &= ~CRYPTO_ALG_TYPE_MASK;
+       type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
        type |= CRYPTO_ALG_TYPE_BLKCIPHER;
-       mask |= CRYPTO_ALG_TYPE_MASK;
+       mask |= CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC;
 
        return crypto_has_alg(alg_name, type, mask);
 }
index a0cd2ce..6579068 100644 (file)
@@ -53,7 +53,7 @@ struct bus_type {
        const char              * name;
        struct module           * owner;
 
-       struct subsystem        subsys;
+       struct kset             subsys;
        struct kset             drivers;
        struct kset             devices;
        struct klist            klist_devices;
@@ -80,7 +80,6 @@ struct bus_type {
        int (*resume)(struct device * dev);
 
        unsigned int drivers_autoprobe:1;
-       unsigned int multithread_probe:1;
 };
 
 extern int __must_check bus_register(struct bus_type * bus);
@@ -179,7 +178,7 @@ struct class {
        const char              * name;
        struct module           * owner;
 
-       struct subsystem        subsys;
+       struct kset             subsys;
        struct list_head        children;
        struct list_head        devices;
        struct list_head        interfaces;
@@ -559,8 +558,8 @@ extern void device_shutdown(void);
 
 
 /* drivers/base/firmware.c */
-extern int __must_check firmware_register(struct subsystem *);
-extern void firmware_unregister(struct subsystem *);
+extern int __must_check firmware_register(struct kset *);
+extern void firmware_unregister(struct kset *);
 
 /* debugging and troubleshooting/diagnostic helpers. */
 extern const char *dev_driver_string(struct device *dev);
index c6310ae..f2d248f 100644 (file)
@@ -434,6 +434,7 @@ struct ethtool_ops {
 #define SUPPORTED_10000baseT_Full      (1 << 12)
 #define SUPPORTED_Pause                        (1 << 13)
 #define SUPPORTED_Asym_Pause           (1 << 14)
+#define SUPPORTED_2500baseX_Full       (1 << 15)
 
 /* Indicates what features are advertised by the interface. */
 #define ADVERTISED_10baseT_Half                (1 << 0)
@@ -451,6 +452,7 @@ struct ethtool_ops {
 #define ADVERTISED_10000baseT_Full     (1 << 12)
 #define ADVERTISED_Pause               (1 << 13)
 #define ADVERTISED_Asym_Pause          (1 << 14)
+#define ADVERTISED_2500baseX_Full      (1 << 15)
 
 /* The following are all involved in forcing a particular link
  * mode for the device for setting things.  When getting the
index 095a9c9..7c0077f 100644 (file)
@@ -1416,7 +1416,7 @@ extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
 extern int vfs_statfs(struct dentry *, struct kstatfs *);
 
 /* /sys/fs */
-extern struct subsystem fs_subsys;
+extern struct kset fs_subsys;
 
 #define FLOCK_VERIFY_READ  1
 #define FLOCK_VERIFY_WRITE 2
index 2b217c7..265d178 100644 (file)
@@ -3,10 +3,11 @@
 
 struct gpio_keys_button {
        /* Configuration parameters */
-       int keycode;
+       int code;               /* input event code (KEY_*, SW_*) */
        int gpio;
        int active_low;
        char *desc;
+       int type;               /* input event type (EV_KEY, EV_SW) */
 };
 
 struct gpio_keys_platform_data {
index bca8e2d..a515eb0 100644 (file)
@@ -44,8 +44,13 @@ static inline void *kmap(struct page *page)
 
 #define kunmap(page) do { (void) (page); } while (0)
 
-#define kmap_atomic(page, idx) \
-       ({ pagefault_disable(); page_address(page); })
+#include <asm/kmap_types.h>
+
+static inline void *kmap_atomic(struct page *page, enum km_type idx)
+{
+       pagefault_disable();
+       return page_address(page);
+}
 #define kmap_atomic_prot(page, idx, prot)      kmap_atomic(page, idx)
 
 #define kunmap_atomic(addr, idx)       do { pagefault_enable(); } while (0)
index debd715..9db3d45 100644 (file)
@@ -71,6 +71,7 @@ typedef struct {
          struct semaphore *semaphore;  /* Semaphore to sleep on. */
        } act;
 } hp_sdc_transaction;
+int __hp_sdc_enqueue_transaction(hp_sdc_transaction *this);
 int hp_sdc_enqueue_transaction(hp_sdc_transaction *this);
 int hp_sdc_dequeue_transaction(hp_sdc_transaction *this);
 
index 937da70..9ee0f80 100644 (file)
@@ -38,11 +38,14 @@ struct i2c_algo_bit_data {
        int  (*getscl) (void *data);
 
        /* local settings */
-       int udelay;             /* half-clock-cycle time in microsecs */
-                               /* i.e. clock is (500 / udelay) KHz */
+       int udelay;             /* half clock cycle time in us,
+                                  minimum 2 us for fast-mode I2C,
+                                  minimum 5 us for standard-mode I2C and SMBus,
+                                  maximum 50 us for SMBus */
        int timeout;            /* in jiffies */
 };
 
 int i2c_bit_add_bus(struct i2c_adapter *);
+int i2c_bit_add_numbered_bus(struct i2c_adapter *);
 
 #endif /* _LINUX_I2C_ALGO_BIT_H */
diff --git a/include/linux/i2c-gpio.h b/include/linux/i2c-gpio.h
new file mode 100644 (file)
index 0000000..c1bcb1f
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * i2c-gpio interface to platform code
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _LINUX_I2C_GPIO_H
+#define _LINUX_I2C_GPIO_H
+
+/**
+ * struct i2c_gpio_platform_data - Platform-dependent data for i2c-gpio
+ * @sda_pin: GPIO pin ID to use for SDA
+ * @scl_pin: GPIO pin ID to use for SCL
+ * @udelay: signal toggle delay. SCL frequency is (500 / udelay) kHz
+ * @timeout: clock stretching timeout in jiffies. If the slave keeps
+ *     SCL low for longer than this, the transfer will time out.
+ * @sda_is_open_drain: SDA is configured as open drain, i.e. the pin
+ *     isn't actively driven high when setting the output value high.
+ *     gpio_get_value() must return the actual pin state even if the
+ *     pin is configured as an output.
+ * @scl_is_open_drain: SCL is set up as open drain. Same requirements
+ *     as for sda_is_open_drain apply.
+ * @scl_is_output_only: SCL output drivers cannot be turned off.
+ */
+struct i2c_gpio_platform_data {
+       unsigned int    sda_pin;
+       unsigned int    scl_pin;
+       int             udelay;
+       int             timeout;
+       unsigned int    sda_is_open_drain:1;
+       unsigned int    scl_is_open_drain:1;
+       unsigned int    scl_is_output_only:1;
+};
+
+#endif /* _LINUX_I2C_GPIO_H */
index 9c21dc7..0e8da68 100644 (file)
 /* --- MCP107 adapter */
 #define I2C_HW_MPC107          0x0d0000
 
-/* --- Marvell mv64xxx i2c adapter */
+/* --- Embedded adapters */
 #define I2C_HW_MV64XXX         0x190000
+#define I2C_HW_BLACKFIN                0x190001 /* ADI Blackfin I2C TWI driver */
 
 /* --- Miscellaneous adapters */
 #define I2C_HW_SAA7146         0x060000 /* SAA7146 video decoder bus */
index 9428092..cae7d61 100644 (file)
 #include <linux/sched.h>       /* for completion */
 #include <linux/mutex.h>
 
-/* --- For i2c-isa ---------------------------------------------------- */
-
-extern void i2c_adapter_dev_release(struct device *dev);
-extern struct device_driver i2c_adapter_driver;
-extern struct class i2c_adapter_class;
 extern struct bus_type i2c_bus_type;
 
 /* --- General options ------------------------------------------------        */
@@ -87,6 +82,9 @@ extern s32 i2c_smbus_write_byte_data(struct i2c_client * client,
 extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command);
 extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
                                      u8 command, u16 value);
+/* Returns the number of read bytes */
+extern s32 i2c_smbus_read_block_data(struct i2c_client *client,
+                                    u8 command, u8 *values);
 extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
                                      u8 command, u8 length,
                                      const u8 *values);
@@ -114,7 +112,7 @@ struct i2c_driver {
         * can be used by the driver to test if the bus meets its conditions
         * & seek for the presence of the chip(s) it supports. If found, it
         * registers the client(s) that are on the bus to the i2c admin. via
-        * i2c_attach_client.
+        * i2c_attach_client.  (LEGACY I2C DRIVERS ONLY)
         */
        int (*attach_adapter)(struct i2c_adapter *);
        int (*detach_adapter)(struct i2c_adapter *);
@@ -122,10 +120,17 @@ struct i2c_driver {
        /* tells the driver that a client is about to be deleted & gives it
         * the chance to remove its private data. Also, if the client struct
         * has been dynamically allocated by the driver in the function above,
-        * it must be freed here.
+        * it must be freed here.  (LEGACY I2C DRIVERS ONLY)
         */
        int (*detach_client)(struct i2c_client *);
 
+       /* Standard driver model interfaces, for "new style" i2c drivers.
+        * With the driver model, device enumeration is NEVER done by drivers;
+        * it's done by infrastructure.  (NEW STYLE DRIVERS ONLY)
+        */
+       int (*probe)(struct i2c_client *);
+       int (*remove)(struct i2c_client *);
+
        /* driver model interfaces that don't relate to enumeration  */
        void (*shutdown)(struct i2c_client *);
        int (*suspend)(struct i2c_client *, pm_message_t mesg);
@@ -141,25 +146,34 @@ struct i2c_driver {
 };
 #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
 
-#define I2C_NAME_SIZE  50
+#define I2C_NAME_SIZE  20
 
-/*
- * i2c_client identifies a single device (i.e. chip) that is connected to an
- * i2c bus. The behaviour is defined by the routines of the driver. This
- * function is mainly used for lookup & other admin. functions.
+/**
+ * struct i2c_client - represent an I2C slave device
+ * @addr: Address used on the I2C bus connected to the parent adapter.
+ * @name: Indicates the type of the device, usually a chip name that's
+ *     generic enough to hide second-sourcing and compatible revisions.
+ * @dev: Driver model device node for the slave.
+ * @driver_name: Identifies new-style driver used with this device; also
+ *     used as the module name for hotplug/coldplug modprobe support.
+ *
+ * An i2c_client identifies a single device (i.e. chip) connected to an
+ * i2c bus. The behaviour is defined by the routines of the driver.
  */
 struct i2c_client {
-       unsigned int flags;             /* div., see below              */
+       unsigned short flags;           /* div., see below              */
        unsigned short addr;            /* chip address - NOTE: 7bit    */
                                        /* addresses are stored in the  */
                                        /* _LOWER_ 7 bits               */
+       char name[I2C_NAME_SIZE];
        struct i2c_adapter *adapter;    /* the adapter we sit on        */
        struct i2c_driver *driver;      /* and our access routines      */
        int usage_count;                /* How many accesses currently  */
                                        /* to the client                */
        struct device dev;              /* the device structure         */
+       int irq;                        /* irq issued by device (or -1) */
+       char driver_name[KOBJ_NAME_LEN];
        struct list_head list;
-       char name[I2C_NAME_SIZE];
        struct completion released;
 };
 #define to_i2c_client(d) container_of(d, struct i2c_client, dev)
@@ -179,6 +193,76 @@ static inline void i2c_set_clientdata (struct i2c_client *dev, void *data)
        dev_set_drvdata (&dev->dev, data);
 }
 
+/**
+ * struct i2c_board_info - template for device creation
+ * @driver_name: identifies the driver to be bound to the device
+ * @type: optional chip type information, to initialize i2c_client.name
+ * @flags: to initialize i2c_client.flags
+ * @addr: stored in i2c_client.addr
+ * @platform_data: stored in i2c_client.dev.platform_data
+ * @irq: stored in i2c_client.irq
+
+ * I2C doesn't actually support hardware probing, although controllers and
+ * devices may be able to use I2C_SMBUS_QUICK to tell whether or not there's
+ * a device at a given address.  Drivers commonly need more information than
+ * that, such as chip type, configuration, associated IRQ, and so on.
+ *
+ * i2c_board_info is used to build tables of information listing I2C devices
+ * that are present.  This information is used to grow the driver model tree
+ * for "new style" I2C drivers.  For mainboards this is done statically using
+ * i2c_register_board_info(), where @bus_num represents an adapter that isn't
+ * yet available.  For add-on boards, i2c_new_device() does this dynamically
+ * with the adapter already known.
+ */
+struct i2c_board_info {
+       char            driver_name[KOBJ_NAME_LEN];
+       char            type[I2C_NAME_SIZE];
+       unsigned short  flags;
+       unsigned short  addr;
+       void            *platform_data;
+       int             irq;
+};
+
+/**
+ * I2C_BOARD_INFO - macro used to list an i2c device and its driver
+ * @driver: identifies the driver to use with the device
+ * @dev_addr: the device's address on the bus.
+ *
+ * This macro initializes essential fields of a struct i2c_board_info,
+ * declaring what has been provided on a particular board.  Optional
+ * fields (such as the chip type, its associated irq, or device-specific
+ * platform_data) are provided using conventional syntax.
+ */
+#define I2C_BOARD_INFO(driver,dev_addr) \
+       .driver_name = (driver), .addr = (dev_addr)
+
+
+/* Add-on boards should register/unregister their devices; e.g. a board
+ * with integrated I2C, a config eeprom, sensors, and a codec that's
+ * used in conjunction with the primary hardware.
+ */
+extern struct i2c_client *
+i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info);
+
+/* If you don't know the exact address of an I2C device, use this variant
+ * instead, which can probe for device presence in a list of possible
+ * addresses.
+ */
+extern struct i2c_client *
+i2c_new_probed_device(struct i2c_adapter *adap,
+                     struct i2c_board_info *info,
+                     unsigned short const *addr_list);
+
+extern void i2c_unregister_device(struct i2c_client *);
+
+/* Mainboard arch_initcall() code should register all its I2C devices.
+ * This is done at arch_initcall time, before declaring any i2c adapters.
+ * Modules for add-on boards must use other calls.
+ */
+extern int
+i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned n);
+
+
 /*
  * The following structs are for those who like to implement new bus drivers:
  * i2c_algorithm is the interface to a class of hardware solutions which can
@@ -228,17 +312,14 @@ struct i2c_adapter {
        int timeout;
        int retries;
        struct device dev;              /* the adapter device */
-       struct class_device class_dev;  /* the class device */
 
        int nr;
        struct list_head clients;
        struct list_head list;
-       char name[I2C_NAME_SIZE];
+       char name[48];
        struct completion dev_released;
-       struct completion class_dev_released;
 };
-#define dev_to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
-#define class_dev_to_i2c_adapter(d) container_of(d, struct i2c_adapter, class_dev)
+#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
 
 static inline void *i2c_get_adapdata (struct i2c_adapter *dev)
 {
@@ -290,9 +371,10 @@ struct i2c_client_address_data {
  */
 extern int i2c_add_adapter(struct i2c_adapter *);
 extern int i2c_del_adapter(struct i2c_adapter *);
+extern int i2c_add_numbered_adapter(struct i2c_adapter *);
 
 extern int i2c_register_driver(struct module *, struct i2c_driver *);
-extern int i2c_del_driver(struct i2c_driver *);
+extern void i2c_del_driver(struct i2c_driver *);
 
 static inline int i2c_add_driver(struct i2c_driver *driver)
 {
@@ -365,6 +447,7 @@ struct i2c_msg {
 #define I2C_M_REV_DIR_ADDR     0x2000
 #define I2C_M_IGNORE_NAK       0x1000
 #define I2C_M_NO_RD_ACK                0x0800
+#define I2C_M_RECV_LEN         0x0400 /* length will be first received byte */
        __u16 len;              /* msg length                           */
        __u8 *buf;              /* pointer to msg data                  */
 };
index d3bbc71..418dfb5 100644 (file)
@@ -613,7 +613,6 @@ typedef struct ide_drive_s {
 
         u8     quirk_list;     /* considered quirky, set for a specific host */
         u8     init_speed;     /* transfer rate set at boot */
-        u8     pio_speed;      /* unused by core, used by some drivers for fallback from DMA */
         u8     current_speed;  /* current transfer rate set */
        u8      desired_speed;  /* desired transfer rate set */
         u8     dn;             /* now wide spread use */
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
new file mode 100644 (file)
index 0000000..ecd61e8
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ * IEEE 802.11 defines
+ *
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <jkmaline@cc.hut.fi>
+ * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright (c) 2005, Devicescape Software, Inc.
+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef IEEE80211_H
+#define IEEE80211_H
+
+#include <linux/types.h>
+
+#define FCS_LEN 4
+
+#define IEEE80211_FCTL_VERS            0x0003
+#define IEEE80211_FCTL_FTYPE           0x000c
+#define IEEE80211_FCTL_STYPE           0x00f0
+#define IEEE80211_FCTL_TODS            0x0100
+#define IEEE80211_FCTL_FROMDS          0x0200
+#define IEEE80211_FCTL_MOREFRAGS       0x0400
+#define IEEE80211_FCTL_RETRY           0x0800
+#define IEEE80211_FCTL_PM              0x1000
+#define IEEE80211_FCTL_MOREDATA                0x2000
+#define IEEE80211_FCTL_PROTECTED       0x4000
+#define IEEE80211_FCTL_ORDER           0x8000
+
+#define IEEE80211_SCTL_FRAG            0x000F
+#define IEEE80211_SCTL_SEQ             0xFFF0
+
+#define IEEE80211_FTYPE_MGMT           0x0000
+#define IEEE80211_FTYPE_CTL            0x0004
+#define IEEE80211_FTYPE_DATA           0x0008
+
+/* management */
+#define IEEE80211_STYPE_ASSOC_REQ      0x0000
+#define IEEE80211_STYPE_ASSOC_RESP     0x0010
+#define IEEE80211_STYPE_REASSOC_REQ    0x0020
+#define IEEE80211_STYPE_REASSOC_RESP   0x0030
+#define IEEE80211_STYPE_PROBE_REQ      0x0040
+#define IEEE80211_STYPE_PROBE_RESP     0x0050
+#define IEEE80211_STYPE_BEACON         0x0080
+#define IEEE80211_STYPE_ATIM           0x0090
+#define IEEE80211_STYPE_DISASSOC       0x00A0
+#define IEEE80211_STYPE_AUTH           0x00B0
+#define IEEE80211_STYPE_DEAUTH         0x00C0
+#define IEEE80211_STYPE_ACTION         0x00D0
+
+/* control */
+#define IEEE80211_STYPE_PSPOLL         0x00A0
+#define IEEE80211_STYPE_RTS            0x00B0
+#define IEEE80211_STYPE_CTS            0x00C0
+#define IEEE80211_STYPE_ACK            0x00D0
+#define IEEE80211_STYPE_CFEND          0x00E0
+#define IEEE80211_STYPE_CFENDACK       0x00F0
+
+/* data */
+#define IEEE80211_STYPE_DATA                   0x0000
+#define IEEE80211_STYPE_DATA_CFACK             0x0010
+#define IEEE80211_STYPE_DATA_CFPOLL            0x0020
+#define IEEE80211_STYPE_DATA_CFACKPOLL         0x0030
+#define IEEE80211_STYPE_NULLFUNC               0x0040
+#define IEEE80211_STYPE_CFACK                  0x0050
+#define IEEE80211_STYPE_CFPOLL                 0x0060
+#define IEEE80211_STYPE_CFACKPOLL              0x0070
+#define IEEE80211_STYPE_QOS_DATA               0x0080
+#define IEEE80211_STYPE_QOS_DATA_CFACK         0x0090
+#define IEEE80211_STYPE_QOS_DATA_CFPOLL                0x00A0
+#define IEEE80211_STYPE_QOS_DATA_CFACKPOLL     0x00B0
+#define IEEE80211_STYPE_QOS_NULLFUNC           0x00C0
+#define IEEE80211_STYPE_QOS_CFACK              0x00D0
+#define IEEE80211_STYPE_QOS_CFPOLL             0x00E0
+#define IEEE80211_STYPE_QOS_CFACKPOLL          0x00F0
+
+
+/* miscellaneous IEEE 802.11 constants */
+#define IEEE80211_MAX_FRAG_THRESHOLD   2346
+#define IEEE80211_MAX_RTS_THRESHOLD    2347
+#define IEEE80211_MAX_AID              2007
+#define IEEE80211_MAX_TIM_LEN          251
+#define IEEE80211_MAX_DATA_LEN         2304
+/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
+   6.2.1.1.2.
+
+   The figure in section 7.1.2 suggests a body size of up to 2312
+   bytes is allowed, which is a bit confusing, I suspect this
+   represents the 2304 bytes of real data, plus a possible 8 bytes of
+   WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
+
+#define IEEE80211_MAX_SSID_LEN         32
+
+struct ieee80211_hdr {
+       __le16 frame_control;
+       __le16 duration_id;
+       u8 addr1[6];
+       u8 addr2[6];
+       u8 addr3[6];
+       __le16 seq_ctrl;
+       u8 addr4[6];
+} __attribute__ ((packed));
+
+
+struct ieee80211_mgmt {
+       __le16 frame_control;
+       __le16 duration;
+       u8 da[6];
+       u8 sa[6];
+       u8 bssid[6];
+       __le16 seq_ctrl;
+       union {
+               struct {
+                       __le16 auth_alg;
+                       __le16 auth_transaction;
+                       __le16 status_code;
+                       /* possibly followed by Challenge text */
+                       u8 variable[0];
+               } __attribute__ ((packed)) auth;
+               struct {
+                       __le16 reason_code;
+               } __attribute__ ((packed)) deauth;
+               struct {
+                       __le16 capab_info;
+                       __le16 listen_interval;
+                       /* followed by SSID and Supported rates */
+                       u8 variable[0];
+               } __attribute__ ((packed)) assoc_req;
+               struct {
+                       __le16 capab_info;
+                       __le16 status_code;
+                       __le16 aid;
+                       /* followed by Supported rates */
+                       u8 variable[0];
+               } __attribute__ ((packed)) assoc_resp, reassoc_resp;
+               struct {
+                       __le16 capab_info;
+                       __le16 listen_interval;
+                       u8 current_ap[6];
+                       /* followed by SSID and Supported rates */
+                       u8 variable[0];
+               } __attribute__ ((packed)) reassoc_req;
+               struct {
+                       __le16 reason_code;
+               } __attribute__ ((packed)) disassoc;
+               struct {
+                       __le64 timestamp;
+                       __le16 beacon_int;
+                       __le16 capab_info;
+                       /* followed by some of SSID, Supported rates,
+                        * FH Params, DS Params, CF Params, IBSS Params, TIM */
+                       u8 variable[0];
+               } __attribute__ ((packed)) beacon;
+               struct {
+                       /* only variable items: SSID, Supported rates */
+                       u8 variable[0];
+               } __attribute__ ((packed)) probe_req;
+               struct {
+                       __le64 timestamp;
+                       __le16 beacon_int;
+                       __le16 capab_info;
+                       /* followed by some of SSID, Supported rates,
+                        * FH Params, DS Params, CF Params, IBSS Params */
+                       u8 variable[0];
+               } __attribute__ ((packed)) probe_resp;
+               struct {
+                       u8 category;
+                       union {
+                               struct {
+                                       u8 action_code;
+                                       u8 dialog_token;
+                                       u8 status_code;
+                                       u8 variable[0];
+                               } __attribute__ ((packed)) wme_action;
+                               struct{
+                                       u8 action_code;
+                                       u8 element_id;
+                                       u8 length;
+                                       u8 switch_mode;
+                                       u8 new_chan;
+                                       u8 switch_count;
+                               } __attribute__((packed)) chan_switch;
+                       } u;
+               } __attribute__ ((packed)) action;
+       } u;
+} __attribute__ ((packed));
+
+
+/* Control frames */
+struct ieee80211_rts {
+       __le16 frame_control;
+       __le16 duration;
+       u8 ra[6];
+       u8 ta[6];
+} __attribute__ ((packed));
+
+struct ieee80211_cts {
+       __le16 frame_control;
+       __le16 duration;
+       u8 ra[6];
+} __attribute__ ((packed));
+
+
+/* Authentication algorithms */
+#define WLAN_AUTH_OPEN 0
+#define WLAN_AUTH_SHARED_KEY 1
+#define WLAN_AUTH_FAST_BSS_TRANSITION 2
+#define WLAN_AUTH_LEAP 128
+
+#define WLAN_AUTH_CHALLENGE_LEN 128
+
+#define WLAN_CAPABILITY_ESS            (1<<0)
+#define WLAN_CAPABILITY_IBSS           (1<<1)
+#define WLAN_CAPABILITY_CF_POLLABLE    (1<<2)
+#define WLAN_CAPABILITY_CF_POLL_REQUEST        (1<<3)
+#define WLAN_CAPABILITY_PRIVACY                (1<<4)
+#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5)
+#define WLAN_CAPABILITY_PBCC           (1<<6)
+#define WLAN_CAPABILITY_CHANNEL_AGILITY        (1<<7)
+/* 802.11h */
+#define WLAN_CAPABILITY_SPECTRUM_MGMT  (1<<8)
+#define WLAN_CAPABILITY_QOS            (1<<9)
+#define WLAN_CAPABILITY_SHORT_SLOT_TIME        (1<<10)
+#define WLAN_CAPABILITY_DSSS_OFDM      (1<<13)
+
+/* Status codes */
+enum ieee80211_statuscode {
+       WLAN_STATUS_SUCCESS = 0,
+       WLAN_STATUS_UNSPECIFIED_FAILURE = 1,
+       WLAN_STATUS_CAPS_UNSUPPORTED = 10,
+       WLAN_STATUS_REASSOC_NO_ASSOC = 11,
+       WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12,
+       WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13,
+       WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14,
+       WLAN_STATUS_CHALLENGE_FAIL = 15,
+       WLAN_STATUS_AUTH_TIMEOUT = 16,
+       WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17,
+       WLAN_STATUS_ASSOC_DENIED_RATES = 18,
+       /* 802.11b */
+       WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19,
+       WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20,
+       WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21,
+       /* 802.11h */
+       WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22,
+       WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23,
+       WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24,
+       /* 802.11g */
+       WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25,
+       WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26,
+       /* 802.11i */
+       WLAN_STATUS_INVALID_IE = 40,
+       WLAN_STATUS_INVALID_GROUP_CIPHER = 41,
+       WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42,
+       WLAN_STATUS_INVALID_AKMP = 43,
+       WLAN_STATUS_UNSUPP_RSN_VERSION = 44,
+       WLAN_STATUS_INVALID_RSN_IE_CAP = 45,
+       WLAN_STATUS_CIPHER_SUITE_REJECTED = 46,
+};
+
+
+/* Reason codes */
+enum ieee80211_reasoncode {
+       WLAN_REASON_UNSPECIFIED = 1,
+       WLAN_REASON_PREV_AUTH_NOT_VALID = 2,
+       WLAN_REASON_DEAUTH_LEAVING = 3,
+       WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4,
+       WLAN_REASON_DISASSOC_AP_BUSY = 5,
+       WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6,
+       WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7,
+       WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8,
+       WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9,
+       /* 802.11h */
+       WLAN_REASON_DISASSOC_BAD_POWER = 10,
+       WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11,
+       /* 802.11i */
+       WLAN_REASON_INVALID_IE = 13,
+       WLAN_REASON_MIC_FAILURE = 14,
+       WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15,
+       WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16,
+       WLAN_REASON_IE_DIFFERENT = 17,
+       WLAN_REASON_INVALID_GROUP_CIPHER = 18,
+       WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19,
+       WLAN_REASON_INVALID_AKMP = 20,
+       WLAN_REASON_UNSUPP_RSN_VERSION = 21,
+       WLAN_REASON_INVALID_RSN_IE_CAP = 22,
+       WLAN_REASON_IEEE8021X_FAILED = 23,
+       WLAN_REASON_CIPHER_SUITE_REJECTED = 24,
+};
+
+
+/* Information Element IDs */
+enum ieee80211_eid {
+       WLAN_EID_SSID = 0,
+       WLAN_EID_SUPP_RATES = 1,
+       WLAN_EID_FH_PARAMS = 2,
+       WLAN_EID_DS_PARAMS = 3,
+       WLAN_EID_CF_PARAMS = 4,
+       WLAN_EID_TIM = 5,
+       WLAN_EID_IBSS_PARAMS = 6,
+       WLAN_EID_CHALLENGE = 16,
+       /* 802.11d */
+       WLAN_EID_COUNTRY = 7,
+       WLAN_EID_HP_PARAMS = 8,
+       WLAN_EID_HP_TABLE = 9,
+       WLAN_EID_REQUEST = 10,
+       /* 802.11h */
+       WLAN_EID_PWR_CONSTRAINT = 32,
+       WLAN_EID_PWR_CAPABILITY = 33,
+       WLAN_EID_TPC_REQUEST = 34,
+       WLAN_EID_TPC_REPORT = 35,
+       WLAN_EID_SUPPORTED_CHANNELS = 36,
+       WLAN_EID_CHANNEL_SWITCH = 37,
+       WLAN_EID_MEASURE_REQUEST = 38,
+       WLAN_EID_MEASURE_REPORT = 39,
+       WLAN_EID_QUIET = 40,
+       WLAN_EID_IBSS_DFS = 41,
+       /* 802.11g */
+       WLAN_EID_ERP_INFO = 42,
+       WLAN_EID_EXT_SUPP_RATES = 50,
+       /* 802.11i */
+       WLAN_EID_RSN = 48,
+       WLAN_EID_WPA = 221,
+       WLAN_EID_GENERIC = 221,
+       WLAN_EID_VENDOR_SPECIFIC = 221,
+       WLAN_EID_QOS_PARAMETER = 222
+};
+
+/* cipher suite selectors */
+#define WLAN_CIPHER_SUITE_USE_GROUP    0x000FAC00
+#define WLAN_CIPHER_SUITE_WEP40                0x000FAC01
+#define WLAN_CIPHER_SUITE_TKIP         0x000FAC02
+/* reserved:                           0x000FAC03 */
+#define WLAN_CIPHER_SUITE_CCMP         0x000FAC04
+#define WLAN_CIPHER_SUITE_WEP104       0x000FAC05
+
+#define WLAN_MAX_KEY_LEN               32
+
+#endif /* IEEE80211_H */
diff --git a/include/linux/input-polldev.h b/include/linux/input-polldev.h
new file mode 100644 (file)
index 0000000..597a007
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef _INPUT_POLLDEV_H
+#define _INPUT_POLLDEV_H
+
+/*
+ * Copyright (c) 2007 Dmitry Torokhov
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/input.h>
+#include <linux/workqueue.h>
+
+/**
+ * struct input_polled_dev - simple polled input device
+ * @private: private driver data
+ * @flush: driver-supplied method that flushes device's state upon
+ *     opening (optional)
+ * @poll: driver-supplied method that polls the device and posts
+ *     input events (mandatory).
+ * @poll_interval: specifies how often the poll() method shoudl be called.
+ * @input: input device structire associated with the polled device.
+ *     Must be properly initialized by the driver (id, name, phys, bits).
+ *
+ * Polled input device provides a skeleton for supporting simple input
+ * devices that do not raise interrupts but have to be periodically
+ * scanned or polled to detect changes in their state.
+ */
+struct input_polled_dev {
+       void *private;
+
+       void (*flush)(struct input_polled_dev *dev);
+       void (*poll)(struct input_polled_dev *dev);
+       unsigned int poll_interval; /* msec */
+
+       struct input_dev *input;
+       struct delayed_work work;
+};
+
+struct input_polled_dev *input_allocate_polled_device(void);
+void input_free_polled_device(struct input_polled_dev *dev);
+int input_register_polled_device(struct input_polled_dev *dev);
+void input_unregister_polled_device(struct input_polled_dev *dev);
+
+#endif
index bde65c8..439954d 100644 (file)
@@ -506,6 +506,7 @@ struct input_absinfo {
 #define KEY_VOICEMAIL          0x1ac
 #define KEY_ADDRESSBOOK                0x1ad
 #define KEY_MESSENGER          0x1ae
+#define KEY_DISPLAYTOGGLE      0x1af   /* Turn display (LCD) on and off */
 
 #define KEY_DEL_EOL            0x1c0
 #define KEY_DEL_EOS            0x1c1
@@ -676,6 +677,7 @@ struct input_absinfo {
 #define BUS_I2C                        0x18
 #define BUS_HOST               0x19
 #define BUS_GSC                        0x1A
+#define BUS_ATARI              0x1B
 
 /*
  * Values describing the status of a force-feedback effect
@@ -913,33 +915,6 @@ struct ff_effect {
 #define BIT(x) (1UL<<((x)%BITS_PER_LONG))
 #define LONG(x) ((x)/BITS_PER_LONG)
 
-#define INPUT_KEYCODE(dev, scancode) ((dev->keycodesize == 1) ? ((u8*)dev->keycode)[scancode] : \
-       ((dev->keycodesize == 2) ? ((u16*)dev->keycode)[scancode] : (((u32*)dev->keycode)[scancode])))
-
-#define SET_INPUT_KEYCODE(dev, scancode, val)                  \
-               ({      unsigned __old;                         \
-               switch (dev->keycodesize) {                     \
-                       case 1: {                               \
-                               u8 *k = (u8 *)dev->keycode;     \
-                               __old = k[scancode];            \
-                               k[scancode] = val;              \
-                               break;                          \
-                       }                                       \
-                       case 2: {                               \
-                               u16 *k = (u16 *)dev->keycode;   \
-                               __old = k[scancode];            \
-                               k[scancode] = val;              \
-                               break;                          \
-                       }                                       \
-                       default: {                              \
-                               u32 *k = (u32 *)dev->keycode;   \
-                               __old = k[scancode];            \
-                               k[scancode] = val;              \
-                               break;                          \
-                       }                                       \
-               }                                               \
-               __old; })
-
 struct input_dev {
 
        void *private;
@@ -962,6 +937,8 @@ struct input_dev {
        unsigned int keycodemax;
        unsigned int keycodesize;
        void *keycode;
+       int (*setkeycode)(struct input_dev *dev, int scancode, int keycode);
+       int (*getkeycode)(struct input_dev *dev, int scancode, int *keycode);
 
        struct ff_device *ff;
 
@@ -996,6 +973,9 @@ struct input_dev {
        unsigned int users;
 
        struct class_device cdev;
+       union {                 /* temporarily so while we switching to struct device */
+               struct device *parent;
+       } dev;
 
        struct list_head        h_list;
        struct list_head        node;
@@ -1074,7 +1054,7 @@ struct input_handler {
        void *private;
 
        void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
-       struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
+       int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
        void (*disconnect)(struct input_handle *handle);
        void (*start)(struct input_handle *handle);
 
@@ -1104,7 +1084,7 @@ struct input_handle {
 };
 
 #define to_dev(n) container_of(n,struct input_dev,node)
-#define to_handler(n) container_of(n,struct input_handler,node);
+#define to_handler(n) container_of(n,struct input_handler,node)
 #define to_handle(n) container_of(n,struct input_handle,d_node)
 #define to_handle_h(n) container_of(n,struct input_handle,h_node)
 
@@ -1121,12 +1101,25 @@ static inline void input_put_device(struct input_dev *dev)
        class_device_put(&dev->cdev);
 }
 
+static inline void *input_get_drvdata(struct input_dev *dev)
+{
+       return dev->private;
+}
+
+static inline void input_set_drvdata(struct input_dev *dev, void *data)
+{
+       dev->private = data;
+}
+
 int input_register_device(struct input_dev *);
 void input_unregister_device(struct input_dev *);
 
 int input_register_handler(struct input_handler *);
 void input_unregister_handler(struct input_handler *);
 
+int input_register_handle(struct input_handle *);
+void input_unregister_handle(struct input_handle *);
+
 int input_grab_device(struct input_handle *);
 void input_release_device(struct input_handle *);
 
@@ -1168,6 +1161,8 @@ static inline void input_sync(struct input_dev *dev)
        input_event(dev, EV_SYN, SYN_REPORT, 0);
 }
 
+void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code);
+
 static inline void input_set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat)
 {
        dev->absmin[axis] = min;
index 838cf5a..0319f66 100644 (file)
@@ -185,10 +185,14 @@ static inline int disable_irq_wake(unsigned int irq)
  * validator need to define the methods below in their asm/irq.h
  * files, under an #ifdef CONFIG_LOCKDEP section.
  */
-# ifndef CONFIG_LOCKDEP
+#ifndef CONFIG_LOCKDEP
 #  define disable_irq_nosync_lockdep(irq)      disable_irq_nosync(irq)
+#  define disable_irq_nosync_lockdep_irqsave(irq, flags) \
+                                               disable_irq_nosync(irq)
 #  define disable_irq_lockdep(irq)             disable_irq(irq)
 #  define enable_irq_lockdep(irq)              enable_irq(irq)
+#  define enable_irq_lockdep_irqrestore(irq, flags) \
+                                               enable_irq(irq)
 # endif
 
 #endif /* CONFIG_GENERIC_HARDIRQS */
index eb0e63e..c288e41 100644 (file)
@@ -124,7 +124,6 @@ struct kset_uevent_ops {
 };
 
 struct kset {
-       struct subsystem        * subsys;
        struct kobj_type        * ktype;
        struct list_head        list;
        spinlock_t              list_lock;
@@ -171,32 +170,23 @@ extern struct kobject * kset_find_obj(struct kset *, const char *);
 #define set_kset_name(str)     .kset = { .kobj = { .name = str } }
 
 
-
-struct subsystem {
-       struct kset             kset;
-};
-
 #define decl_subsys(_name,_type,_uevent_ops) \
-struct subsystem _name##_subsys = { \
-       .kset = { \
-               .kobj = { .name = __stringify(_name) }, \
-               .ktype = _type, \
-               .uevent_ops =_uevent_ops, \
-       } \
+struct kset _name##_subsys = { \
+       .kobj = { .name = __stringify(_name) }, \
+       .ktype = _type, \
+       .uevent_ops =_uevent_ops, \
 }
 #define decl_subsys_name(_varname,_name,_type,_uevent_ops) \
-struct subsystem _varname##_subsys = { \
-       .kset = { \
-               .kobj = { .name = __stringify(_name) }, \
-               .ktype = _type, \
-               .uevent_ops =_uevent_ops, \
-       } \
+struct kset _varname##_subsys = { \
+       .kobj = { .name = __stringify(_name) }, \
+       .ktype = _type, \
+       .uevent_ops =_uevent_ops, \
 }
 
 /* The global /sys/kernel/ subsystem for people to chain off of */
-extern struct subsystem kernel_subsys;
+extern struct kset kernel_subsys;
 /* The global /sys/hypervisor/ subsystem  */
-extern struct subsystem hypervisor_subsys;
+extern struct kset hypervisor_subsys;
 
 /**
  * Helpers for setting the kset of registered objects.
@@ -214,7 +204,7 @@ extern struct subsystem hypervisor_subsys;
  */
 
 #define kobj_set_kset_s(obj,subsys) \
-       (obj)->kobj.kset = &(subsys).kset
+       (obj)->kobj.kset = &(subsys)
 
 /**
  *     kset_set_kset_s(obj,subsys) - set kset for embedded kset.
@@ -228,7 +218,7 @@ extern struct subsystem hypervisor_subsys;
  */
 
 #define kset_set_kset_s(obj,subsys) \
-       (obj)->kset.kobj.kset = &(subsys).kset
+       (obj)->kset.kobj.kset = &(subsys)
 
 /**
  *     subsys_set_kset(obj,subsys) - set kset for subsystem
@@ -241,29 +231,31 @@ extern struct subsystem hypervisor_subsys;
  */
 
 #define subsys_set_kset(obj,_subsys) \
-       (obj)->subsys.kset.kobj.kset = &(_subsys).kset
+       (obj)->subsys.kobj.kset = &(_subsys)
 
-extern void subsystem_init(struct subsystem *);
-extern int __must_check subsystem_register(struct subsystem *);
-extern void subsystem_unregister(struct subsystem *);
+extern void subsystem_init(struct kset *);
+extern int __must_check subsystem_register(struct kset *);
+extern void subsystem_unregister(struct kset *);
 
-static inline struct subsystem * subsys_get(struct subsystem * s)
+static inline struct kset *subsys_get(struct kset *s)
 {
-       return s ? container_of(kset_get(&s->kset),struct subsystem,kset) : NULL;
+       if (s)
+               return kset_get(s);
+       return NULL;
 }
 
-static inline void subsys_put(struct subsystem * s)
+static inline void subsys_put(struct kset *s)
 {
-       kset_put(&s->kset);
+       kset_put(s);
 }
 
 struct subsys_attribute {
        struct attribute attr;
-       ssize_t (*show)(struct subsystem *, char *);
-       ssize_t (*store)(struct subsystem *, const char *, size_t); 
+       ssize_t (*show)(struct kset *, char *);
+       ssize_t (*store)(struct kset *, const char *, size_t);
 };
 
-extern int __must_check subsys_create_file(struct subsystem * ,
+extern int __must_check subsys_create_file(struct kset *,
                                        struct subsys_attribute *);
 
 #if defined(CONFIG_HOTPLUG)
index ac25b56..f6a81e0 100644 (file)
@@ -88,7 +88,7 @@ struct nlm_wait;
 /*
  * Memory chunk for NLM client RPC request.
  */
-#define NLMCLNT_OHSIZE         (sizeof(utsname()->nodename)+10)
+#define NLMCLNT_OHSIZE         ((__NEW_UTS_LEN) + 10u)
 struct nlm_rqst {
        unsigned int            a_flags;        /* initial RPC task flags */
        struct nlm_host *       a_host;         /* host handle */
index e45712a..badf702 100644 (file)
@@ -10,7 +10,7 @@
 #ifndef LINUX_MMC_CARD_H
 #define LINUX_MMC_CARD_H
 
-#include <linux/mmc/mmc.h>
+#include <linux/mmc/core.h>
 
 struct mmc_cid {
        unsigned int            manfid;
@@ -41,6 +41,7 @@ struct mmc_csd {
 
 struct mmc_ext_csd {
        unsigned int            hs_max_dtr;
+       unsigned int            sectors;
 };
 
 struct sd_scr {
@@ -60,18 +61,17 @@ struct mmc_host;
  * MMC device
  */
 struct mmc_card {
-       struct list_head        node;           /* node in hosts devices list */
        struct mmc_host         *host;          /* the host this device belongs to */
        struct device           dev;            /* the device */
        unsigned int            rca;            /* relative card address of device */
+       unsigned int            type;           /* card type */
+#define MMC_TYPE_MMC           0               /* MMC card */
+#define MMC_TYPE_SD            1               /* SD card */
        unsigned int            state;          /* (our) card state */
 #define MMC_STATE_PRESENT      (1<<0)          /* present in sysfs */
-#define MMC_STATE_DEAD         (1<<1)          /* device no longer in stack */
-#define MMC_STATE_BAD          (1<<2)          /* unrecognised device */
-#define MMC_STATE_SDCARD       (1<<3)          /* is an SD card */
-#define MMC_STATE_READONLY     (1<<4)          /* card is read-only */
-#define MMC_STATE_HIGHSPEED    (1<<5)          /* card is in high speed mode */
-#define MMC_STATE_BLOCKADDR    (1<<6)          /* card uses block-addressing */
+#define MMC_STATE_READONLY     (1<<1)          /* card is read-only */
+#define MMC_STATE_HIGHSPEED    (1<<2)          /* card is in high speed mode */
+#define MMC_STATE_BLOCKADDR    (1<<3)          /* card uses block-addressing */
        u32                     raw_cid[4];     /* raw card CID */
        u32                     raw_csd[4];     /* raw card CSD */
        u32                     raw_scr[2];     /* raw card SCR */
@@ -82,18 +82,15 @@ struct mmc_card {
        struct sd_switch_caps   sw_caps;        /* switch (CMD6) caps */
 };
 
+#define mmc_card_mmc(c)                ((c)->type == MMC_TYPE_MMC)
+#define mmc_card_sd(c)         ((c)->type == MMC_TYPE_SD)
+
 #define mmc_card_present(c)    ((c)->state & MMC_STATE_PRESENT)
-#define mmc_card_dead(c)       ((c)->state & MMC_STATE_DEAD)
-#define mmc_card_bad(c)                ((c)->state & MMC_STATE_BAD)
-#define mmc_card_sd(c)         ((c)->state & MMC_STATE_SDCARD)
 #define mmc_card_readonly(c)   ((c)->state & MMC_STATE_READONLY)
 #define mmc_card_highspeed(c)  ((c)->state & MMC_STATE_HIGHSPEED)
 #define mmc_card_blockaddr(c)  ((c)->state & MMC_STATE_BLOCKADDR)
 
 #define mmc_card_set_present(c)        ((c)->state |= MMC_STATE_PRESENT)
-#define mmc_card_set_dead(c)   ((c)->state |= MMC_STATE_DEAD)
-#define mmc_card_set_bad(c)    ((c)->state |= MMC_STATE_BAD)
-#define mmc_card_set_sd(c)     ((c)->state |= MMC_STATE_SDCARD)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
 #define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
 #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
@@ -119,11 +116,4 @@ struct mmc_driver {
 extern int mmc_register_driver(struct mmc_driver *);
 extern void mmc_unregister_driver(struct mmc_driver *);
 
-static inline int mmc_card_claim_host(struct mmc_card *card)
-{
-       return __mmc_claim_host(card->host, card);
-}
-
-#define mmc_card_release_host(c)       mmc_release_host((c)->host)
-
 #endif
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
new file mode 100644 (file)
index 0000000..04bbe12
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ *  linux/include/linux/mmc/core.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef LINUX_MMC_CORE_H
+#define LINUX_MMC_CORE_H
+
+#include <linux/interrupt.h>
+#include <linux/device.h>
+
+struct request;
+struct mmc_data;
+struct mmc_request;
+
+struct mmc_command {
+       u32                     opcode;
+       u32                     arg;
+       u32                     resp[4];
+       unsigned int            flags;          /* expected response type */
+#define MMC_RSP_PRESENT        (1 << 0)
+#define MMC_RSP_136    (1 << 1)                /* 136 bit response */
+#define MMC_RSP_CRC    (1 << 2)                /* expect valid crc */
+#define MMC_RSP_BUSY   (1 << 3)                /* card may send busy */
+#define MMC_RSP_OPCODE (1 << 4)                /* response contains opcode */
+#define MMC_CMD_MASK   (3 << 5)                /* command type */
+#define MMC_CMD_AC     (0 << 5)
+#define MMC_CMD_ADTC   (1 << 5)
+#define MMC_CMD_BC     (2 << 5)
+#define MMC_CMD_BCR    (3 << 5)
+
+/*
+ * These are the response types, and correspond to valid bit
+ * patterns of the above flags.  One additional valid pattern
+ * is all zeros, which means we don't expect a response.
+ */
+#define MMC_RSP_NONE   (0)
+#define MMC_RSP_R1     (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+#define MMC_RSP_R1B    (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY)
+#define MMC_RSP_R2     (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
+#define MMC_RSP_R3     (MMC_RSP_PRESENT)
+#define MMC_RSP_R6     (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+#define MMC_RSP_R7     (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+
+#define mmc_resp_type(cmd)     ((cmd)->flags & (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC|MMC_RSP_BUSY|MMC_RSP_OPCODE))
+
+/*
+ * These are the command types.
+ */
+#define mmc_cmd_type(cmd)      ((cmd)->flags & MMC_CMD_MASK)
+
+       unsigned int            retries;        /* max number of retries */
+       unsigned int            error;          /* command error */
+
+#define MMC_ERR_NONE   0
+#define MMC_ERR_TIMEOUT        1
+#define MMC_ERR_BADCRC 2
+#define MMC_ERR_FIFO   3
+#define MMC_ERR_FAILED 4
+#define MMC_ERR_INVALID        5
+
+       struct mmc_data         *data;          /* data segment associated with cmd */
+       struct mmc_request      *mrq;           /* associated request */
+};
+
+struct mmc_data {
+       unsigned int            timeout_ns;     /* data timeout (in ns, max 80ms) */
+       unsigned int            timeout_clks;   /* data timeout (in clocks) */
+       unsigned int            blksz;          /* data block size */
+       unsigned int            blocks;         /* number of blocks */
+       unsigned int            error;          /* data error */
+       unsigned int            flags;
+
+#define MMC_DATA_WRITE (1 << 8)
+#define MMC_DATA_READ  (1 << 9)
+#define MMC_DATA_STREAM        (1 << 10)
+#define MMC_DATA_MULTI (1 << 11)
+
+       unsigned int            bytes_xfered;
+
+       struct mmc_command      *stop;          /* stop command */
+       struct mmc_request      *mrq;           /* associated request */
+
+       unsigned int            sg_len;         /* size of scatter list */
+       struct scatterlist      *sg;            /* I/O scatter list */
+};
+
+struct mmc_request {
+       struct mmc_command      *cmd;
+       struct mmc_data         *data;
+       struct mmc_command      *stop;
+
+       void                    *done_data;     /* completion data */
+       void                    (*done)(struct mmc_request *);/* completion function */
+};
+
+struct mmc_host;
+struct mmc_card;
+
+extern int mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
+extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
+extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *,
+       struct mmc_command *, int);
+
+extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *, int);
+
+extern void mmc_claim_host(struct mmc_host *host);
+extern void mmc_release_host(struct mmc_host *host);
+
+#endif
index bfcef8a..b1350df 100644 (file)
 #ifndef LINUX_MMC_HOST_H
 #define LINUX_MMC_HOST_H
 
-#include <linux/mmc/mmc.h>
+#include <linux/mmc/core.h>
 
 struct mmc_ios {
        unsigned int    clock;                  /* clock rate */
        unsigned short  vdd;
 
-#define        MMC_VDD_150     0
-#define        MMC_VDD_155     1
-#define        MMC_VDD_160     2
-#define        MMC_VDD_165     3
-#define        MMC_VDD_170     4
-#define        MMC_VDD_180     5
-#define        MMC_VDD_190     6
-#define        MMC_VDD_200     7
-#define        MMC_VDD_210     8
-#define        MMC_VDD_220     9
-#define        MMC_VDD_230     10
-#define        MMC_VDD_240     11
-#define        MMC_VDD_250     12
-#define        MMC_VDD_260     13
-#define        MMC_VDD_270     14
-#define        MMC_VDD_280     15
-#define        MMC_VDD_290     16
-#define        MMC_VDD_300     17
-#define        MMC_VDD_310     18
-#define        MMC_VDD_320     19
-#define        MMC_VDD_330     20
-#define        MMC_VDD_340     21
-#define        MMC_VDD_350     22
-#define        MMC_VDD_360     23
+/* vdd stores the bit number of the selected voltage range from below. */
 
        unsigned char   bus_mode;               /* command output mode */
 
@@ -88,6 +65,24 @@ struct mmc_host {
        unsigned int            f_max;
        u32                     ocr_avail;
 
+#define MMC_VDD_165_195                0x00000080      /* VDD voltage 1.65 - 1.95 */
+#define MMC_VDD_20_21          0x00000100      /* VDD voltage 2.0 ~ 2.1 */
+#define MMC_VDD_21_22          0x00000200      /* VDD voltage 2.1 ~ 2.2 */
+#define MMC_VDD_22_23          0x00000400      /* VDD voltage 2.2 ~ 2.3 */
+#define MMC_VDD_23_24          0x00000800      /* VDD voltage 2.3 ~ 2.4 */
+#define MMC_VDD_24_25          0x00001000      /* VDD voltage 2.4 ~ 2.5 */
+#define MMC_VDD_25_26          0x00002000      /* VDD voltage 2.5 ~ 2.6 */
+#define MMC_VDD_26_27          0x00004000      /* VDD voltage 2.6 ~ 2.7 */
+#define MMC_VDD_27_28          0x00008000      /* VDD voltage 2.7 ~ 2.8 */
+#define MMC_VDD_28_29          0x00010000      /* VDD voltage 2.8 ~ 2.9 */
+#define MMC_VDD_29_30          0x00020000      /* VDD voltage 2.9 ~ 3.0 */
+#define MMC_VDD_30_31          0x00040000      /* VDD voltage 3.0 ~ 3.1 */
+#define MMC_VDD_31_32          0x00080000      /* VDD voltage 3.1 ~ 3.2 */
+#define MMC_VDD_32_33          0x00100000      /* VDD voltage 3.2 ~ 3.3 */
+#define MMC_VDD_33_34          0x00200000      /* VDD voltage 3.3 ~ 3.4 */
+#define MMC_VDD_34_35          0x00400000      /* VDD voltage 3.4 ~ 3.5 */
+#define MMC_VDD_35_36          0x00800000      /* VDD voltage 3.5 ~ 3.6 */
+
        unsigned long           caps;           /* Host capabilities */
 
 #define MMC_CAP_4_BIT_DATA     (1 << 0)        /* Can the host do 4 bit transfers */
@@ -106,6 +101,8 @@ struct mmc_host {
        unsigned int            max_blk_count;  /* maximum number of blocks in one req */
 
        /* private data */
+       spinlock_t              lock;           /* lock for claim and bus ops */
+
        struct mmc_ios          ios;            /* current io bus settings */
        u32                     ocr;            /* the current OCR setting */
 
@@ -113,15 +110,19 @@ struct mmc_host {
 #define MMC_MODE_MMC           0
 #define MMC_MODE_SD            1
 
-       struct list_head        cards;          /* devices attached to this host */
+       struct mmc_card         *card;          /* device attached to this host */
 
        wait_queue_head_t       wq;
-       spinlock_t              lock;           /* claimed lock */
        unsigned int            claimed:1;      /* host exclusively claimed */
 
-       struct mmc_card         *card_selected; /* the selected MMC card */
-
        struct delayed_work     detect;
+#ifdef CONFIG_MMC_DEBUG
+       unsigned int            removed:1;      /* host is being removed */
+#endif
+
+       const struct mmc_bus_ops *bus_ops;      /* current bus driver */
+       unsigned int            bus_refs;       /* reference counter */
+       unsigned int            bus_dead:1;     /* bus has been released */
 
        unsigned long           private[0] ____cacheline_aligned;
 };
index cdc54be..e3ed9b9 100644 (file)
 /*
- *  linux/include/linux/mmc/mmc.h
+ * Header for MultiMediaCard (MMC)
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * Copyright 2002 Hewlett-Packard Company
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
+ * FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ * Many thanks to Alessandro Rubini and Jonathan Corbet!
+ *
+ * Based strongly on code by:
+ *
+ * Author: Yong-iL Joh <tolkien@mizi.com>
+ * Date  : $Date: 2002/06/18 12:37:30 $
+ *
+ * Author:  Andrew Christian
+ *          15 May 2002
  */
-#ifndef MMC_H
-#define MMC_H
-
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-
-struct request;
-struct mmc_data;
-struct mmc_request;
-
-struct mmc_command {
-       u32                     opcode;
-       u32                     arg;
-       u32                     resp[4];
-       unsigned int            flags;          /* expected response type */
-#define MMC_RSP_PRESENT        (1 << 0)
-#define MMC_RSP_136    (1 << 1)                /* 136 bit response */
-#define MMC_RSP_CRC    (1 << 2)                /* expect valid crc */
-#define MMC_RSP_BUSY   (1 << 3)                /* card may send busy */
-#define MMC_RSP_OPCODE (1 << 4)                /* response contains opcode */
-#define MMC_CMD_MASK   (3 << 5)                /* command type */
-#define MMC_CMD_AC     (0 << 5)
-#define MMC_CMD_ADTC   (1 << 5)
-#define MMC_CMD_BC     (2 << 5)
-#define MMC_CMD_BCR    (3 << 5)
+
+#ifndef MMC_MMC_H
+#define MMC_MMC_H
+
+/* Standard MMC commands (4.1)           type  argument     response */
+   /* class 1 */
+#define        MMC_GO_IDLE_STATE         0   /* bc                          */
+#define MMC_SEND_OP_COND          1   /* bcr  [31:0] OCR         R3  */
+#define MMC_ALL_SEND_CID          2   /* bcr                     R2  */
+#define MMC_SET_RELATIVE_ADDR     3   /* ac   [31:16] RCA        R1  */
+#define MMC_SET_DSR               4   /* bc   [31:16] RCA            */
+#define MMC_SWITCH                6   /* ac   [31:0] See below   R1b */
+#define MMC_SELECT_CARD           7   /* ac   [31:16] RCA        R1  */
+#define MMC_SEND_EXT_CSD          8   /* adtc                    R1  */
+#define MMC_SEND_CSD              9   /* ac   [31:16] RCA        R2  */
+#define MMC_SEND_CID             10   /* ac   [31:16] RCA        R2  */
+#define MMC_READ_DAT_UNTIL_STOP  11   /* adtc [31:0] dadr        R1  */
+#define MMC_STOP_TRANSMISSION    12   /* ac                      R1b */
+#define MMC_SEND_STATUS                 13   /* ac   [31:16] RCA        R1  */
+#define MMC_GO_INACTIVE_STATE    15   /* ac   [31:16] RCA            */
+
+  /* class 2 */
+#define MMC_SET_BLOCKLEN         16   /* ac   [31:0] block len   R1  */
+#define MMC_READ_SINGLE_BLOCK    17   /* adtc [31:0] data addr   R1  */
+#define MMC_READ_MULTIPLE_BLOCK  18   /* adtc [31:0] data addr   R1  */
+
+  /* class 3 */
+#define MMC_WRITE_DAT_UNTIL_STOP 20   /* adtc [31:0] data addr   R1  */
+
+  /* class 4 */
+#define MMC_SET_BLOCK_COUNT      23   /* adtc [31:0] data addr   R1  */
+#define MMC_WRITE_BLOCK          24   /* adtc [31:0] data addr   R1  */
+#define MMC_WRITE_MULTIPLE_BLOCK 25   /* adtc                    R1  */
+#define MMC_PROGRAM_CID          26   /* adtc                    R1  */
+#define MMC_PROGRAM_CSD          27   /* adtc                    R1  */
+
+  /* class 6 */
+#define MMC_SET_WRITE_PROT       28   /* ac   [31:0] data addr   R1b */
+#define MMC_CLR_WRITE_PROT       29   /* ac   [31:0] data addr   R1b */
+#define MMC_SEND_WRITE_PROT      30   /* adtc [31:0] wpdata addr R1  */
+
+  /* class 5 */
+#define MMC_ERASE_GROUP_START    35   /* ac   [31:0] data addr   R1  */
+#define MMC_ERASE_GROUP_END      36   /* ac   [31:0] data addr   R1  */
+#define MMC_ERASE                38   /* ac                      R1b */
+
+  /* class 9 */
+#define MMC_FAST_IO              39   /* ac   <Complex>          R4  */
+#define MMC_GO_IRQ_STATE         40   /* bcr                     R5  */
+
+  /* class 7 */
+#define MMC_LOCK_UNLOCK          42   /* adtc                    R1b */
+
+  /* class 8 */
+#define MMC_APP_CMD              55   /* ac   [31:16] RCA        R1  */
+#define MMC_GEN_CMD              56   /* adtc [0] RD/WR          R1  */
 
 /*
- * These are the response types, and correspond to valid bit
- * patterns of the above flags.  One additional valid pattern
- * is all zeros, which means we don't expect a response.
+ * MMC_SWITCH argument format:
+ *
+ *     [31:26] Always 0
+ *     [25:24] Access Mode
+ *     [23:16] Location of target Byte in EXT_CSD
+ *     [15:08] Value Byte
+ *     [07:03] Always 0
+ *     [02:00] Command Set
  */
-#define MMC_RSP_NONE   (0)
-#define MMC_RSP_R1     (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
-#define MMC_RSP_R1B    (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY)
-#define MMC_RSP_R2     (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
-#define MMC_RSP_R3     (MMC_RSP_PRESENT)
-#define MMC_RSP_R6     (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
-#define MMC_RSP_R7     (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
-
-#define mmc_resp_type(cmd)     ((cmd)->flags & (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC|MMC_RSP_BUSY|MMC_RSP_OPCODE))
 
 /*
- * These are the command types.
+  MMC status in R1
+  Type
+       e : error bit
+       s : status bit
+       r : detected and set for the actual command response
+       x : detected and set during command execution. the host must poll
+            the card by sending status command in order to read these bits.
+  Clear condition
+       a : according to the card state
+       b : always related to the previous command. Reception of
+            a valid command will clear it (with a delay of one command)
+       c : clear by read
  */
-#define mmc_cmd_type(cmd)      ((cmd)->flags & MMC_CMD_MASK)
 
-       unsigned int            retries;        /* max number of retries */
-       unsigned int            error;          /* command error */
+#define R1_OUT_OF_RANGE                (1 << 31)       /* er, c */
+#define R1_ADDRESS_ERROR       (1 << 30)       /* erx, c */
+#define R1_BLOCK_LEN_ERROR     (1 << 29)       /* er, c */
+#define R1_ERASE_SEQ_ERROR      (1 << 28)      /* er, c */
+#define R1_ERASE_PARAM         (1 << 27)       /* ex, c */
+#define R1_WP_VIOLATION                (1 << 26)       /* erx, c */
+#define R1_CARD_IS_LOCKED      (1 << 25)       /* sx, a */
+#define R1_LOCK_UNLOCK_FAILED  (1 << 24)       /* erx, c */
+#define R1_COM_CRC_ERROR       (1 << 23)       /* er, b */
+#define R1_ILLEGAL_COMMAND     (1 << 22)       /* er, b */
+#define R1_CARD_ECC_FAILED     (1 << 21)       /* ex, c */
+#define R1_CC_ERROR            (1 << 20)       /* erx, c */
+#define R1_ERROR               (1 << 19)       /* erx, c */
+#define R1_UNDERRUN            (1 << 18)       /* ex, c */
+#define R1_OVERRUN             (1 << 17)       /* ex, c */
+#define R1_CID_CSD_OVERWRITE   (1 << 16)       /* erx, c, CID/CSD overwrite */
+#define R1_WP_ERASE_SKIP       (1 << 15)       /* sx, c */
+#define R1_CARD_ECC_DISABLED   (1 << 14)       /* sx, a */
+#define R1_ERASE_RESET         (1 << 13)       /* sr, c */
+#define R1_STATUS(x)            (x & 0xFFFFE000)
+#define R1_CURRENT_STATE(x)            ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */
+#define R1_READY_FOR_DATA      (1 << 8)        /* sx, a */
+#define R1_APP_CMD             (1 << 5)        /* sr, c */
 
-#define MMC_ERR_NONE   0
-#define MMC_ERR_TIMEOUT        1
-#define MMC_ERR_BADCRC 2
-#define MMC_ERR_FIFO   3
-#define MMC_ERR_FAILED 4
-#define MMC_ERR_INVALID        5
+/* These are unpacked versions of the actual responses */
 
-       struct mmc_data         *data;          /* data segment associated with cmd */
-       struct mmc_request      *mrq;           /* associated request */
+struct _mmc_csd {
+       u8  csd_structure;
+       u8  spec_vers;
+       u8  taac;
+       u8  nsac;
+       u8  tran_speed;
+       u16 ccc;
+       u8  read_bl_len;
+       u8  read_bl_partial;
+       u8  write_blk_misalign;
+       u8  read_blk_misalign;
+       u8  dsr_imp;
+       u16 c_size;
+       u8  vdd_r_curr_min;
+       u8  vdd_r_curr_max;
+       u8  vdd_w_curr_min;
+       u8  vdd_w_curr_max;
+       u8  c_size_mult;
+       union {
+               struct { /* MMC system specification version 3.1 */
+                       u8  erase_grp_size;
+                       u8  erase_grp_mult;
+               } v31;
+               struct { /* MMC system specification version 2.2 */
+                       u8  sector_size;
+                       u8  erase_grp_size;
+               } v22;
+       } erase;
+       u8  wp_grp_size;
+       u8  wp_grp_enable;
+       u8  default_ecc;
+       u8  r2w_factor;
+       u8  write_bl_len;
+       u8  write_bl_partial;
+       u8  file_format_grp;
+       u8  copy;
+       u8  perm_write_protect;
+       u8  tmp_write_protect;
+       u8  file_format;
+       u8  ecc;
 };
 
-struct mmc_data {
-       unsigned int            timeout_ns;     /* data timeout (in ns, max 80ms) */
-       unsigned int            timeout_clks;   /* data timeout (in clocks) */
-       unsigned int            blksz;          /* data block size */
-       unsigned int            blocks;         /* number of blocks */
-       unsigned int            error;          /* data error */
-       unsigned int            flags;
+/*
+ * OCR bits are mostly in host.h
+ */
+#define MMC_CARD_BUSY  0x80000000      /* Card Power up status bit */
 
-#define MMC_DATA_WRITE (1 << 8)
-#define MMC_DATA_READ  (1 << 9)
-#define MMC_DATA_STREAM        (1 << 10)
-#define MMC_DATA_MULTI (1 << 11)
+/*
+ * Card Command Classes (CCC)
+ */
+#define CCC_BASIC              (1<<0)  /* (0) Basic protocol functions */
+                                       /* (CMD0,1,2,3,4,7,9,10,12,13,15) */
+#define CCC_STREAM_READ                (1<<1)  /* (1) Stream read commands */
+                                       /* (CMD11) */
+#define CCC_BLOCK_READ         (1<<2)  /* (2) Block read commands */
+                                       /* (CMD16,17,18) */
+#define CCC_STREAM_WRITE       (1<<3)  /* (3) Stream write commands */
+                                       /* (CMD20) */
+#define CCC_BLOCK_WRITE                (1<<4)  /* (4) Block write commands */
+                                       /* (CMD16,24,25,26,27) */
+#define CCC_ERASE              (1<<5)  /* (5) Ability to erase blocks */
+                                       /* (CMD32,33,34,35,36,37,38,39) */
+#define CCC_WRITE_PROT         (1<<6)  /* (6) Able to write protect blocks */
+                                       /* (CMD28,29,30) */
+#define CCC_LOCK_CARD          (1<<7)  /* (7) Able to lock down card */
+                                       /* (CMD16,CMD42) */
+#define CCC_APP_SPEC           (1<<8)  /* (8) Application specific */
+                                       /* (CMD55,56,57,ACMD*) */
+#define CCC_IO_MODE            (1<<9)  /* (9) I/O mode */
+                                       /* (CMD5,39,40,52,53) */
+#define CCC_SWITCH             (1<<10) /* (10) High speed switch */
+                                       /* (CMD6,34,35,36,37,50) */
+                                       /* (11) Reserved */
+                                       /* (CMD?) */
 
-       unsigned int            bytes_xfered;
+/*
+ * CSD field definitions
+ */
 
-       struct mmc_command      *stop;          /* stop command */
-       struct mmc_request      *mrq;           /* associated request */
+#define CSD_STRUCT_VER_1_0  0           /* Valid for system specification 1.0 - 1.2 */
+#define CSD_STRUCT_VER_1_1  1           /* Valid for system specification 1.4 - 2.2 */
+#define CSD_STRUCT_VER_1_2  2           /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */
+#define CSD_STRUCT_EXT_CSD  3           /* Version is coded in CSD_STRUCTURE in EXT_CSD */
 
-       unsigned int            sg_len;         /* size of scatter list */
-       struct scatterlist      *sg;            /* I/O scatter list */
-};
+#define CSD_SPEC_VER_0      0           /* Implements system specification 1.0 - 1.2 */
+#define CSD_SPEC_VER_1      1           /* Implements system specification 1.4 */
+#define CSD_SPEC_VER_2      2           /* Implements system specification 2.0 - 2.2 */
+#define CSD_SPEC_VER_3      3           /* Implements system specification 3.1 - 3.2 - 3.31 */
+#define CSD_SPEC_VER_4      4           /* Implements system specification 4.0 - 4.1 */
 
-struct mmc_request {
-       struct mmc_command      *cmd;
-       struct mmc_data         *data;
-       struct mmc_command      *stop;
+/*
+ * EXT_CSD fields
+ */
 
-       void                    *done_data;     /* completion data */
-       void                    (*done)(struct mmc_request *);/* completion function */
-};
+#define EXT_CSD_BUS_WIDTH      183     /* R/W */
+#define EXT_CSD_HS_TIMING      185     /* R/W */
+#define EXT_CSD_CARD_TYPE      196     /* RO */
+#define EXT_CSD_SEC_CNT                212     /* RO, 4 bytes */
+
+/*
+ * EXT_CSD field definitions
+ */
 
-struct mmc_host;
-struct mmc_card;
+#define EXT_CSD_CMD_SET_NORMAL         (1<<0)
+#define EXT_CSD_CMD_SET_SECURE         (1<<1)
+#define EXT_CSD_CMD_SET_CPSECURE       (1<<2)
 
-extern int mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
-extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
-extern int mmc_wait_for_app_cmd(struct mmc_host *, unsigned int,
-       struct mmc_command *, int);
+#define EXT_CSD_CARD_TYPE_26   (1<<0)  /* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_52   (1<<1)  /* Card can run at 52MHz */
 
-extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *, int);
+#define EXT_CSD_BUS_WIDTH_1    0       /* Card is in 1 bit mode */
+#define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */
+#define EXT_CSD_BUS_WIDTH_8    2       /* Card is in 8 bit mode */
 
-extern int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card);
+/*
+ * MMC_SWITCH access modes
+ */
 
-static inline void mmc_claim_host(struct mmc_host *host)
-{
-       __mmc_claim_host(host, (struct mmc_card *)-1);
-}
+#define MMC_SWITCH_MODE_CMD_SET                0x00    /* Change the command set */
+#define MMC_SWITCH_MODE_SET_BITS       0x01    /* Set bits which are 1 in value */
+#define MMC_SWITCH_MODE_CLEAR_BITS     0x02    /* Clear bits which are 1 in value */
+#define MMC_SWITCH_MODE_WRITE_BYTE     0x03    /* Set target to value */
 
-extern void mmc_release_host(struct mmc_host *host);
+#endif  /* MMC_MMC_PROTOCOL_H */
 
-#endif
diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h
deleted file mode 100644 (file)
index c90b676..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * Header for MultiMediaCard (MMC)
- *
- * Copyright 2002 Hewlett-Packard Company
- *
- * Use consistent with the GNU GPL is permitted,
- * provided that this copyright notice is
- * preserved in its entirety in all copies and derived works.
- *
- * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
- * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
- * FITNESS FOR ANY PARTICULAR PURPOSE.
- *
- * Many thanks to Alessandro Rubini and Jonathan Corbet!
- *
- * Based strongly on code by:
- *
- * Author: Yong-iL Joh <tolkien@mizi.com>
- * Date  : $Date: 2002/06/18 12:37:30 $
- *
- * Author:  Andrew Christian
- *          15 May 2002
- */
-
-#ifndef MMC_MMC_PROTOCOL_H
-#define MMC_MMC_PROTOCOL_H
-
-/* Standard MMC commands (4.1)           type  argument     response */
-   /* class 1 */
-#define        MMC_GO_IDLE_STATE         0   /* bc                          */
-#define MMC_SEND_OP_COND          1   /* bcr  [31:0] OCR         R3  */
-#define MMC_ALL_SEND_CID          2   /* bcr                     R2  */
-#define MMC_SET_RELATIVE_ADDR     3   /* ac   [31:16] RCA        R1  */
-#define MMC_SET_DSR               4   /* bc   [31:16] RCA            */
-#define MMC_SWITCH                6   /* ac   [31:0] See below   R1b */
-#define MMC_SELECT_CARD           7   /* ac   [31:16] RCA        R1  */
-#define MMC_SEND_EXT_CSD          8   /* adtc                    R1  */
-#define MMC_SEND_CSD              9   /* ac   [31:16] RCA        R2  */
-#define MMC_SEND_CID             10   /* ac   [31:16] RCA        R2  */
-#define MMC_READ_DAT_UNTIL_STOP  11   /* adtc [31:0] dadr        R1  */
-#define MMC_STOP_TRANSMISSION    12   /* ac                      R1b */
-#define MMC_SEND_STATUS                 13   /* ac   [31:16] RCA        R1  */
-#define MMC_GO_INACTIVE_STATE    15   /* ac   [31:16] RCA            */
-
-  /* class 2 */
-#define MMC_SET_BLOCKLEN         16   /* ac   [31:0] block len   R1  */
-#define MMC_READ_SINGLE_BLOCK    17   /* adtc [31:0] data addr   R1  */
-#define MMC_READ_MULTIPLE_BLOCK  18   /* adtc [31:0] data addr   R1  */
-
-  /* class 3 */
-#define MMC_WRITE_DAT_UNTIL_STOP 20   /* adtc [31:0] data addr   R1  */
-
-  /* class 4 */
-#define MMC_SET_BLOCK_COUNT      23   /* adtc [31:0] data addr   R1  */
-#define MMC_WRITE_BLOCK          24   /* adtc [31:0] data addr   R1  */
-#define MMC_WRITE_MULTIPLE_BLOCK 25   /* adtc                    R1  */
-#define MMC_PROGRAM_CID          26   /* adtc                    R1  */
-#define MMC_PROGRAM_CSD          27   /* adtc                    R1  */
-
-  /* class 6 */
-#define MMC_SET_WRITE_PROT       28   /* ac   [31:0] data addr   R1b */
-#define MMC_CLR_WRITE_PROT       29   /* ac   [31:0] data addr   R1b */
-#define MMC_SEND_WRITE_PROT      30   /* adtc [31:0] wpdata addr R1  */
-
-  /* class 5 */
-#define MMC_ERASE_GROUP_START    35   /* ac   [31:0] data addr   R1  */
-#define MMC_ERASE_GROUP_END      36   /* ac   [31:0] data addr   R1  */
-#define MMC_ERASE                38   /* ac                      R1b */
-
-  /* class 9 */
-#define MMC_FAST_IO              39   /* ac   <Complex>          R4  */
-#define MMC_GO_IRQ_STATE         40   /* bcr                     R5  */
-
-  /* class 7 */
-#define MMC_LOCK_UNLOCK          42   /* adtc                    R1b */
-
-  /* class 8 */
-#define MMC_APP_CMD              55   /* ac   [31:16] RCA        R1  */
-#define MMC_GEN_CMD              56   /* adtc [0] RD/WR          R1  */
-
-/* SD commands                           type  argument     response */
-  /* class 0 */
-/* This is basically the same command as for MMC with some quirks. */
-#define SD_SEND_RELATIVE_ADDR     3   /* bcr                     R6  */
-#define SD_SEND_IF_COND           8   /* bcr  [11:0] See below   R7  */
-
-  /* class 10 */
-#define SD_SWITCH                 6   /* adtc [31:0] See below   R1  */
-
-  /* Application commands */
-#define SD_APP_SET_BUS_WIDTH      6   /* ac   [1:0] bus width    R1  */
-#define SD_APP_SEND_NUM_WR_BLKS  22   /* adtc                    R1  */
-#define SD_APP_OP_COND           41   /* bcr  [31:0] OCR         R3  */
-#define SD_APP_SEND_SCR          51   /* adtc                    R1  */
-
-/*
- * MMC_SWITCH argument format:
- *
- *     [31:26] Always 0
- *     [25:24] Access Mode
- *     [23:16] Location of target Byte in EXT_CSD
- *     [15:08] Value Byte
- *     [07:03] Always 0
- *     [02:00] Command Set
- */
-
-/*
- * SD_SWITCH argument format:
- *
- *      [31] Check (0) or switch (1)
- *      [30:24] Reserved (0)
- *      [23:20] Function group 6
- *      [19:16] Function group 5
- *      [15:12] Function group 4
- *      [11:8] Function group 3
- *      [7:4] Function group 2
- *      [3:0] Function group 1
- */
-
-/*
- * SD_SEND_IF_COND argument format:
- *
- *     [31:12] Reserved (0)
- *     [11:8] Host Voltage Supply Flags
- *     [7:0] Check Pattern (0xAA)
- */
-
-/*
-  MMC status in R1
-  Type
-       e : error bit
-       s : status bit
-       r : detected and set for the actual command response
-       x : detected and set during command execution. the host must poll
-            the card by sending status command in order to read these bits.
-  Clear condition
-       a : according to the card state
-       b : always related to the previous command. Reception of
-            a valid command will clear it (with a delay of one command)
-       c : clear by read
- */
-
-#define R1_OUT_OF_RANGE                (1 << 31)       /* er, c */
-#define R1_ADDRESS_ERROR       (1 << 30)       /* erx, c */
-#define R1_BLOCK_LEN_ERROR     (1 << 29)       /* er, c */
-#define R1_ERASE_SEQ_ERROR      (1 << 28)      /* er, c */
-#define R1_ERASE_PARAM         (1 << 27)       /* ex, c */
-#define R1_WP_VIOLATION                (1 << 26)       /* erx, c */
-#define R1_CARD_IS_LOCKED      (1 << 25)       /* sx, a */
-#define R1_LOCK_UNLOCK_FAILED  (1 << 24)       /* erx, c */
-#define R1_COM_CRC_ERROR       (1 << 23)       /* er, b */
-#define R1_ILLEGAL_COMMAND     (1 << 22)       /* er, b */
-#define R1_CARD_ECC_FAILED     (1 << 21)       /* ex, c */
-#define R1_CC_ERROR            (1 << 20)       /* erx, c */
-#define R1_ERROR               (1 << 19)       /* erx, c */
-#define R1_UNDERRUN            (1 << 18)       /* ex, c */
-#define R1_OVERRUN             (1 << 17)       /* ex, c */
-#define R1_CID_CSD_OVERWRITE   (1 << 16)       /* erx, c, CID/CSD overwrite */
-#define R1_WP_ERASE_SKIP       (1 << 15)       /* sx, c */
-#define R1_CARD_ECC_DISABLED   (1 << 14)       /* sx, a */
-#define R1_ERASE_RESET         (1 << 13)       /* sr, c */
-#define R1_STATUS(x)            (x & 0xFFFFE000)
-#define R1_CURRENT_STATE(x)            ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */
-#define R1_READY_FOR_DATA      (1 << 8)        /* sx, a */
-#define R1_APP_CMD             (1 << 5)        /* sr, c */
-
-/* These are unpacked versions of the actual responses */
-
-struct _mmc_csd {
-       u8  csd_structure;
-       u8  spec_vers;
-       u8  taac;
-       u8  nsac;
-       u8  tran_speed;
-       u16 ccc;
-       u8  read_bl_len;
-       u8  read_bl_partial;
-       u8  write_blk_misalign;
-       u8  read_blk_misalign;
-       u8  dsr_imp;
-       u16 c_size;
-       u8  vdd_r_curr_min;
-       u8  vdd_r_curr_max;
-       u8  vdd_w_curr_min;
-       u8  vdd_w_curr_max;
-       u8  c_size_mult;
-       union {
-               struct { /* MMC system specification version 3.1 */
-                       u8  erase_grp_size;
-                       u8  erase_grp_mult;
-               } v31;
-               struct { /* MMC system specification version 2.2 */
-                       u8  sector_size;
-                       u8  erase_grp_size;
-               } v22;
-       } erase;
-       u8  wp_grp_size;
-       u8  wp_grp_enable;
-       u8  default_ecc;
-       u8  r2w_factor;
-       u8  write_bl_len;
-       u8  write_bl_partial;
-       u8  file_format_grp;
-       u8  copy;
-       u8  perm_write_protect;
-       u8  tmp_write_protect;
-       u8  file_format;
-       u8  ecc;
-};
-
-#define MMC_VDD_145_150        0x00000001      /* VDD voltage 1.45 - 1.50 */
-#define MMC_VDD_150_155        0x00000002      /* VDD voltage 1.50 - 1.55 */
-#define MMC_VDD_155_160        0x00000004      /* VDD voltage 1.55 - 1.60 */
-#define MMC_VDD_160_165        0x00000008      /* VDD voltage 1.60 - 1.65 */
-#define MMC_VDD_165_170        0x00000010      /* VDD voltage 1.65 - 1.70 */
-#define MMC_VDD_17_18  0x00000020      /* VDD voltage 1.7 - 1.8 */
-#define MMC_VDD_18_19  0x00000040      /* VDD voltage 1.8 - 1.9 */
-#define MMC_VDD_19_20  0x00000080      /* VDD voltage 1.9 - 2.0 */
-#define MMC_VDD_20_21  0x00000100      /* VDD voltage 2.0 ~ 2.1 */
-#define MMC_VDD_21_22  0x00000200      /* VDD voltage 2.1 ~ 2.2 */
-#define MMC_VDD_22_23  0x00000400      /* VDD voltage 2.2 ~ 2.3 */
-#define MMC_VDD_23_24  0x00000800      /* VDD voltage 2.3 ~ 2.4 */
-#define MMC_VDD_24_25  0x00001000      /* VDD voltage 2.4 ~ 2.5 */
-#define MMC_VDD_25_26  0x00002000      /* VDD voltage 2.5 ~ 2.6 */
-#define MMC_VDD_26_27  0x00004000      /* VDD voltage 2.6 ~ 2.7 */
-#define MMC_VDD_27_28  0x00008000      /* VDD voltage 2.7 ~ 2.8 */
-#define MMC_VDD_28_29  0x00010000      /* VDD voltage 2.8 ~ 2.9 */
-#define MMC_VDD_29_30  0x00020000      /* VDD voltage 2.9 ~ 3.0 */
-#define MMC_VDD_30_31  0x00040000      /* VDD voltage 3.0 ~ 3.1 */
-#define MMC_VDD_31_32  0x00080000      /* VDD voltage 3.1 ~ 3.2 */
-#define MMC_VDD_32_33  0x00100000      /* VDD voltage 3.2 ~ 3.3 */
-#define MMC_VDD_33_34  0x00200000      /* VDD voltage 3.3 ~ 3.4 */
-#define MMC_VDD_34_35  0x00400000      /* VDD voltage 3.4 ~ 3.5 */
-#define MMC_VDD_35_36  0x00800000      /* VDD voltage 3.5 ~ 3.6 */
-#define MMC_CARD_BUSY  0x80000000      /* Card Power up status bit */
-
-/*
- * Card Command Classes (CCC)
- */
-#define CCC_BASIC              (1<<0)  /* (0) Basic protocol functions */
-                                       /* (CMD0,1,2,3,4,7,9,10,12,13,15) */
-#define CCC_STREAM_READ                (1<<1)  /* (1) Stream read commands */
-                                       /* (CMD11) */
-#define CCC_BLOCK_READ         (1<<2)  /* (2) Block read commands */
-                                       /* (CMD16,17,18) */
-#define CCC_STREAM_WRITE       (1<<3)  /* (3) Stream write commands */
-                                       /* (CMD20) */
-#define CCC_BLOCK_WRITE                (1<<4)  /* (4) Block write commands */
-                                       /* (CMD16,24,25,26,27) */
-#define CCC_ERASE              (1<<5)  /* (5) Ability to erase blocks */
-                                       /* (CMD32,33,34,35,36,37,38,39) */
-#define CCC_WRITE_PROT         (1<<6)  /* (6) Able to write protect blocks */
-                                       /* (CMD28,29,30) */
-#define CCC_LOCK_CARD          (1<<7)  /* (7) Able to lock down card */
-                                       /* (CMD16,CMD42) */
-#define CCC_APP_SPEC           (1<<8)  /* (8) Application specific */
-                                       /* (CMD55,56,57,ACMD*) */
-#define CCC_IO_MODE            (1<<9)  /* (9) I/O mode */
-                                       /* (CMD5,39,40,52,53) */
-#define CCC_SWITCH             (1<<10) /* (10) High speed switch */
-                                       /* (CMD6,34,35,36,37,50) */
-                                       /* (11) Reserved */
-                                       /* (CMD?) */
-
-/*
- * CSD field definitions
- */
-
-#define CSD_STRUCT_VER_1_0  0           /* Valid for system specification 1.0 - 1.2 */
-#define CSD_STRUCT_VER_1_1  1           /* Valid for system specification 1.4 - 2.2 */
-#define CSD_STRUCT_VER_1_2  2           /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */
-#define CSD_STRUCT_EXT_CSD  3           /* Version is coded in CSD_STRUCTURE in EXT_CSD */
-
-#define CSD_SPEC_VER_0      0           /* Implements system specification 1.0 - 1.2 */
-#define CSD_SPEC_VER_1      1           /* Implements system specification 1.4 */
-#define CSD_SPEC_VER_2      2           /* Implements system specification 2.0 - 2.2 */
-#define CSD_SPEC_VER_3      3           /* Implements system specification 3.1 - 3.2 - 3.31 */
-#define CSD_SPEC_VER_4      4           /* Implements system specification 4.0 - 4.1 */
-
-/*
- * EXT_CSD fields
- */
-
-#define EXT_CSD_BUS_WIDTH      183     /* R/W */
-#define EXT_CSD_HS_TIMING      185     /* R/W */
-#define EXT_CSD_CARD_TYPE      196     /* RO */
-
-/*
- * EXT_CSD field definitions
- */
-
-#define EXT_CSD_CMD_SET_NORMAL         (1<<0)
-#define EXT_CSD_CMD_SET_SECURE         (1<<1)
-#define EXT_CSD_CMD_SET_CPSECURE       (1<<2)
-
-#define EXT_CSD_CARD_TYPE_26   (1<<0)  /* Card can run at 26MHz */
-#define EXT_CSD_CARD_TYPE_52   (1<<1)  /* Card can run at 52MHz */
-
-#define EXT_CSD_BUS_WIDTH_1    0       /* Card is in 1 bit mode */
-#define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */
-#define EXT_CSD_BUS_WIDTH_8    2       /* Card is in 8 bit mode */
-
-/*
- * MMC_SWITCH access modes
- */
-
-#define MMC_SWITCH_MODE_CMD_SET                0x00    /* Change the command set */
-#define MMC_SWITCH_MODE_SET_BITS       0x01    /* Set bits which are 1 in value */
-#define MMC_SWITCH_MODE_CLEAR_BITS     0x02    /* Clear bits which are 1 in value */
-#define MMC_SWITCH_MODE_WRITE_BYTE     0x03    /* Set target to value */
-
-/*
- * SCR field definitions
- */
-
-#define SCR_SPEC_VER_0      0           /* Implements system specification 1.0 - 1.01 */
-#define SCR_SPEC_VER_1      1           /* Implements system specification 1.10 */
-#define SCR_SPEC_VER_2      2           /* Implements system specification 2.00 */
-
-/*
- * SD bus widths
- */
-#define SD_BUS_WIDTH_1      0
-#define SD_BUS_WIDTH_4      2
-
-#endif  /* MMC_MMC_PROTOCOL_H */
-
diff --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h
new file mode 100644 (file)
index 0000000..f310062
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ *  include/linux/mmc/sd.h
+ *
+ *  Copyright (C) 2005-2007 Pierre Ossman, 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.
+ */
+
+#ifndef MMC_SD_H
+#define MMC_SD_H
+
+/* SD commands                           type  argument     response */
+  /* class 0 */
+/* This is basically the same command as for MMC with some quirks. */
+#define SD_SEND_RELATIVE_ADDR     3   /* bcr                     R6  */
+#define SD_SEND_IF_COND           8   /* bcr  [11:0] See below   R7  */
+
+  /* class 10 */
+#define SD_SWITCH                 6   /* adtc [31:0] See below   R1  */
+
+  /* Application commands */
+#define SD_APP_SET_BUS_WIDTH      6   /* ac   [1:0] bus width    R1  */
+#define SD_APP_SEND_NUM_WR_BLKS  22   /* adtc                    R1  */
+#define SD_APP_OP_COND           41   /* bcr  [31:0] OCR         R3  */
+#define SD_APP_SEND_SCR          51   /* adtc                    R1  */
+
+/*
+ * SD_SWITCH argument format:
+ *
+ *      [31] Check (0) or switch (1)
+ *      [30:24] Reserved (0)
+ *      [23:20] Function group 6
+ *      [19:16] Function group 5
+ *      [15:12] Function group 4
+ *      [11:8] Function group 3
+ *      [7:4] Function group 2
+ *      [3:0] Function group 1
+ */
+
+/*
+ * SD_SEND_IF_COND argument format:
+ *
+ *     [31:12] Reserved (0)
+ *     [11:8] Host Voltage Supply Flags
+ *     [7:0] Check Pattern (0xAA)
+ */
+
+/*
+ * SCR field definitions
+ */
+
+#define SCR_SPEC_VER_0         0       /* Implements system specification 1.0 - 1.01 */
+#define SCR_SPEC_VER_1         1       /* Implements system specification 1.10 */
+#define SCR_SPEC_VER_2         2       /* Implements system specification 2.00 */
+
+/*
+ * SD bus widths
+ */
+#define SD_BUS_WIDTH_1         0
+#define SD_BUS_WIDTH_4         2
+
+/*
+ * SD_SWITCH mode
+ */
+#define SD_SWITCH_CHECK                0
+#define SD_SWITCH_SET          1
+
+/*
+ * SD_SWITCH function groups
+ */
+#define SD_SWITCH_GRP_ACCESS   0
+
+/*
+ * SD_SWITCH access modes
+ */
+#define SD_SWITCH_ACCESS_DEF   0
+#define SD_SWITCH_ACCESS_HS    1
+
+#endif
+
index 95679eb..f0b0faf 100644 (file)
@@ -568,7 +568,7 @@ struct device_driver;
 #ifdef CONFIG_SYSFS
 struct module;
 
-extern struct subsystem module_subsys;
+extern struct kset module_subsys;
 
 int mod_sysfs_init(struct module *mod);
 int mod_sysfs_setup(struct module *mod,
index e38fe68..94bb46d 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef LINUX_MSI_H
 #define LINUX_MSI_H
 
+#include <linux/list.h>
+
 struct msi_msg {
        u32     address_lo;     /* low 32 bits of msi message address */
        u32     address_hi;     /* high 32 bits of msi message address */
@@ -24,10 +26,8 @@ struct msi_desc {
                unsigned default_irq;   /* default pre-assigned irq       */
        }msi_attrib;
 
-       struct {
-               __u16   head;
-               __u16   tail;
-       }link;
+       unsigned int irq;
+       struct list_head list;
 
        void __iomem *mask_base;
        struct pci_dev *dev;
@@ -41,6 +41,9 @@ struct msi_desc {
  */
 int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
 void arch_teardown_msi_irq(unsigned int irq);
+extern int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
+extern void arch_teardown_msi_irqs(struct pci_dev *dev);
+extern int arch_msi_check_device(struct pci_dev* dev, int nvec, int type);
 
 
 #endif /* LINUX_MSI_H */
index ac0c92b..3044622 100644 (file)
@@ -304,7 +304,7 @@ struct net_device
 
        unsigned long           state;
 
-       struct net_device       *next;
+       struct list_head        dev_list;
        
        /* The device initialization function. Called only once. */
        int                     (*init)(struct net_device *dev);
@@ -575,13 +575,36 @@ struct packet_type {
 #include <linux/notifier.h>
 
 extern struct net_device               loopback_dev;           /* The loopback */
-extern struct net_device               *dev_base;              /* All devices */
+extern struct list_head                        dev_base_head;          /* All devices */
 extern rwlock_t                                dev_base_lock;          /* Device list lock */
 
+#define for_each_netdev(d)             \
+               list_for_each_entry(d, &dev_base_head, dev_list)
+#define for_each_netdev_safe(d, n)     \
+               list_for_each_entry_safe(d, n, &dev_base_head, dev_list)
+#define for_each_netdev_continue(d)            \
+               list_for_each_entry_continue(d, &dev_base_head, dev_list)
+#define net_device_entry(lh)   list_entry(lh, struct net_device, dev_list)
+
+static inline struct net_device *next_net_device(struct net_device *dev)
+{
+       struct list_head *lh;
+
+       lh = dev->dev_list.next;
+       return lh == &dev_base_head ? NULL : net_device_entry(lh);
+}
+
+static inline struct net_device *first_net_device(void)
+{
+       return list_empty(&dev_base_head) ? NULL :
+               net_device_entry(dev_base_head.next);
+}
+
 extern int                     netdev_boot_setup_check(struct net_device *dev);
 extern unsigned long           netdev_boot_base(const char *prefix, int unit);
 extern struct net_device    *dev_getbyhwaddr(unsigned short type, char *hwaddr);
 extern struct net_device *dev_getfirstbyhwtype(unsigned short type);
+extern struct net_device *__dev_getfirstbyhwtype(unsigned short type);
 extern void            dev_add_pack(struct packet_type *pt);
 extern void            dev_remove_pack(struct packet_type *pt);
 extern void            __dev_remove_pack(struct packet_type *pt);
index 4e6bbce..535e421 100644 (file)
@@ -87,24 +87,6 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
 /* delete keymap entries */
 void nf_ct_gre_keymap_destroy(struct nf_conn *ct);
 
-/* get pointer to gre key, if present */
-static inline __be32 *gre_key(struct gre_hdr *greh)
-{
-       if (!greh->key)
-               return NULL;
-       if (greh->csum || greh->routing)
-               return (__be32 *)(greh+sizeof(*greh)+4);
-       return (__be32 *)(greh+sizeof(*greh));
-}
-
-/* get pointer ot gre csum, if present */
-static inline __sum16 *gre_csum(struct gre_hdr *greh)
-{
-       if (!greh->csum)
-               return NULL;
-       return (__sum16 *)(greh+sizeof(*greh));
-}
-
 extern void nf_ct_gre_keymap_flush(void);
 extern void nf_nat_need_gre(void);
 
index 1906003..533ee35 100644 (file)
@@ -55,18 +55,25 @@ static inline int nf_bridge_maybe_copy_header(struct sk_buff *skb)
        return 0;
 }
 
+static inline unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb)
+{
+       switch (skb->protocol) {
+       case __constant_htons(ETH_P_8021Q):
+               return VLAN_HLEN;
+       case __constant_htons(ETH_P_PPP_SES):
+               return PPPOE_SES_HLEN;
+       default:
+               return 0;
+       }
+}
+
 /* This is called by the IP fragmenting code and it ensures there is
  * enough room for the encapsulating header (if there is one). */
-static inline int nf_bridge_pad(const struct sk_buff *skb)
+static inline unsigned int nf_bridge_pad(const struct sk_buff *skb)
 {
-       int padding = 0;
-
-       if (skb->nf_bridge && skb->protocol == htons(ETH_P_8021Q))
-               padding = VLAN_HLEN;
-       else if (skb->nf_bridge && skb->protocol == htons(ETH_P_PPP_SES))
-               padding = PPPOE_SES_HLEN;
-
-       return padding;
+       if (skb->nf_bridge)
+               return nf_bridge_encap_header_len(skb);
+       return 0;
 }
 
 struct bridge_skb_cb {
index f41688f..2e23353 100644 (file)
@@ -31,7 +31,7 @@ struct sockaddr_nl
 {
        sa_family_t     nl_family;      /* AF_NETLINK   */
        unsigned short  nl_pad;         /* zero         */
-       __u32           nl_pid;         /* process pid  */
+       __u32           nl_pid;         /* port ID      */
                __u32           nl_groups;      /* multicast groups mask */
 };
 
@@ -41,7 +41,7 @@ struct nlmsghdr
        __u16           nlmsg_type;     /* Message content */
        __u16           nlmsg_flags;    /* Additional flags */
        __u32           nlmsg_seq;      /* Sequence number */
-       __u32           nlmsg_pid;      /* Sending process PID */
+       __u32           nlmsg_pid;      /* Sending process port ID */
 };
 
 /* Flags values */
index e9ae0c6..0543439 100644 (file)
@@ -455,7 +455,7 @@ nfs_have_writebacks(struct inode *inode)
 /*
  * Allocate nfs_write_data structures
  */
-extern struct nfs_write_data *nfs_writedata_alloc(size_t len);
+extern struct nfs_write_data *nfs_writedata_alloc(unsigned int npages);
 
 /*
  * linux/fs/nfs/read.c
@@ -469,7 +469,7 @@ extern void nfs_readdata_release(void *data);
 /*
  * Allocate nfs_read_data structures
  */
-extern struct nfs_read_data *nfs_readdata_alloc(size_t len);
+extern struct nfs_read_data *nfs_readdata_alloc(unsigned int npages);
 
 /*
  * linux/fs/nfs3proc.c
index 659c754..cc8b9c5 100644 (file)
@@ -61,6 +61,7 @@ struct nfs_mount_data {
 #define NFS_MOUNT_NOACL                0x0800  /* 4 */
 #define NFS_MOUNT_STRICTLOCK   0x1000  /* reserved for NFSv4 */
 #define NFS_MOUNT_SECFLAVOUR   0x2000  /* 5 */
+#define NFS_MOUNT_NORDIRPLUS   0x4000  /* 5 */
 #define NFS_MOUNT_FLAGMASK     0xFFFF
 
 #endif
index 16b0266..41afab6 100644 (file)
@@ -21,8 +21,7 @@
 /*
  * Valid flags for the radix tree
  */
-#define NFS_PAGE_TAG_DIRTY     0
-#define NFS_PAGE_TAG_WRITEBACK 1
+#define NFS_PAGE_TAG_WRITEBACK 0
 
 /*
  * Valid flags for a dirty buffer
@@ -39,7 +38,7 @@ struct nfs_page {
        struct page             *wb_page;       /* page to read in/write out */
        struct nfs_open_context *wb_context;    /* File state context info */
        atomic_t                wb_complete;    /* i/os we're waiting for */
-       unsigned long           wb_index;       /* Offset >> PAGE_CACHE_SHIFT */
+       pgoff_t                 wb_index;       /* Offset >> PAGE_CACHE_SHIFT */
        unsigned int            wb_offset,      /* Offset & ~PAGE_CACHE_MASK */
                                wb_pgbase,      /* Start of page data */
                                wb_bytes;       /* Length of request */
@@ -48,6 +47,19 @@ struct nfs_page {
        struct nfs_writeverf    wb_verf;        /* Commit cookie */
 };
 
+struct nfs_pageio_descriptor {
+       struct list_head        pg_list;
+       unsigned long           pg_bytes_written;
+       size_t                  pg_count;
+       size_t                  pg_bsize;
+       unsigned int            pg_base;
+
+       struct inode            *pg_inode;
+       int                     (*pg_doio)(struct inode *, struct list_head *, unsigned int, size_t, int);
+       int                     pg_ioflags;
+       int                     pg_error;
+};
+
 #define NFS_WBACK_BUSY(req)    (test_bit(PG_BUSY,&(req)->wb_flags))
 
 extern struct nfs_page *nfs_create_request(struct nfs_open_context *ctx,
@@ -59,13 +71,16 @@ extern      void nfs_clear_request(struct nfs_page *req);
 extern void nfs_release_request(struct nfs_page *req);
 
 
-extern long nfs_scan_dirty(struct address_space *mapping,
-                               struct writeback_control *wbc,
-                               struct list_head *dst);
 extern int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head, struct list_head *dst,
-                         unsigned long idx_start, unsigned int npages);
-extern int nfs_coalesce_requests(struct list_head *, struct list_head *,
-                                 unsigned int);
+                         pgoff_t idx_start, unsigned int npages);
+extern void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
+                            struct inode *inode,
+                            int (*doio)(struct inode *, struct list_head *, unsigned int, size_t, int),
+                            size_t bsize,
+                            int how);
+extern int nfs_pageio_add_request(struct nfs_pageio_descriptor *,
+                                  struct nfs_page *);
+extern void nfs_pageio_complete(struct nfs_pageio_descriptor *desc);
 extern  int nfs_wait_on_request(struct nfs_page *);
 extern void nfs_unlock_request(struct nfs_page *req);
 extern  int nfs_set_page_writeback_locked(struct nfs_page *req);
index 870e66a..cdb3e9b 100644 (file)
@@ -28,18 +28,18 @@ enum nubus_category {
 };
 
 enum nubus_type_network {
-       NUBUS_TYPE_ETHERNET      = 0x0001,
-       NUBUS_TYPE_RS232         = 0x0002
+       NUBUS_TYPE_ETHERNET      = 0x0001,
+       NUBUS_TYPE_RS232         = 0x0002
 };
 
 enum nubus_type_display {
-       NUBUS_TYPE_VIDEO         = 0x0001
+       NUBUS_TYPE_VIDEO         = 0x0001
 };
 
 enum nubus_type_cpu {
-       NUBUS_TYPE_68020         = 0x0003,
-       NUBUS_TYPE_68030         = 0x0004,
-       NUBUS_TYPE_68040         = 0x0005
+       NUBUS_TYPE_68020         = 0x0003,
+       NUBUS_TYPE_68030         = 0x0004,
+       NUBUS_TYPE_68040         = 0x0005
 };
 
 /* Known <Cat,Type,SW,HW> tuples: (according to TattleTech and Slots)
@@ -56,6 +56,7 @@ enum nubus_type_cpu {
  *
  *  SONIC comm-slot/on-board and DuoDock Ethernet: <4,1,1,272>
  *  SONIC LC-PDS Ethernet (Dayna, but like Apple 16-bit, sort of): <4,1,1,271>
+ *  Apple SONIC LC-PDS Ethernet ("Apple Ethernet LC Twisted-Pair Card"): <4,1,0,281>
  *  Sonic Systems Ethernet A-Series Card: <4,1,268,256>
  *  Asante MacCon NuBus-A: <4,1,260,256> (alpha-1.0,1.1 revision)
  *   ROM on the above card: <2,1,0,0>
@@ -80,24 +81,26 @@ enum nubus_type_cpu {
 /* Add known DrSW values here */
 enum nubus_drsw {
        /* NUBUS_CAT_DISPLAY */
-       NUBUS_DRSW_APPLE        = 0x0001,
-       NUBUS_DRSW_APPLE_HIRES  = 0x0013, /* MacII HiRes card driver */
+       NUBUS_DRSW_APPLE        = 0x0001,
+       NUBUS_DRSW_APPLE_HIRES  = 0x0013, /* MacII HiRes card driver */
        
        /* NUBUS_CAT_NETWORK */
-       NUBUS_DRSW_CABLETRON    = 0x0001,
-       NUBUS_DRSW_SONIC_LC     = 0x0001,
-       NUBUS_DRSW_KINETICS     = 0x0103,
-       NUBUS_DRSW_ASANTE       = 0x0104,
-       NUBUS_DRSW_DAYNA        = 0x010b,
-       NUBUS_DRSW_FARALLON     = 0x010c,
-       NUBUS_DRSW_APPLE_SN     = 0x010f,
-       NUBUS_DRSW_DAYNA2       = 0x0115,
+       NUBUS_DRSW_3COM         = 0x0000,
+       NUBUS_DRSW_CABLETRON    = 0x0001,
+       NUBUS_DRSW_SONIC_LC     = 0x0001,
+       NUBUS_DRSW_KINETICS     = 0x0103,
+       NUBUS_DRSW_ASANTE       = 0x0104,
+       NUBUS_DRSW_TECHWORKS    = 0x0109,
+       NUBUS_DRSW_DAYNA        = 0x010b,
+       NUBUS_DRSW_FARALLON     = 0x010c,
+       NUBUS_DRSW_APPLE_SN     = 0x010f,
+       NUBUS_DRSW_DAYNA2       = 0x0115,
        NUBUS_DRSW_FOCUS        = 0x011a,
        NUBUS_DRSW_ASANTE_CS    = 0x011d, /* use asante SMC9194 driver */
-       NUBUS_DRSW_DAYNA_LC     = 0x011e,
+       NUBUS_DRSW_DAYNA_LC     = 0x011e,
 
        /* NUBUS_CAT_CPU */
-       NUBUS_DRSW_NONE         = 0x0000,
+       NUBUS_DRSW_NONE         = 0x0000,
 };
 
 /* DrHW: Uniquely identifies the hardware interface to a board (or at
@@ -107,27 +110,48 @@ enum nubus_drsw {
 /* Add known DrHW values here */
 enum nubus_drhw {
        /* NUBUS_CAT_DISPLAY */
-       NUBUS_DRHW_APPLE_TFB    = 0x0001, /* Toby frame buffer card */
-       NUBUS_DRHW_APPLE_HRVC   = 0x0013, /* Mac II High Res Video card */
-       NUBUS_DRHW_APPLE_RBV1   = 0x0018, /* IIci RBV video */
-       NUBUS_DRHW_APPLE_MDC    = 0x0019, /* Macintosh Display Card */
-       NUBUS_DRHW_APPLE_SONORA = 0x0022, /* Sonora built-in video */
-       NUBUS_DRHW_APPLE_JET    = 0x0029, /* Jet framebuffer (DuoDock) */
+       NUBUS_DRHW_APPLE_TFB      = 0x0001, /* Toby frame buffer card */
+       NUBUS_DRHW_APPLE_WVC      = 0x0006, /* Apple Workstation Video Card */
+       NUBUS_DRHW_SIGMA_CLRMAX   = 0x0007, /* Sigma Design ColorMax */
+       NUBUS_DRHW_APPLE_SE30     = 0x0009, /* Apple SE/30 video */
+       NUBUS_DRHW_APPLE_HRVC     = 0x0013, /* Mac II High-Res Video Card */
+       NUBUS_DRHW_APPLE_PVC      = 0x0017, /* Mac II Portrait Video Card */
+       NUBUS_DRHW_APPLE_RBV1     = 0x0018, /* IIci RBV video */
+       NUBUS_DRHW_APPLE_MDC      = 0x0019, /* Macintosh Display Card */
+       NUBUS_DRHW_APPLE_SONORA   = 0x0022, /* Sonora built-in video */
+       NUBUS_DRHW_APPLE_24AC     = 0x002b, /* Mac 24AC Video Card */
        NUBUS_DRHW_APPLE_VALKYRIE = 0x002e,
-       NUBUS_DRHW_THUNDER24    = 0x02cb, /* SuperMac Thunder/24 */
+       NUBUS_DRHW_APPLE_JET      = 0x0029, /* Jet framebuffer (DuoDock) */
+       NUBUS_DRHW_SMAC_GFX       = 0x0105, /* SuperMac GFX */
+       NUBUS_DRHW_RASTER_CB264   = 0x013B, /* RasterOps ColorBoard 264 */
+       NUBUS_DRHW_MICRON_XCEED   = 0x0146, /* Micron Exceed color */
+       NUBUS_DRHW_RDIUS_GSC      = 0x0153, /* Radius GS/C */
+       NUBUS_DRHW_SMAC_SPEC8     = 0x017B, /* SuperMac Spectrum/8 */
+       NUBUS_DRHW_SMAC_SPEC24    = 0x017C, /* SuperMac Spectrum/24 */
+       NUBUS_DRHW_RASTER_CB364   = 0x026F, /* RasterOps ColorBoard 364 */
+       NUBUS_DRHW_RDIUS_DCGX     = 0x027C, /* Radius DirectColor/GX */
+       NUBUS_DRHW_RDIUS_PC8      = 0x0291, /* Radius PrecisionColor 8 */
+       NUBUS_DRHW_LAPIS_PCS8     = 0x0292, /* Lapis ProColorServer 8 */
+       NUBUS_DRHW_RASTER_24LXI   = 0x02A0, /* RasterOps 8/24 XLi */
+       NUBUS_DRHW_RASTER_PBPGT   = 0x02A5, /* RasterOps PaintBoard Prism GT */
+       NUBUS_DRHW_EMACH_FSX      = 0x02AE, /* E-Machines Futura SX */
+       NUBUS_DRHW_SMAC_THUND24   = 0x02CB, /* SuperMac Thunder/24 */
+       NUBUS_DRHW_RDIUS_PC24XP   = 0x0406, /* Radius PrecisionColor 24Xp */
+       NUBUS_DRHW_RDIUS_PC24X    = 0x040A, /* Radius PrecisionColor 24X */
+       NUBUS_DRHW_RDIUS_PC8XJ    = 0x040B, /* Radius PrecisionColor 8XJ */
        
        /* NUBUS_CAT_NETWORK */
-       NUBUS_DRHW_INTERLAN     = 0x0100,
-       NUBUS_DRHW_SMC9194      = 0x0101,
-       NUBUS_DRHW_KINETICS     = 0x0106,
-       NUBUS_DRHW_CABLETRON    = 0x0109,
-       NUBUS_DRHW_ASANTE_LC    = 0x010f,
-       NUBUS_DRHW_SONIC        = 0x0110,
-       NUBUS_DRHW_SONIC_NB     = 0x0118,
-       NUBUS_DRHW_SONIC_LC     = 0x0119,
-       
-       /* NUBUS_CAT_COMMUNICATIONS */
-       NUBUS_DRHW_DOVEFAX      = 0x0100,
+       NUBUS_DRHW_INTERLAN       = 0x0100,
+       NUBUS_DRHW_SMC9194        = 0x0101,
+       NUBUS_DRHW_KINETICS       = 0x0106,
+       NUBUS_DRHW_CABLETRON      = 0x0109,
+       NUBUS_DRHW_ASANTE_LC      = 0x010f,
+       NUBUS_DRHW_SONIC          = 0x0110,
+       NUBUS_DRHW_TECHWORKS      = 0x0112,
+       NUBUS_DRHW_APPLE_SONIC_NB = 0x0118,
+       NUBUS_DRHW_APPLE_SONIC_LC = 0x0119,
+       NUBUS_DRHW_FOCUS          = 0x011c,
+       NUBUS_DRHW_SONNET         = 0x011d,
 };
 
 /* Resource IDs: These are the identifiers for the various weird and
@@ -153,17 +177,17 @@ enum nubus_res_id {
 
 /* Category-specific resources. */
 enum nubus_board_res_id {
-       NUBUS_RESID_BOARDID      = 0x0020,
+       NUBUS_RESID_BOARDID      = 0x0020,
        NUBUS_RESID_PRAMINITDATA = 0x0021,
-       NUBUS_RESID_PRIMARYINIT  = 0x0022,
+       NUBUS_RESID_PRIMARYINIT  = 0x0022,
        NUBUS_RESID_TIMEOUTCONST = 0x0023,
-       NUBUS_RESID_VENDORINFO   = 0x0024,
-       NUBUS_RESID_BOARDFLAGS   = 0x0025,
-       NUBUS_RESID_SECONDINIT   = 0x0026,
+       NUBUS_RESID_VENDORINFO   = 0x0024,
+       NUBUS_RESID_BOARDFLAGS   = 0x0025,
+       NUBUS_RESID_SECONDINIT   = 0x0026,
 
        /* Not sure why Apple put these next two in here */
-       NUBUS_RESID_VIDNAMES     = 0x0041,
-       NUBUS_RESID_VIDMODES     = 0x007e
+       NUBUS_RESID_VIDNAMES     = 0x0041,
+       NUBUS_RESID_VIDMODES     = 0x007e
 };
 
 /* Fields within the vendor info directory */
@@ -185,13 +209,13 @@ enum nubus_cpu_res_id {
 };
 
 enum nubus_display_res_id {
-       NUBUS_RESID_GAMMADIR    = 0x0040,
-       NUBUS_RESID_FIRSTMODE   = 0x0080,
-       NUBUS_RESID_SECONDMODE  = 0x0081,
-       NUBUS_RESID_THIRDMODE   = 0x0082,
-       NUBUS_RESID_FOURTHMODE  = 0x0083,
-       NUBUS_RESID_FIFTHMODE   = 0x0084,
-       NUBUS_RESID_SIXTHMODE   = 0x0085
+       NUBUS_RESID_GAMMADIR    = 0x0040,
+       NUBUS_RESID_FIRSTMODE   = 0x0080,
+       NUBUS_RESID_SECONDMODE  = 0x0081,
+       NUBUS_RESID_THIRDMODE   = 0x0082,
+       NUBUS_RESID_FOURTHMODE  = 0x0083,
+       NUBUS_RESID_FIFTHMODE   = 0x0084,
+       NUBUS_RESID_SIXTHMODE   = 0x0085
 };
 
 struct nubus_dir
@@ -214,7 +238,7 @@ struct nubus_board {
        struct nubus_board* next;
        struct nubus_dev* first_dev;
        
-        /* Only 9-E actually exist, though 0-8 are also theoretically
+       /* Only 9-E actually exist, though 0-8 are also theoretically
           possible, and 0 is a special case which represents the
           motherboard and onboard peripherals (Ethernet, video) */
        int slot;
index fa33328..26b2bdf 100644 (file)
@@ -11,7 +11,7 @@
 /* associates an integer enumerator with a pattern string. */
 struct match_token {
        int token;
-       char *pattern;
+       const char *pattern;
 };
 
 typedef struct match_token match_table_t[];
@@ -29,5 +29,5 @@ int match_token(char *, match_table_t table, substring_t args[]);
 int match_int(substring_t *, int *result);
 int match_octal(substring_t *, int *result);
 int match_hex(substring_t *, int *result);
-void match_strcpy(char *, substring_t *);
-char *match_strdup(substring_t *);
+void match_strcpy(char *, const substring_t *);
+char *match_strdup(const substring_t *);
index 9724910..fbf3766 100644 (file)
@@ -96,6 +96,19 @@ enum pci_channel_state {
        pci_channel_io_perm_failure = (__force pci_channel_state_t) 3,
 };
 
+typedef unsigned int __bitwise pcie_reset_state_t;
+
+enum pcie_reset_state {
+       /* Reset is NOT asserted (Use to deassert reset) */
+       pcie_deassert_reset = (__force pcie_reset_state_t) 1,
+
+       /* Use #PERST to reset PCI-E device */
+       pcie_warm_reset = (__force pcie_reset_state_t) 2,
+
+       /* Use PCI-E Hot Reset to reset device */
+       pcie_hot_reset = (__force pcie_reset_state_t) 3
+};
+
 typedef unsigned short __bitwise pci_bus_flags_t;
 enum pci_bus_flags {
        PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1,
@@ -176,10 +189,12 @@ struct pci_dev {
        int rom_attr_enabled;           /* has display of the rom attribute been enabled? */
        struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */
 #ifdef CONFIG_PCI_MSI
-       unsigned int first_msi_irq;
+       struct list_head msi_list;
 #endif
 };
 
+extern struct pci_dev *alloc_pci_dev(void);
+
 #define pci_dev_g(n) list_entry(n, struct pci_dev, global_list)
 #define pci_dev_b(n) list_entry(n, struct pci_dev, bus_list)
 #define        to_pci_dev(n) container_of(n, struct pci_dev, dev)
@@ -392,12 +407,6 @@ struct pci_driver {
        .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \
        .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID
 
-/*
- * pci_module_init is obsolete, this stays here till we fix up all usages of it
- * in the tree.
- */
-#define pci_module_init        pci_register_driver
-
 /**
  * PCI_VDEVICE - macro used to describe a specific pci device in short form
  * @vend: the vendor name
@@ -532,6 +541,7 @@ static inline int pci_is_managed(struct pci_dev *pdev)
 
 void pci_disable_device(struct pci_dev *dev);
 void pci_set_master(struct pci_dev *dev);
+int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state);
 #define HAVE_PCI_SET_MWI
 int __must_check pci_set_mwi(struct pci_dev *dev);
 void pci_clear_mwi(struct pci_dev *dev);
@@ -730,6 +740,9 @@ static inline int pci_set_power_state(struct pci_dev *dev, pci_power_t state) {
 static inline pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) { return PCI_D0; }
 static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) { return 0; }
 
+static inline int pci_request_regions(struct pci_dev *dev, const char *res_name) { return -EIO; }
+static inline void pci_release_regions(struct pci_dev *dev) { }
+
 #define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0)
 
 static inline void pci_block_user_cfg_access(struct pci_dev *dev) { }
index a675a05..ab4cb6e 100644 (file)
@@ -174,7 +174,7 @@ extern int pci_hp_register          (struct hotplug_slot *slot);
 extern int pci_hp_deregister           (struct hotplug_slot *slot);
 extern int __must_check pci_hp_change_slot_info        (struct hotplug_slot *slot,
                                                 struct hotplug_slot_info *info);
-extern struct subsystem pci_hotplug_slots_subsys;
+extern struct kset pci_hotplug_slots_subsys;
 
 /* PCI Setting Record (Type 0) */
 struct hpp_type0 {
index 1b0ddbb..ae849f0 100644 (file)
 #define PCI_DEVICE_ID_NVIDIA_NVENET_16              0x03E5
 #define PCI_DEVICE_ID_NVIDIA_NVENET_17              0x03E6
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA      0x03E7
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS            0x03EB
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE       0x03EC
 #define PCI_DEVICE_ID_NVIDIA_NVENET_18              0x03EE
 #define PCI_DEVICE_ID_NVIDIA_NVENET_19              0x03EF
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2     0x03F6
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3     0x03F7
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS            0x0446
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE      0x0448
 #define PCI_DEVICE_ID_NVIDIA_NVENET_20              0x0450
 #define PCI_DEVICE_ID_NVIDIA_NVENET_21              0x0451
 #define PCI_DEVICE_ID_TIGON3_5752      0x1600
 #define PCI_DEVICE_ID_TIGON3_5752M     0x1601
 #define PCI_DEVICE_ID_NX2_5709         0x1639
+#define PCI_DEVICE_ID_NX2_5709S                0x163a
 #define PCI_DEVICE_ID_TIGON3_5700      0x1644
 #define PCI_DEVICE_ID_TIGON3_5701      0x1645
 #define PCI_DEVICE_ID_TIGON3_5702      0x1646
index 253a2b9..e7367c7 100644 (file)
@@ -197,7 +197,7 @@ typedef unsigned char *sk_buff_data_t;
  *     @tstamp: Time we arrived
  *     @dev: Device we arrived on/are leaving by
  *     @iif: ifindex of device we arrived on
- *     @h: Transport layer header
+ *     @transport_header: Transport layer header
  *     @network_header: Network layer header
  *     @mac_header: Link layer header
  *     @dst: destination entry
index c7a78ee..6661142 100644 (file)
@@ -84,7 +84,8 @@ struct rpc_procinfo {
        u32                     p_proc;         /* RPC procedure number */
        kxdrproc_t              p_encode;       /* XDR encode function */
        kxdrproc_t              p_decode;       /* XDR decode function */
-       unsigned int            p_bufsiz;       /* req. buffer size */
+       unsigned int            p_arglen;       /* argument hdr length (u32) */
+       unsigned int            p_replen;       /* reply hdr length (u32) */
        unsigned int            p_count;        /* call count */
        unsigned int            p_timer;        /* Which RTT timer to use */
        u32                     p_statidx;      /* Which procedure to account */
@@ -121,8 +122,8 @@ struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
 int            rpc_shutdown_client(struct rpc_clnt *);
 int            rpc_destroy_client(struct rpc_clnt *);
 void           rpc_release_client(struct rpc_clnt *);
-void           rpc_getport(struct rpc_task *);
-int            rpc_register(u32, u32, int, unsigned short, int *);
+int            rpcb_register(u32, u32, int, unsigned short, int *);
+void           rpcb_getport(struct rpc_task *);
 
 void           rpc_call_setup(struct rpc_task *, struct rpc_message *, int);
 
@@ -144,7 +145,7 @@ char *              rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t);
 /*
  * Helper function for NFSroot support
  */
-int            rpc_getport_external(struct sockaddr_in *, __u32, __u32, int);
+int            rpcb_getport_external(struct sockaddr_in *, __u32, __u32, int);
 
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SUNRPC_CLNT_H */
index b7c7307..3912cf1 100644 (file)
@@ -17,7 +17,7 @@
 #define RPCDBG_DEBUG           0x0004
 #define RPCDBG_NFS             0x0008
 #define RPCDBG_AUTH            0x0010
-#define RPCDBG_PMAP            0x0020
+#define RPCDBG_BIND            0x0020
 #define RPCDBG_SCHED           0x0040
 #define RPCDBG_TRANS           0x0080
 #define RPCDBG_SVCSOCK         0x0100
index 606cb21..784d4c3 100644 (file)
@@ -78,10 +78,6 @@ enum rpc_auth_stat {
        RPCSEC_GSS_CTXPROBLEM = 14
 };
 
-#define RPC_PMAP_PROGRAM       100000
-#define RPC_PMAP_VERSION       2
-#define RPC_PMAP_PORT          111
-
 #define RPC_MAXNETNAMELEN      256
 
 /*
index 3069ecc..2047fb2 100644 (file)
@@ -264,7 +264,7 @@ struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *);
 void           rpc_wake_up_status(struct rpc_wait_queue *, int);
 void           rpc_delay(struct rpc_task *, unsigned long);
 void *         rpc_malloc(struct rpc_task *, size_t);
-void           rpc_free(struct rpc_task *);
+void           rpc_free(void *);
 int            rpciod_up(void);
 void           rpciod_down(void);
 int            __rpc_wait_for_completion_task(struct rpc_task *task, int (*)(void *));
index f780e72..fa89ce6 100644 (file)
@@ -84,7 +84,9 @@ struct rpc_rqst {
        struct list_head        rq_list;
 
        __u32 *                 rq_buffer;      /* XDR encode buffer */
-       size_t                  rq_bufsize;
+       size_t                  rq_bufsize,
+                               rq_callsize,
+                               rq_rcvsize;
 
        struct xdr_buf          rq_private_buf;         /* The receive buffer
                                                         * used in the softirq.
@@ -112,7 +114,7 @@ struct rpc_xprt_ops {
        void            (*set_port)(struct rpc_xprt *xprt, unsigned short port);
        void            (*connect)(struct rpc_task *task);
        void *          (*buf_alloc)(struct rpc_task *task, size_t size);
-       void            (*buf_free)(struct rpc_task *task);
+       void            (*buf_free)(void *buffer);
        int             (*send_request)(struct rpc_task *task);
        void            (*set_retrans_timeout)(struct rpc_task *task);
        void            (*timer)(struct rpc_task *task);
@@ -150,6 +152,7 @@ struct rpc_xprt {
        unsigned long           state;          /* transport state */
        unsigned char           shutdown   : 1, /* being shut down */
                                resvport   : 1; /* use a reserved port */
+       unsigned int            bind_index;     /* bind function index */
 
        /*
         * Connection of transports
index 3deb0a6..2a19698 100644 (file)
 
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
-#include <linux/wait.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
-#include <linux/kthread.h>
+#include <linux/workqueue.h>
 
 /* Host registers (relative to pci base address): */
 enum {
        FM_SET_INTERRUPT_ENABLE   = 0x008,
        FM_CLEAR_INTERRUPT_ENABLE = 0x00c,
-       FM_INTERRUPT_STATUS       = 0x014 };
+       FM_INTERRUPT_STATUS       = 0x014
+};
 
 /* Socket registers (relative to socket base address): */
 enum {
@@ -58,14 +58,8 @@ enum {
        SOCK_MS_DATA                   = 0x188,
        SOCK_MS_STATUS                 = 0x18c,
        SOCK_MS_SYSTEM                 = 0x190,
-       SOCK_FIFO_ACCESS               = 0x200 };
-
-
-#define TIFM_IRQ_ENABLE           0x80000000
-#define TIFM_IRQ_SOCKMASK(x)      (x)
-#define TIFM_IRQ_CARDMASK(x)      ((x) << 8)
-#define TIFM_IRQ_FIFOMASK(x)      ((x) << 16)
-#define TIFM_IRQ_SETALL           0xffffffff
+       SOCK_FIFO_ACCESS               = 0x200
+};
 
 #define TIFM_CTRL_LED             0x00000040
 #define TIFM_CTRL_FAST_CLK        0x00000100
@@ -73,63 +67,76 @@ enum {
 #define TIFM_SOCK_STATE_OCCUPIED  0x00000008
 #define TIFM_SOCK_STATE_POWERED   0x00000080
 
-#define TIFM_FIFO_ENABLE          0x00000001 /* Meaning of this constant is unverified */
+#define TIFM_FIFO_ENABLE          0x00000001
+#define TIFM_FIFO_READY           0x00000001
 #define TIFM_FIFO_INT_SETALL      0x0000ffff
-#define TIFM_FIFO_INTMASK         0x00000005 /* Meaning of this constant is unverified */
+#define TIFM_FIFO_INTMASK         0x00000005
+
+#define TIFM_DMA_RESET            0x00000002
+#define TIFM_DMA_TX               0x00008000
+#define TIFM_DMA_EN               0x00000001
+#define TIFM_DMA_TSIZE            0x0000007f
 
-#define TIFM_DMA_RESET            0x00000002 /* Meaning of this constant is unverified */
-#define TIFM_DMA_TX               0x00008000 /* Meaning of this constant is unverified */
-#define TIFM_DMA_EN               0x00000001 /* Meaning of this constant is unverified */
+#define TIFM_TYPE_XD 1
+#define TIFM_TYPE_MS 2
+#define TIFM_TYPE_SD 3
 
-typedef enum {FM_NULL = 0, FM_XD = 0x01, FM_MS = 0x02, FM_SD = 0x03} tifm_media_id;
+struct tifm_device_id {
+       unsigned char type;
+};
 
 struct tifm_driver;
 struct tifm_dev {
-       char __iomem            *addr;
-       spinlock_t              lock;
-       tifm_media_id           media_id;
-       unsigned int            socket_id;
+       char __iomem  *addr;
+       spinlock_t    lock;
+       unsigned char type;
+       unsigned int  socket_id;
 
-       void                    (*signal_irq)(struct tifm_dev *sock,
-                                             unsigned int sock_irq_status);
+       void          (*card_event)(struct tifm_dev *sock);
+       void          (*data_event)(struct tifm_dev *sock);
 
-       struct tifm_driver      *drv;
-       struct device           dev;
+       struct device dev;
 };
 
 struct tifm_driver {
-       tifm_media_id        *id_table;
-       int                  (*probe)(struct tifm_dev *dev);
-       void                 (*remove)(struct tifm_dev *dev);
-       int                  (*suspend)(struct tifm_dev *dev,
-                                        pm_message_t state);
-       int                  (*resume)(struct tifm_dev *dev);
-
-       struct device_driver driver;
+       struct tifm_device_id *id_table;
+       int                   (*probe)(struct tifm_dev *dev);
+       void                  (*remove)(struct tifm_dev *dev);
+       int                   (*suspend)(struct tifm_dev *dev,
+                                        pm_message_t state);
+       int                   (*resume)(struct tifm_dev *dev);
+
+       struct device_driver  driver;
 };
 
 struct tifm_adapter {
-       char __iomem            *addr;
-       spinlock_t              lock;
-       unsigned int            irq_status;
-       unsigned int            socket_change_set;
-       wait_queue_head_t       change_set_notify;
-       unsigned int            id;
-       unsigned int            num_sockets;
-       struct tifm_dev         **sockets;
-       struct task_struct      *media_switcher;
-       struct class_device     cdev;
-       struct device           *dev;
-
-       void                    (*eject)(struct tifm_adapter *fm, struct tifm_dev *sock);
+       char __iomem        *addr;
+       spinlock_t          lock;
+       unsigned int        irq_status;
+       unsigned int        socket_change_set;
+       unsigned int        id;
+       unsigned int        num_sockets;
+       struct completion   *finish_me;
+
+       struct work_struct  media_switcher;
+       struct class_device cdev;
+
+       void                (*eject)(struct tifm_adapter *fm,
+                                    struct tifm_dev *sock);
+
+       struct tifm_dev     *sockets[0];
 };
 
-struct tifm_adapter *tifm_alloc_adapter(void);
-void tifm_free_device(struct device *dev);
-void tifm_free_adapter(struct tifm_adapter *fm);
-int tifm_add_adapter(struct tifm_adapter *fm, int (*mediathreadfn)(void *data));
+struct tifm_adapter *tifm_alloc_adapter(unsigned int num_sockets,
+                                       struct device *dev);
+int tifm_add_adapter(struct tifm_adapter *fm);
 void tifm_remove_adapter(struct tifm_adapter *fm);
-struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm);
+void tifm_free_adapter(struct tifm_adapter *fm);
+
+void tifm_free_device(struct device *dev);
+struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id,
+                                  unsigned char type);
+
 int tifm_register_driver(struct tifm_driver *drv);
 void tifm_unregister_driver(struct tifm_driver *drv);
 void tifm_eject(struct tifm_dev *sock);
@@ -137,11 +144,11 @@ int tifm_map_sg(struct tifm_dev *sock, struct scatterlist *sg, int nents,
                int direction);
 void tifm_unmap_sg(struct tifm_dev *sock, struct scatterlist *sg, int nents,
                   int direction);
-
+void tifm_queue_work(struct work_struct *work);
 
 static inline void *tifm_get_drvdata(struct tifm_dev *dev)
 {
-        return dev_get_drvdata(&dev->dev);
+       return dev_get_drvdata(&dev->dev);
 }
 
 static inline void tifm_set_drvdata(struct tifm_dev *dev, void *data)
@@ -149,8 +156,4 @@ static inline void tifm_set_drvdata(struct tifm_dev *dev, void *data)
        dev_set_drvdata(&dev->dev, data);
 }
 
-struct tifm_device_id {
-       tifm_media_id media_id;
-};
-
 #endif
index 0c78f7f..daa6c12 100644 (file)
@@ -59,6 +59,8 @@ struct writeback_control {
        unsigned for_reclaim:1;         /* Invoked from the page allocator */
        unsigned for_writepages:1;      /* This is a writepages() call */
        unsigned range_cyclic:1;        /* range_start is cyclic */
+
+       void *fs_private;               /* For use by ->writepages() */
 };
 
 /*
index a5d53e0..b58adc5 100644 (file)
@@ -243,17 +243,6 @@ enum xfrm_ae_ftype_t {
 #define XFRM_AE_MAX (__XFRM_AE_MAX - 1)
 };
 
-/* SAD Table filter flags  */
-enum xfrm_sad_ftype_t {
-       XFRM_SAD_UNSPEC,
-       XFRM_SAD_HMASK=1,
-       XFRM_SAD_HMAX=2,
-       XFRM_SAD_CNT=4,
-       __XFRM_SAD_MAX
-
-#define XFRM_SAD_MAX (__XFRM_SAD_MAX - 1)
-};
-
 struct xfrm_userpolicy_type {
        __u8            type;
        __u16           reserved1;
@@ -287,44 +276,41 @@ enum xfrm_attr_type_t {
 
 enum xfrm_sadattr_type_t {
        XFRMA_SAD_UNSPEC,
-       XFRMA_SADHMASK,
-       XFRMA_SADHMAX,
-       XFRMA_SADCNT,
+       XFRMA_SAD_CNT,
+       XFRMA_SAD_HINFO,
        __XFRMA_SAD_MAX
 
 #define XFRMA_SAD_MAX (__XFRMA_SAD_MAX - 1)
 };
 
-/* SPD Table filter flags  */
-enum xfrm_spd_ftype_t {
-       XFRM_SPD_UNSPEC,
-       XFRM_SPD_HMASK=1,
-       XFRM_SPD_HMAX=2,
-       XFRM_SPD_ICNT=4,
-       XFRM_SPD_OCNT=8,
-       XFRM_SPD_FCNT=16,
-       XFRM_SPD_ISCNT=32,
-       XFRM_SPD_OSCNT=64,
-       XFRM_SPD_FSCNT=128,
-       __XFRM_SPD_MAX
-
-#define XFRM_SPD_MAX (__XFRM_SPD_MAX - 1)
+struct xfrmu_sadhinfo {
+       __u32 sadhcnt; /* current hash bkts */
+       __u32 sadhmcnt; /* max allowed hash bkts */
 };
+
 enum xfrm_spdattr_type_t {
        XFRMA_SPD_UNSPEC,
-       XFRMA_SPDHMASK,
-       XFRMA_SPDHMAX,
-       XFRMA_SPDICNT,
-       XFRMA_SPDOCNT,
-       XFRMA_SPDFCNT,
-       XFRMA_SPDISCNT,
-       XFRMA_SPDOSCNT,
-       XFRMA_SPDFSCNT,
+       XFRMA_SPD_INFO,
+       XFRMA_SPD_HINFO,
        __XFRMA_SPD_MAX
 
 #define XFRMA_SPD_MAX (__XFRMA_SPD_MAX - 1)
 };
 
+struct xfrmu_spdinfo {
+       __u32 incnt;
+       __u32 outcnt;
+       __u32 fwdcnt;
+       __u32 inscnt;
+       __u32 outscnt;
+       __u32 fwdscnt;
+};
+
+struct xfrmu_spdhinfo {
+       __u32 spdhcnt;
+       __u32 spdhmcnt;
+};
+
 struct xfrm_usersa_info {
        struct xfrm_selector            sel;
        struct xfrm_id                  id;
index 0f43451..05b9569 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
-#include <linux/i2c.h>
 
 /* --------------------------------- */
 /*           ENUMERATIONS            */
index a41ac41..6dcf3c4 100644 (file)
@@ -23,6 +23,7 @@
 #define _TUNER_H
 
 #include <linux/videodev2.h>
+#include <linux/i2c.h>
 #include <media/tuner-types.h>
 
 extern int tuner_debug;
index f70afef..4fa5dfe 100644 (file)
@@ -204,9 +204,9 @@ struct ip6_flowlabel
 {
        struct ip6_flowlabel    *next;
        __be32                  label;
+       atomic_t                users;
        struct in6_addr         dst;
        struct ipv6_txoptions   *opt;
-       atomic_t                users;
        unsigned long           linger;
        u8                      share;
        u32                     owner;
@@ -291,7 +291,7 @@ static inline int ipv6_addr_src_scope(const struct in6_addr *addr)
 
 static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr *a2)
 {
-       return memcmp((const void *) a1, (const void *) a2, sizeof(struct in6_addr));
+       return memcmp(a1, a2, sizeof(struct in6_addr));
 }
 
 static inline int
@@ -308,7 +308,7 @@ ipv6_masked_addr_cmp(const struct in6_addr *a1, const struct in6_addr *m,
 
 static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2)
 {
-       memcpy((void *) a1, (const void *) a2, sizeof(struct in6_addr));
+       memcpy(a1, a2, sizeof(struct in6_addr));
 }
 
 static inline void ipv6_addr_prefix(struct in6_addr *pfx, 
@@ -319,16 +319,12 @@ static inline void ipv6_addr_prefix(struct in6_addr *pfx,
        int o = plen >> 3,
            b = plen & 0x7;
 
+       memset(pfx->s6_addr, 0, sizeof(pfx->s6_addr));
        memcpy(pfx->s6_addr, addr, o);
-       if (b != 0) {
+       if (b != 0)
                pfx->s6_addr[o] = addr->s6_addr[o] & (0xff00 >> b);
-               o++;
-       }
-       if (o < 16)
-               memset(pfx->s6_addr + o, 0, 16 - o);
 }
 
-#ifndef __HAVE_ARCH_ADDR_SET
 static inline void ipv6_addr_set(struct in6_addr *addr, 
                                     __be32 w1, __be32 w2,
                                     __be32 w3, __be32 w4)
@@ -338,7 +334,6 @@ static inline void ipv6_addr_set(struct in6_addr *addr,
        addr->s6_addr32[2] = w3;
        addr->s6_addr32[3] = w4;
 }
-#endif
 
 static inline int ipv6_addr_equal(const struct in6_addr *a1,
                                  const struct in6_addr *a2)
index 04d1abb..f9bd11b 100644 (file)
@@ -28,6 +28,7 @@ enum {
        IUCV_LISTEN,
        IUCV_SEVERED,
        IUCV_DISCONN,
+       IUCV_CLOSING,
        IUCV_CLOSED
 };
 
@@ -62,6 +63,7 @@ struct iucv_sock {
        struct sock             *parent;
        struct iucv_path        *path;
        struct sk_buff_head     send_skb_q;
+       struct sk_buff_head     backlog_skb_q;
        unsigned int            send_tag;
 };
 
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
new file mode 100644 (file)
index 0000000..a7f122b
--- /dev/null
@@ -0,0 +1,1045 @@
+/*
+ * Low-level hardware driver -- IEEE 802.11 driver (80211.o) interface
+ * Copyright 2002-2005, Devicescape Software, Inc.
+ * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MAC80211_H
+#define MAC80211_H
+
+#include <linux/kernel.h>
+#include <linux/if_ether.h>
+#include <linux/skbuff.h>
+#include <linux/wireless.h>
+#include <linux/device.h>
+#include <linux/ieee80211.h>
+#include <net/wireless.h>
+#include <net/cfg80211.h>
+
+/* Note! Only ieee80211_tx_status_irqsafe() and ieee80211_rx_irqsafe() can be
+ * called in hardware interrupt context. The low-level driver must not call any
+ * other functions in hardware interrupt context. If there is a need for such
+ * call, the low-level driver should first ACK the interrupt and perform the
+ * IEEE 802.11 code call after this, e.g., from a scheduled tasklet (in
+ * software interrupt context).
+ */
+
+/*
+ * Frame format used when passing frame between low-level hardware drivers
+ * and IEEE 802.11 driver the same as used in the wireless media, i.e.,
+ * buffers start with IEEE 802.11 header and include the same octets that
+ * are sent over air.
+ *
+ * If hardware uses IEEE 802.3 headers (and perform 802.3 <-> 802.11
+ * conversion in firmware), upper layer 802.11 code needs to be changed to
+ * support this.
+ *
+ * If the receive frame format is not the same as the real frame sent
+ * on the wireless media (e.g., due to padding etc.), upper layer 802.11 code
+ * could be updated to provide support for such format assuming this would
+ * optimize the performance, e.g., by removing need to re-allocation and
+ * copying of the data.
+ */
+
+#define IEEE80211_CHAN_W_SCAN 0x00000001
+#define IEEE80211_CHAN_W_ACTIVE_SCAN 0x00000002
+#define IEEE80211_CHAN_W_IBSS 0x00000004
+
+/* Channel information structure. Low-level driver is expected to fill in chan,
+ * freq, and val fields. Other fields will be filled in by 80211.o based on
+ * hostapd information and low-level driver does not need to use them. The
+ * limits for each channel will be provided in 'struct ieee80211_conf' when
+ * configuring the low-level driver with hw->config callback. If a device has
+ * a default regulatory domain, IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED
+ * can be set to let the driver configure all fields */
+struct ieee80211_channel {
+       short chan; /* channel number (IEEE 802.11) */
+       short freq; /* frequency in MHz */
+       int val; /* hw specific value for the channel */
+       int flag; /* flag for hostapd use (IEEE80211_CHAN_*) */
+       unsigned char power_level;
+       unsigned char antenna_max;
+};
+
+#define IEEE80211_RATE_ERP 0x00000001
+#define IEEE80211_RATE_BASIC 0x00000002
+#define IEEE80211_RATE_PREAMBLE2 0x00000004
+#define IEEE80211_RATE_SUPPORTED 0x00000010
+#define IEEE80211_RATE_OFDM 0x00000020
+#define IEEE80211_RATE_CCK 0x00000040
+#define IEEE80211_RATE_TURBO 0x00000080
+#define IEEE80211_RATE_MANDATORY 0x00000100
+
+#define IEEE80211_RATE_CCK_2 (IEEE80211_RATE_CCK | IEEE80211_RATE_PREAMBLE2)
+#define IEEE80211_RATE_MODULATION(f) \
+       (f & (IEEE80211_RATE_CCK | IEEE80211_RATE_OFDM))
+
+/* Low-level driver should set PREAMBLE2, OFDM, CCK, and TURBO flags.
+ * BASIC, SUPPORTED, ERP, and MANDATORY flags are set in 80211.o based on the
+ * configuration. */
+struct ieee80211_rate {
+       int rate; /* rate in 100 kbps */
+       int val; /* hw specific value for the rate */
+       int flags; /* IEEE80211_RATE_ flags */
+       int val2; /* hw specific value for the rate when using short preamble
+                  * (only when IEEE80211_RATE_PREAMBLE2 flag is set, i.e., for
+                  * 2, 5.5, and 11 Mbps) */
+       signed char min_rssi_ack;
+       unsigned char min_rssi_ack_delta;
+
+       /* following fields are set by 80211.o and need not be filled by the
+        * low-level driver */
+       int rate_inv; /* inverse of the rate (LCM(all rates) / rate) for
+                      * optimizing channel utilization estimates */
+};
+
+/* 802.11g is backwards-compatible with 802.11b, so a wlan card can
+ * actually be both in 11b and 11g modes at the same time. */
+enum {
+       MODE_IEEE80211A, /* IEEE 802.11a */
+       MODE_IEEE80211B, /* IEEE 802.11b only */
+       MODE_ATHEROS_TURBO, /* Atheros Turbo mode (2x.11a at 5 GHz) */
+       MODE_IEEE80211G, /* IEEE 802.11g (and 802.11b compatibility) */
+       MODE_ATHEROS_TURBOG, /* Atheros Turbo mode (2x.11g at 2.4 GHz) */
+
+       /* keep last */
+       NUM_IEEE80211_MODES
+};
+
+struct ieee80211_hw_mode {
+       int mode; /* MODE_IEEE80211... */
+       int num_channels; /* Number of channels (below) */
+       struct ieee80211_channel *channels; /* Array of supported channels */
+       int num_rates; /* Number of rates (below) */
+       struct ieee80211_rate *rates; /* Array of supported rates */
+
+       struct list_head list; /* Internal, don't touch */
+};
+
+struct ieee80211_tx_queue_params {
+       int aifs; /* 0 .. 255; -1 = use default */
+       int cw_min; /* 2^n-1: 1, 3, 7, .. , 1023; 0 = use default */
+       int cw_max; /* 2^n-1: 1, 3, 7, .. , 1023; 0 = use default */
+       int burst_time; /* maximum burst time in 0.1 ms (i.e., 10 = 1 ms);
+                        * 0 = disabled */
+};
+
+struct ieee80211_tx_queue_stats_data {
+       unsigned int len; /* num packets in queue */
+       unsigned int limit; /* queue len (soft) limit */
+       unsigned int count; /* total num frames sent */
+};
+
+enum {
+       IEEE80211_TX_QUEUE_DATA0,
+       IEEE80211_TX_QUEUE_DATA1,
+       IEEE80211_TX_QUEUE_DATA2,
+       IEEE80211_TX_QUEUE_DATA3,
+       IEEE80211_TX_QUEUE_DATA4,
+       IEEE80211_TX_QUEUE_SVP,
+
+       NUM_TX_DATA_QUEUES,
+
+/* due to stupidity in the sub-ioctl userspace interface, the items in
+ * this struct need to have fixed values. As soon as it is removed, we can
+ * fix these entries. */
+       IEEE80211_TX_QUEUE_AFTER_BEACON = 6,
+       IEEE80211_TX_QUEUE_BEACON = 7
+};
+
+struct ieee80211_tx_queue_stats {
+       struct ieee80211_tx_queue_stats_data data[NUM_TX_DATA_QUEUES];
+};
+
+struct ieee80211_low_level_stats {
+       unsigned int dot11ACKFailureCount;
+       unsigned int dot11RTSFailureCount;
+       unsigned int dot11FCSErrorCount;
+       unsigned int dot11RTSSuccessCount;
+};
+
+/* Transmit control fields. This data structure is passed to low-level driver
+ * with each TX frame. The low-level driver is responsible for configuring
+ * the hardware to use given values (depending on what is supported). */
+#define HW_KEY_IDX_INVALID -1
+
+struct ieee80211_tx_control {
+       int tx_rate; /* Transmit rate, given as the hw specific value for the
+                     * rate (from struct ieee80211_rate) */
+       int rts_cts_rate; /* Transmit rate for RTS/CTS frame, given as the hw
+                          * specific value for the rate (from
+                          * struct ieee80211_rate) */
+
+#define IEEE80211_TXCTL_REQ_TX_STATUS  (1<<0)/* request TX status callback for
+                                               * this frame */
+#define IEEE80211_TXCTL_DO_NOT_ENCRYPT (1<<1) /* send this frame without
+                                               * encryption; e.g., for EAPOL
+                                               * frames */
+#define IEEE80211_TXCTL_USE_RTS_CTS    (1<<2) /* use RTS-CTS before sending
+                                               * frame */
+#define IEEE80211_TXCTL_USE_CTS_PROTECT        (1<<3) /* use CTS protection for the
+                                               * frame (e.g., for combined
+                                               * 802.11g / 802.11b networks) */
+#define IEEE80211_TXCTL_NO_ACK         (1<<4) /* tell the low level not to
+                                               * wait for an ack */
+#define IEEE80211_TXCTL_RATE_CTRL_PROBE        (1<<5)
+#define IEEE80211_TXCTL_CLEAR_DST_MASK (1<<6)
+#define IEEE80211_TXCTL_REQUEUE                (1<<7)
+#define IEEE80211_TXCTL_FIRST_FRAGMENT (1<<8) /* this is a first fragment of
+                                               * the frame */
+#define IEEE80211_TXCTL_TKIP_NEW_PHASE1_KEY (1<<9)
+       u32 flags;                             /* tx control flags defined
+                                               * above */
+       u8 retry_limit;         /* 1 = only first attempt, 2 = one retry, .. */
+       u8 power_level;         /* per-packet transmit power level, in dBm */
+       u8 antenna_sel_tx;      /* 0 = default/diversity, 1 = Ant0, 2 = Ant1 */
+       s8 key_idx;             /* -1 = do not encrypt, >= 0 keyidx from
+                                * hw->set_key() */
+       u8 icv_len;             /* length of the ICV/MIC field in octets */
+       u8 iv_len;              /* length of the IV field in octets */
+       u8 tkip_key[16];        /* generated phase2/phase1 key for hw TKIP */
+       u8 queue;               /* hardware queue to use for this frame;
+                                * 0 = highest, hw->queues-1 = lowest */
+       u8 sw_retry_attempt;    /* number of times hw has tried to
+                                * transmit frame (not incl. hw retries) */
+
+       struct ieee80211_rate *rate;            /* internal 80211.o rate */
+       struct ieee80211_rate *rts_rate;        /* internal 80211.o rate
+                                                * for RTS/CTS */
+       int alt_retry_rate; /* retry rate for the last retries, given as the
+                            * hw specific value for the rate (from
+                            * struct ieee80211_rate). To be used to limit
+                            * packet dropping when probing higher rates, if hw
+                            * supports multiple retry rates. -1 = not used */
+       int type;       /* internal */
+       int ifindex;    /* internal */
+};
+
+/* Receive status. The low-level driver should provide this information
+ * (the subset supported by hardware) to the 802.11 code with each received
+ * frame. */
+struct ieee80211_rx_status {
+       u64 mactime;
+       int freq; /* receive frequency in Mhz */
+       int channel;
+       int phymode;
+       int ssi;
+       int signal; /* used as qual in statistics reporting */
+       int noise;
+       int antenna;
+       int rate;
+#define RX_FLAG_MMIC_ERROR     (1<<0)
+#define RX_FLAG_DECRYPTED      (1<<1)
+#define RX_FLAG_RADIOTAP       (1<<2)
+       int flag;
+};
+
+/* Transmit status. The low-level driver should provide this information
+ * (the subset supported by hardware) to the 802.11 code for each transmit
+ * frame. */
+struct ieee80211_tx_status {
+       /* copied ieee80211_tx_control structure */
+       struct ieee80211_tx_control control;
+
+#define IEEE80211_TX_STATUS_TX_FILTERED        (1<<0)
+#define IEEE80211_TX_STATUS_ACK                (1<<1) /* whether the TX frame was ACKed */
+       u32 flags;              /* tx staus flags defined above */
+
+       int ack_signal; /* measured signal strength of the ACK frame */
+       int excessive_retries;
+       int retry_count;
+
+       int queue_length;      /* information about TX queue */
+       int queue_number;
+};
+
+
+/**
+ * struct ieee80211_conf - configuration of the device
+ *
+ * This struct indicates how the driver shall configure the hardware.
+ *
+ * @radio_enabled: when zero, driver is required to switch off the radio.
+ */
+struct ieee80211_conf {
+       int channel;                    /* IEEE 802.11 channel number */
+       int freq;                       /* MHz */
+       int channel_val;                /* hw specific value for the channel */
+
+       int phymode;                    /* MODE_IEEE80211A, .. */
+       struct ieee80211_channel *chan;
+       struct ieee80211_hw_mode *mode;
+       unsigned int regulatory_domain;
+       int radio_enabled;
+
+       int beacon_int;
+
+#define IEEE80211_CONF_SHORT_SLOT_TIME (1<<0) /* use IEEE 802.11g Short Slot
+                                               * Time */
+#define IEEE80211_CONF_SSID_HIDDEN     (1<<1) /* do not broadcast the ssid */
+#define IEEE80211_CONF_RADIOTAP                (1<<2) /* use radiotap if supported
+                                                 check this bit at RX time */
+       u32 flags;                      /* configuration flags defined above */
+
+       u8 power_level;                 /* transmit power limit for current
+                                        * regulatory domain; in dBm */
+       u8 antenna_max;                 /* maximum antenna gain */
+       short tx_power_reduction; /* in 0.1 dBm */
+
+       /* 0 = default/diversity, 1 = Ant0, 2 = Ant1 */
+       u8 antenna_sel_tx;
+       u8 antenna_sel_rx;
+
+       int antenna_def;
+       int antenna_mode;
+
+       /* Following five fields are used for IEEE 802.11H */
+       unsigned int radar_detect;
+       unsigned int spect_mgmt;
+       /* All following fields are currently unused. */
+       unsigned int quiet_duration; /* duration of quiet period */
+       unsigned int quiet_offset; /* how far into the beacon is the quiet
+                                   * period */
+       unsigned int quiet_period;
+       u8 radar_firpwr_threshold;
+       u8 radar_rssi_threshold;
+       u8 pulse_height_threshold;
+       u8 pulse_rssi_threshold;
+       u8 pulse_inband_threshold;
+};
+
+/**
+ * enum ieee80211_if_types - types of 802.11 network interfaces
+ *
+ * @IEEE80211_IF_TYPE_AP: interface in AP mode.
+ * @IEEE80211_IF_TYPE_MGMT: special interface for communication with hostap
+ *     daemon. Drivers should never see this type.
+ * @IEEE80211_IF_TYPE_STA: interface in STA (client) mode.
+ * @IEEE80211_IF_TYPE_IBSS: interface in IBSS (ad-hoc) mode.
+ * @IEEE80211_IF_TYPE_MNTR: interface in monitor (rfmon) mode.
+ * @IEEE80211_IF_TYPE_WDS: interface in WDS mode.
+ * @IEEE80211_IF_TYPE_VLAN: not used.
+ */
+enum ieee80211_if_types {
+       IEEE80211_IF_TYPE_AP = 0x00000000,
+       IEEE80211_IF_TYPE_MGMT = 0x00000001,
+       IEEE80211_IF_TYPE_STA = 0x00000002,
+       IEEE80211_IF_TYPE_IBSS = 0x00000003,
+       IEEE80211_IF_TYPE_MNTR = 0x00000004,
+       IEEE80211_IF_TYPE_WDS = 0x5A580211,
+       IEEE80211_IF_TYPE_VLAN = 0x00080211,
+};
+
+/**
+ * struct ieee80211_if_init_conf - initial configuration of an interface
+ *
+ * @if_id: internal interface ID. This number has no particular meaning to
+ *     drivers and the only allowed usage is to pass it to
+ *     ieee80211_beacon_get() and ieee80211_get_buffered_bc() functions.
+ *     This field is not valid for monitor interfaces
+ *     (interfaces of %IEEE80211_IF_TYPE_MNTR type).
+ * @type: one of &enum ieee80211_if_types constants. Determines the type of
+ *     added/removed interface.
+ * @mac_addr: pointer to MAC address of the interface. This pointer is valid
+ *     until the interface is removed (i.e. it cannot be used after
+ *     remove_interface() callback was called for this interface).
+ *
+ * This structure is used in add_interface() and remove_interface()
+ * callbacks of &struct ieee80211_hw.
+ */
+struct ieee80211_if_init_conf {
+       int if_id;
+       int type;
+       void *mac_addr;
+};
+
+/**
+ * struct ieee80211_if_conf - configuration of an interface
+ *
+ * @type: type of the interface. This is always the same as was specified in
+ *     &struct ieee80211_if_init_conf. The type of an interface never changes
+ *     during the life of the interface; this field is present only for
+ *     convenience.
+ * @bssid: BSSID of the network we are associated to/creating.
+ * @ssid: used (together with @ssid_len) by drivers for hardware that
+ *     generate beacons independently. The pointer is valid only during the
+ *     config_interface() call, so copy the value somewhere if you need
+ *     it.
+ * @ssid_len: length of the @ssid field.
+ * @generic_elem: used (together with @generic_elem_len) by drivers for
+ *     hardware that generate beacons independently. The pointer is valid
+ *     only during the config_interface() call, so copy the value somewhere
+ *     if you need it.
+ * @generic_elem_len: length of the generic element.
+ * @beacon: beacon template. Valid only if @host_gen_beacon_template in
+ *     &struct ieee80211_hw is set. The driver is responsible of freeing
+ *     the sk_buff.
+ * @beacon_control: tx_control for the beacon template, this field is only
+ *     valid when the @beacon field was set.
+ *
+ * This structure is passed to the config_interface() callback of
+ * &struct ieee80211_hw.
+ */
+struct ieee80211_if_conf {
+       int type;
+       u8 *bssid;
+       u8 *ssid;
+       size_t ssid_len;
+       u8 *generic_elem;
+       size_t generic_elem_len;
+       struct sk_buff *beacon;
+       struct ieee80211_tx_control *beacon_control;
+};
+
+typedef enum { ALG_NONE, ALG_WEP, ALG_TKIP, ALG_CCMP, ALG_NULL }
+ieee80211_key_alg;
+
+
+struct ieee80211_key_conf {
+
+       int hw_key_idx;                 /* filled + used by low-level driver */
+       ieee80211_key_alg alg;
+       int keylen;
+
+#define IEEE80211_KEY_FORCE_SW_ENCRYPT (1<<0) /* to be cleared by low-level
+                                                driver */
+#define IEEE80211_KEY_DEFAULT_TX_KEY   (1<<1) /* This key is the new default TX
+                                                key (used only for broadcast
+                                                keys). */
+#define IEEE80211_KEY_DEFAULT_WEP_ONLY (1<<2) /* static WEP is the only
+                                                configured security policy;
+                                                this allows some low-level
+                                                drivers to determine when
+                                                hwaccel can be used */
+       u32 flags; /* key configuration flags defined above */
+
+       s8 keyidx;                      /* WEP key index */
+       u8 key[0];
+};
+
+#define IEEE80211_SEQ_COUNTER_RX       0
+#define IEEE80211_SEQ_COUNTER_TX       1
+
+typedef enum {
+       SET_KEY, DISABLE_KEY, REMOVE_ALL_KEYS,
+} set_key_cmd;
+
+/* This is driver-visible part of the per-hw state the stack keeps. */
+struct ieee80211_hw {
+       /* points to the cfg80211 wiphy for this piece. Note
+        * that you must fill in the perm_addr and dev fields
+        * of this structure, use the macros provided below. */
+       struct wiphy *wiphy;
+
+       /* assigned by mac80211, don't write */
+       struct ieee80211_conf conf;
+
+       /* Single thread workqueue available for driver use
+        * Allocated by mac80211 on registration */
+       struct workqueue_struct *workqueue;
+
+       /* Pointer to the private area that was
+        * allocated with this struct for you. */
+       void *priv;
+
+       /* The rest is information about your hardware */
+
+       /* TODO: frame_type 802.11/802.3, sw_encryption requirements */
+
+       /* Some wireless LAN chipsets generate beacons in the hardware/firmware
+        * and others rely on host generated beacons. This option is used to
+        * configure the upper layer IEEE 802.11 module to generate beacons.
+        * The low-level driver can use ieee80211_beacon_get() to fetch the
+        * next beacon frame. */
+#define IEEE80211_HW_HOST_GEN_BEACON (1<<0)
+
+       /* The device needs to be supplied with a beacon template only. */
+#define IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE (1<<1)
+
+       /* Some devices handle decryption internally and do not
+        * indicate whether the frame was encrypted (unencrypted frames
+        * will be dropped by the hardware, unless specifically allowed
+        * through) */
+#define IEEE80211_HW_DEVICE_HIDES_WEP (1<<2)
+
+       /* Whether RX frames passed to ieee80211_rx() include FCS in the end */
+#define IEEE80211_HW_RX_INCLUDES_FCS (1<<3)
+
+       /* Some wireless LAN chipsets buffer broadcast/multicast frames for
+        * power saving stations in the hardware/firmware and others rely on
+        * the host system for such buffering. This option is used to
+        * configure the IEEE 802.11 upper layer to buffer broadcast/multicast
+        * frames when there are power saving stations so that low-level driver
+        * can fetch them with ieee80211_get_buffered_bc(). */
+#define IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING (1<<4)
+
+#define IEEE80211_HW_WEP_INCLUDE_IV (1<<5)
+
+       /* will data nullfunc frames get proper TX status callback */
+#define IEEE80211_HW_DATA_NULLFUNC_ACK (1<<6)
+
+       /* Force software encryption for TKIP packets if WMM is enabled. */
+#define IEEE80211_HW_NO_TKIP_WMM_HWACCEL (1<<7)
+
+       /* Some devices handle Michael MIC internally and do not include MIC in
+        * the received packets passed up. device_strips_mic must be set
+        * for such devices. The 'encryption' frame control bit is expected to
+        * be still set in the IEEE 802.11 header with this option unlike with
+        * the device_hides_wep configuration option.
+        */
+#define IEEE80211_HW_DEVICE_STRIPS_MIC (1<<8)
+
+       /* Device is capable of performing full monitor mode even during
+        * normal operation. */
+#define IEEE80211_HW_MONITOR_DURING_OPER (1<<9)
+
+       /* Device does not need BSSID filter set to broadcast in order to
+        * receive all probe responses while scanning */
+#define IEEE80211_HW_NO_PROBE_FILTERING (1<<10)
+
+       /* Channels are already configured to the default regulatory domain
+        * specified in the device's EEPROM */
+#define IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED (1<<11)
+
+       /* calculate Michael MIC for an MSDU when doing hwcrypto */
+#define IEEE80211_HW_TKIP_INCLUDE_MMIC (1<<12)
+       /* Do TKIP phase1 key mixing in stack to support cards only do
+        * phase2 key mixing when doing hwcrypto */
+#define IEEE80211_HW_TKIP_REQ_PHASE1_KEY (1<<13)
+       /* Do TKIP phase1 and phase2 key mixing in stack and send the generated
+        * per-packet RC4 key with each TX frame when doing hwcrypto */
+#define IEEE80211_HW_TKIP_REQ_PHASE2_KEY (1<<14)
+
+       u32 flags;                      /* hardware flags defined above */
+
+       /* Set to the size of a needed device specific skb headroom for TX skbs. */
+       unsigned int extra_tx_headroom;
+
+       /* This is the time in us to change channels
+        */
+       int channel_change_time;
+       /* Maximum values for various statistics.
+        * Leave at 0 to indicate no support. Use negative numbers for dBm. */
+       s8 max_rssi;
+       s8 max_signal;
+       s8 max_noise;
+
+       /* Number of available hardware TX queues for data packets.
+        * WMM requires at least four queues. */
+       int queues;
+};
+
+static inline void SET_IEEE80211_DEV(struct ieee80211_hw *hw, struct device *dev)
+{
+       set_wiphy_dev(hw->wiphy, dev);
+}
+
+static inline void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, u8 *addr)
+{
+       memcpy(hw->wiphy->perm_addr, addr, ETH_ALEN);
+}
+
+/* Configuration block used by the low-level driver to tell the 802.11 code
+ * about supported hardware features and to pass function pointers to callback
+ * functions. */
+struct ieee80211_ops {
+       /* Handler that 802.11 module calls for each transmitted frame.
+        * skb contains the buffer starting from the IEEE 802.11 header.
+        * The low-level driver should send the frame out based on
+        * configuration in the TX control data.
+        * Must be atomic. */
+       int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb,
+                 struct ieee80211_tx_control *control);
+
+       /* Handler for performing hardware reset. */
+       int (*reset)(struct ieee80211_hw *hw);
+
+       /* Handler that is called when any netdevice attached to the hardware
+        * device is set UP for the first time. This can be used, e.g., to
+        * enable interrupts and beacon sending. */
+       int (*open)(struct ieee80211_hw *hw);
+
+       /* Handler that is called when the last netdevice attached to the
+        * hardware device is set DOWN. This can be used, e.g., to disable
+        * interrupts and beacon sending. */
+       int (*stop)(struct ieee80211_hw *hw);
+
+       /* Handler for asking a driver if a new interface can be added (or,
+        * more exactly, set UP). If the handler returns zero, the interface
+        * is added. Driver should perform any initialization it needs prior
+        * to returning zero. By returning non-zero addition of the interface
+        * is inhibited. Unless monitor_during_oper is set, it is guaranteed
+        * that monitor interfaces and normal interfaces are mutually
+        * exclusive. The open() handler is called after add_interface()
+        * if this is the first device added. At least one of the open()
+        * open() and add_interface() callbacks has to be assigned. If
+        * add_interface() is NULL, one STA interface is permitted only. */
+       int (*add_interface)(struct ieee80211_hw *hw,
+                            struct ieee80211_if_init_conf *conf);
+
+       /* Notify a driver that an interface is going down. The stop() handler
+        * is called prior to this if this is a last interface. */
+       void (*remove_interface)(struct ieee80211_hw *hw,
+                                struct ieee80211_if_init_conf *conf);
+
+       /* Handler for configuration requests. IEEE 802.11 code calls this
+        * function to change hardware configuration, e.g., channel. */
+       int (*config)(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
+
+       /* Handler for configuration requests related to interfaces (e.g.
+        * BSSID). */
+       int (*config_interface)(struct ieee80211_hw *hw,
+                               int if_id, struct ieee80211_if_conf *conf);
+
+       /* ieee80211 drivers do not have access to the &struct net_device
+        * that is (are) connected with their device. Hence (and because
+        * we need to combine the multicast lists and flags for multiple
+        * virtual interfaces), they cannot assign set_multicast_list.
+        * The parameters here replace dev->flags and dev->mc_count,
+        * dev->mc_list is replaced by calling ieee80211_get_mc_list_item.
+        * Must be atomic. */
+       void (*set_multicast_list)(struct ieee80211_hw *hw,
+                                  unsigned short flags, int mc_count);
+
+       /* Set TIM bit handler. If the hardware/firmware takes care of beacon
+        * generation, IEEE 802.11 code uses this function to tell the
+        * low-level to set (or clear if set==0) TIM bit for the given aid. If
+        * host system is used to generate beacons, this handler is not used
+        * and low-level driver should set it to NULL.
+        * Must be atomic. */
+       int (*set_tim)(struct ieee80211_hw *hw, int aid, int set);
+
+       /* Set encryption key. IEEE 802.11 module calls this function to set
+        * encryption keys. addr is ff:ff:ff:ff:ff:ff for default keys and
+        * station hwaddr for individual keys. aid of the station is given
+        * to help low-level driver in selecting which key->hw_key_idx to use
+        * for this key. TX control data will use the hw_key_idx selected by
+        * the low-level driver.
+        * Must be atomic. */
+       int (*set_key)(struct ieee80211_hw *hw, set_key_cmd cmd,
+                      u8 *addr, struct ieee80211_key_conf *key, int aid);
+
+       /* Set TX key index for default/broadcast keys. This is needed in cases
+        * where wlan card is doing full WEP/TKIP encapsulation (wep_include_iv
+        * is not set), in other cases, this function pointer can be set to
+        * NULL since the IEEE 802. 11 module takes care of selecting the key
+        * index for each TX frame. */
+       int (*set_key_idx)(struct ieee80211_hw *hw, int idx);
+
+       /* Enable/disable IEEE 802.1X. This item requests wlan card to pass
+        * unencrypted EAPOL-Key frames even when encryption is configured.
+        * If the wlan card does not require such a configuration, this
+        * function pointer can be set to NULL. */
+       int (*set_ieee8021x)(struct ieee80211_hw *hw, int use_ieee8021x);
+
+       /* Set port authorization state (IEEE 802.1X PAE) to be authorized
+        * (authorized=1) or unauthorized (authorized=0). This function can be
+        * used if the wlan hardware or low-level driver implements PAE.
+        * 80211.o module will anyway filter frames based on authorization
+        * state, so this function pointer can be NULL if low-level driver does
+        * not require event notification about port state changes.
+        * Currently unused. */
+       int (*set_port_auth)(struct ieee80211_hw *hw, u8 *addr,
+                            int authorized);
+
+       /* Ask the hardware to service the scan request, no need to start
+        * the scan state machine in stack. */
+       int (*hw_scan)(struct ieee80211_hw *hw, u8 *ssid, size_t len);
+
+       /* return low-level statistics */
+       int (*get_stats)(struct ieee80211_hw *hw,
+                        struct ieee80211_low_level_stats *stats);
+
+       /* For devices that generate their own beacons and probe response
+        * or association responses this updates the state of privacy_invoked
+        * returns 0 for success or an error number */
+       int (*set_privacy_invoked)(struct ieee80211_hw *hw,
+                                  int privacy_invoked);
+
+       /* For devices that have internal sequence counters, allow 802.11
+        * code to access the current value of a counter */
+       int (*get_sequence_counter)(struct ieee80211_hw *hw,
+                                   u8* addr, u8 keyidx, u8 txrx,
+                                   u32* iv32, u16* iv16);
+
+       /* Configuration of RTS threshold (if device needs it) */
+       int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value);
+
+       /* Configuration of fragmentation threshold.
+        * Assign this if the device does fragmentation by itself,
+        * if this method is assigned then the stack will not do
+        * fragmentation. */
+       int (*set_frag_threshold)(struct ieee80211_hw *hw, u32 value);
+
+       /* Configuration of retry limits (if device needs it) */
+       int (*set_retry_limit)(struct ieee80211_hw *hw,
+                              u32 short_retry, u32 long_retr);
+
+       /* Number of STAs in STA table notification (NULL = disabled).
+        * Must be atomic. */
+       void (*sta_table_notification)(struct ieee80211_hw *hw,
+                                      int num_sta);
+
+       /* Configure TX queue parameters (EDCF (aifs, cw_min, cw_max),
+        * bursting) for a hardware TX queue.
+        * queue = IEEE80211_TX_QUEUE_*.
+        * Must be atomic. */
+       int (*conf_tx)(struct ieee80211_hw *hw, int queue,
+                      const struct ieee80211_tx_queue_params *params);
+
+       /* Get statistics of the current TX queue status. This is used to get
+        * number of currently queued packets (queue length), maximum queue
+        * size (limit), and total number of packets sent using each TX queue
+        * (count).
+        * Currently unused. */
+       int (*get_tx_stats)(struct ieee80211_hw *hw,
+                           struct ieee80211_tx_queue_stats *stats);
+
+       /* Get the current TSF timer value from firmware/hardware. Currently,
+        * this is only used for IBSS mode debugging and, as such, is not a
+        * required function.
+        * Must be atomic. */
+       u64 (*get_tsf)(struct ieee80211_hw *hw);
+
+       /* Reset the TSF timer and allow firmware/hardware to synchronize with
+        * other STAs in the IBSS. This is only used in IBSS mode. This
+        * function is optional if the firmware/hardware takes full care of
+        * TSF synchronization. */
+       void (*reset_tsf)(struct ieee80211_hw *hw);
+
+       /* Setup beacon data for IBSS beacons. Unlike access point (Master),
+        * IBSS uses a fixed beacon frame which is configured using this
+        * function. This handler is required only for IBSS mode. */
+       int (*beacon_update)(struct ieee80211_hw *hw,
+                            struct sk_buff *skb,
+                            struct ieee80211_tx_control *control);
+
+       /* Determine whether the last IBSS beacon was sent by us. This is
+        * needed only for IBSS mode and the result of this function is used to
+        * determine whether to reply to Probe Requests. */
+       int (*tx_last_beacon)(struct ieee80211_hw *hw);
+};
+
+/* Allocate a new hardware device. This must be called once for each
+ * hardware device. The returned pointer must be used to refer to this
+ * device when calling other functions. 802.11 code allocates a private data
+ * area for the low-level driver. The size of this area is given as
+ * priv_data_len.
+ */
+struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
+                                       const struct ieee80211_ops *ops);
+
+/* Register hardware device to the IEEE 802.11 code and kernel. Low-level
+ * drivers must call this function before using any other IEEE 802.11
+ * function except ieee80211_register_hwmode. */
+int ieee80211_register_hw(struct ieee80211_hw *hw);
+
+/* driver can use this and ieee80211_get_rx_led_name to get the
+ * name of the registered LEDs after ieee80211_register_hw
+ * was called.
+ * This is useful to set the default trigger on the LED class
+ * device that your driver should export for each LED the device
+ * has, that way the default behaviour will be as expected but
+ * the user can still change it/turn off the LED etc.
+ */
+#ifdef CONFIG_MAC80211_LEDS
+extern char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw);
+extern char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw);
+#endif
+static inline char *ieee80211_get_tx_led_name(struct ieee80211_hw *hw)
+{
+#ifdef CONFIG_MAC80211_LEDS
+       return __ieee80211_get_tx_led_name(hw);
+#else
+       return NULL;
+#endif
+}
+
+static inline char *ieee80211_get_rx_led_name(struct ieee80211_hw *hw)
+{
+#ifdef CONFIG_MAC80211_LEDS
+       return __ieee80211_get_rx_led_name(hw);
+#else
+       return NULL;
+#endif
+}
+
+/* Register a new hardware PHYMODE capability to the stack. */
+int ieee80211_register_hwmode(struct ieee80211_hw *hw,
+                             struct ieee80211_hw_mode *mode);
+
+/* Unregister a hardware device. This function instructs 802.11 code to free
+ * allocated resources and unregister netdevices from the kernel. */
+void ieee80211_unregister_hw(struct ieee80211_hw *hw);
+
+/* Free everything that was allocated including private data of a driver. */
+void ieee80211_free_hw(struct ieee80211_hw *hw);
+
+/* Receive frame callback function. The low-level driver uses this function to
+ * send received frames to the IEEE 802.11 code. Receive buffer (skb) must
+ * start with IEEE 802.11 header. */
+void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
+                   struct ieee80211_rx_status *status);
+void ieee80211_rx_irqsafe(struct ieee80211_hw *hw,
+                         struct sk_buff *skb,
+                         struct ieee80211_rx_status *status);
+
+/* Transmit status callback function. The low-level driver must call this
+ * function to report transmit status for all the TX frames that had
+ * req_tx_status set in the transmit control fields. In addition, this should
+ * be called at least for all unicast frames to provide information for TX rate
+ * control algorithm. In order to maintain all statistics, this function is
+ * recommended to be called after each frame, including multicast/broadcast, is
+ * sent. */
+void ieee80211_tx_status(struct ieee80211_hw *hw,
+                        struct sk_buff *skb,
+                        struct ieee80211_tx_status *status);
+void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
+                                struct sk_buff *skb,
+                                struct ieee80211_tx_status *status);
+
+/**
+ * ieee80211_beacon_get - beacon generation function
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @if_id: interface ID from &struct ieee80211_if_init_conf.
+ * @control: will be filled with information needed to send this beacon.
+ *
+ * If the beacon frames are generated by the host system (i.e., not in
+ * hardware/firmware), the low-level driver uses this function to receive
+ * the next beacon frame from the 802.11 code. The low-level is responsible
+ * for calling this function before beacon data is needed (e.g., based on
+ * hardware interrupt). Returned skb is used only once and low-level driver
+ * is responsible of freeing it.
+ */
+struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
+                                    int if_id,
+                                    struct ieee80211_tx_control *control);
+
+/**
+ * ieee80211_rts_get - RTS frame generation function
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @frame: pointer to the frame that is going to be protected by the RTS.
+ * @frame_len: the frame length (in octets).
+ * @frame_txctl: &struct ieee80211_tx_control of the frame.
+ * @rts: The buffer where to store the RTS frame.
+ *
+ * If the RTS frames are generated by the host system (i.e., not in
+ * hardware/firmware), the low-level driver uses this function to receive
+ * the next RTS frame from the 802.11 code. The low-level is responsible
+ * for calling this function before and RTS frame is needed.
+ */
+void ieee80211_rts_get(struct ieee80211_hw *hw,
+                      const void *frame, size_t frame_len,
+                      const struct ieee80211_tx_control *frame_txctl,
+                      struct ieee80211_rts *rts);
+
+/**
+ * ieee80211_rts_duration - Get the duration field for an RTS frame
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @frame_len: the length of the frame that is going to be protected by the RTS.
+ * @frame_txctl: &struct ieee80211_tx_control of the frame.
+ *
+ * If the RTS is generated in firmware, but the host system must provide
+ * the duration field, the low-level driver uses this function to receive
+ * the duration field value in little-endian byteorder.
+ */
+__le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
+                             size_t frame_len,
+                             const struct ieee80211_tx_control *frame_txctl);
+
+/**
+ * ieee80211_ctstoself_get - CTS-to-self frame generation function
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @frame: pointer to the frame that is going to be protected by the CTS-to-self.
+ * @frame_len: the frame length (in octets).
+ * @frame_txctl: &struct ieee80211_tx_control of the frame.
+ * @cts: The buffer where to store the CTS-to-self frame.
+ *
+ * If the CTS-to-self frames are generated by the host system (i.e., not in
+ * hardware/firmware), the low-level driver uses this function to receive
+ * the next CTS-to-self frame from the 802.11 code. The low-level is responsible
+ * for calling this function before and CTS-to-self frame is needed.
+ */
+void ieee80211_ctstoself_get(struct ieee80211_hw *hw,
+                            const void *frame, size_t frame_len,
+                            const struct ieee80211_tx_control *frame_txctl,
+                            struct ieee80211_cts *cts);
+
+/**
+ * ieee80211_ctstoself_duration - Get the duration field for a CTS-to-self frame
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @frame_len: the length of the frame that is going to be protected by the CTS-to-self.
+ * @frame_txctl: &struct ieee80211_tx_control of the frame.
+ *
+ * If the CTS-to-self is generated in firmware, but the host system must provide
+ * the duration field, the low-level driver uses this function to receive
+ * the duration field value in little-endian byteorder.
+ */
+__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
+                                   size_t frame_len,
+                                   const struct ieee80211_tx_control *frame_txctl);
+
+/**
+ * ieee80211_generic_frame_duration - Calculate the duration field for a frame
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @frame_len: the length of the frame.
+ * @rate: the rate (in 100kbps) at which the frame is going to be transmitted.
+ *
+ * Calculate the duration field of some generic frame, given its
+ * length and transmission rate (in 100kbps).
+ */
+__le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
+                                       size_t frame_len,
+                                       int rate);
+
+/**
+ * ieee80211_get_buffered_bc - accessing buffered broadcast and multicast frames
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ * @if_id: interface ID from &struct ieee80211_if_init_conf.
+ * @control: will be filled with information needed to send returned frame.
+ *
+ * Function for accessing buffered broadcast and multicast frames. If
+ * hardware/firmware does not implement buffering of broadcast/multicast
+ * frames when power saving is used, 802.11 code buffers them in the host
+ * memory. The low-level driver uses this function to fetch next buffered
+ * frame. In most cases, this is used when generating beacon frame. This
+ * function returns a pointer to the next buffered skb or NULL if no more
+ * buffered frames are available.
+ *
+ * Note: buffered frames are returned only after DTIM beacon frame was
+ * generated with ieee80211_beacon_get() and the low-level driver must thus
+ * call ieee80211_beacon_get() first. ieee80211_get_buffered_bc() returns
+ * NULL if the previous generated beacon was not DTIM, so the low-level driver
+ * does not need to check for DTIM beacons separately and should be able to
+ * use common code for all beacons.
+ */
+struct sk_buff *
+ieee80211_get_buffered_bc(struct ieee80211_hw *hw, int if_id,
+                         struct ieee80211_tx_control *control);
+
+/* Low level drivers that have their own MLME and MAC indicate
+ * the aid for an associating station with this call */
+int ieee80211_set_aid_for_sta(struct ieee80211_hw *hw,
+                             u8 *peer_address, u16 aid);
+
+
+/* Given an sk_buff with a raw 802.11 header at the data pointer this function
+ * returns the 802.11 header length in bytes (not including encryption
+ * headers). If the data in the sk_buff is too short to contain a valid 802.11
+ * header the function returns 0.
+ */
+int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);
+
+/* Like ieee80211_get_hdrlen_from_skb() but takes a FC in CPU order. */
+int ieee80211_get_hdrlen(u16 fc);
+
+/**
+ * ieee80211_wake_queue - wake specific queue
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ * @queue: queue number (counted from zero).
+ *
+ * Drivers should use this function instead of netif_wake_queue.
+ */
+void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue);
+
+/**
+ * ieee80211_stop_queue - stop specific queue
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ * @queue: queue number (counted from zero).
+ *
+ * Drivers should use this function instead of netif_stop_queue.
+ */
+void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue);
+
+/**
+ * ieee80211_start_queues - start all queues
+ * @hw: pointer to as obtained from ieee80211_alloc_hw().
+ *
+ * Drivers should use this function instead of netif_start_queue.
+ */
+void ieee80211_start_queues(struct ieee80211_hw *hw);
+
+/**
+ * ieee80211_stop_queues - stop all queues
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ *
+ * Drivers should use this function instead of netif_stop_queue.
+ */
+void ieee80211_stop_queues(struct ieee80211_hw *hw);
+
+/**
+ * ieee80211_wake_queues - wake all queues
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ *
+ * Drivers should use this function instead of netif_wake_queue.
+ */
+void ieee80211_wake_queues(struct ieee80211_hw *hw);
+
+/**
+ * ieee80211_get_mc_list_item - iteration over items in multicast list
+ * @hw: pointer as obtained from ieee80211_alloc_hw().
+ * @prev: value returned by previous call to ieee80211_get_mc_list_item() or
+ *     NULL to start a new iteration.
+ * @ptr: pointer to buffer of void * type for internal usage of
+ *     ieee80211_get_mc_list_item().
+ *
+ * Iterates over items in multicast list of given device. To get the first
+ * item, pass NULL in @prev and in *@ptr. In subsequent calls, pass the
+ * value returned by previous call in @prev. Don't alter *@ptr during
+ * iteration. When there are no more items, NULL is returned.
+ */
+struct dev_mc_list *
+ieee80211_get_mc_list_item(struct ieee80211_hw *hw,
+                          struct dev_mc_list *prev,
+                          void **ptr);
+
+/* called by driver to notify scan status completed */
+void ieee80211_scan_completed(struct ieee80211_hw *hw);
+
+/* Function to indicate Radar Detection. The low level driver must call this
+ * function to indicate the presence of radar in the current channel.
+ * Additionally the radar type also could be sent */
+int  ieee80211_radar_status(struct ieee80211_hw *hw, int channel,
+                           int radar, int radar_type);
+
+/* return a pointer to the source address (SA) */
+static inline u8 *ieee80211_get_SA(struct ieee80211_hdr *hdr)
+{
+       u8 *raw = (u8 *) hdr;
+       u8 tofrom = (*(raw+1)) & 3; /* get the TODS and FROMDS bits */
+
+       switch (tofrom) {
+               case 2:
+                       return hdr->addr3;
+               case 3:
+                       return hdr->addr4;
+       }
+       return hdr->addr2;
+}
+
+/* return a pointer to the destination address (DA) */
+static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr)
+{
+       u8 *raw = (u8 *) hdr;
+       u8 to_ds = (*(raw+1)) & 1; /* get the TODS bit */
+
+       if (to_ds)
+               return hdr->addr3;
+       return hdr->addr1;
+}
+
+static inline int ieee80211_get_morefrag(struct ieee80211_hdr *hdr)
+{
+       return (le16_to_cpu(hdr->frame_control) &
+               IEEE80211_FCTL_MOREFRAGS) != 0;
+}
+
+#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
+#define MAC_ARG(x) ((u8*)(x))[0], ((u8*)(x))[1], ((u8*)(x))[2], \
+                  ((u8*)(x))[3], ((u8*)(x))[4], ((u8*)(x))[5]
+
+#endif /* MAC80211_H */
index 6114c4f..f56c8d6 100644 (file)
@@ -100,6 +100,8 @@ typedef enum {
        SCTP_CMD_T3_RTX_TIMERS_STOP, /* Stops T3-rtx pending timers */
        SCTP_CMD_FORCE_PRIM_RETRAN,  /* Forces retrans. over primary path. */
        SCTP_CMD_SET_SK_ERR,     /* Set sk_err */
+       SCTP_CMD_ASSOC_CHANGE,   /* generate and send assoc_change event */
+       SCTP_CMD_ADAPTATION_IND, /* generate and send adaptation event */
        SCTP_CMD_LAST
 } sctp_verb_t;
 
index 28af680..dda72bf 100644 (file)
@@ -378,11 +378,15 @@ static inline int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int
 
 int sctp_v6_init(void);
 void sctp_v6_exit(void);
+int sctp_v6_add_protocol(void);
+void sctp_v6_del_protocol(void);
 
 #else /* #ifdef defined(CONFIG_IPV6) */
 
 static inline int sctp_v6_init(void) { return 0; }
 static inline void sctp_v6_exit(void) { return; }
+static inline int sctp_v6_add_protocol(void) { return 0; }
+static inline void sctp_v6_del_protocol(void) { return; }
 
 #endif /* #if defined(CONFIG_IPV6) */
 
index 7b4fff9..5e81984 100644 (file)
@@ -1857,6 +1857,7 @@ int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *,
 int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *,
                                         struct sctp_cookie*,
                                         gfp_t gfp);
+int sctp_assoc_set_id(struct sctp_association *, gfp_t);
 
 int sctp_cmp_addr_exact(const union sctp_addr *ss1,
                        const union sctp_addr *ss2);
index ef8f9d4..e22b4f0 100644 (file)
@@ -736,7 +736,8 @@ static inline __u32 tcp_current_ssthresh(const struct sock *sk)
 
 static inline void tcp_sync_left_out(struct tcp_sock *tp)
 {
-       BUG_ON(tp->sacked_out + tp->lost_out > tp->packets_out);
+       BUG_ON(tp->rx_opt.sack_ok &&
+              (tp->sacked_out + tp->lost_out > tp->packets_out));
        tp->left_out = tp->sacked_out + tp->lost_out;
 }
 
index 66c2d3e..39ef925 100644 (file)
@@ -416,25 +416,6 @@ struct xfrm_audit
        u32     secid;
 };
 
-/* SAD metadata, add more later */
-struct xfrm_sadinfo
-{
-       u32 sadhcnt; /* current hash bkts */
-       u32 sadhmcnt; /* max allowed hash bkts */
-       u32 sadcnt; /* current running count */
-};
-
-struct xfrm_spdinfo
-{
-       u32 incnt;
-       u32 outcnt;
-       u32 fwdcnt;
-       u32 inscnt;
-       u32 outscnt;
-       u32 fwdscnt;
-       u32 spdhcnt;
-       u32 spdhmcnt;
-};
 #ifdef CONFIG_AUDITSYSCALL
 extern void xfrm_audit_log(uid_t auid, u32 secid, int type, int result,
                    struct xfrm_policy *xp, struct xfrm_state *x);
@@ -964,11 +945,29 @@ static inline int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **s
        return -ENOSYS;
 }
 #endif
+
+struct xfrmk_sadinfo {
+       u32 sadhcnt; /* current hash bkts */
+       u32 sadhmcnt; /* max allowed hash bkts */
+       u32 sadcnt; /* current running count */
+};
+
+struct xfrmk_spdinfo {
+       u32 incnt;
+       u32 outcnt;
+       u32 fwdcnt;
+       u32 inscnt;
+       u32 outscnt;
+       u32 fwdscnt;
+       u32 spdhcnt;
+       u32 spdhmcnt;
+};
+
 extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
 extern int xfrm_state_delete(struct xfrm_state *x);
 extern void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info);
-extern void xfrm_sad_getinfo(struct xfrm_sadinfo *si);
-extern void xfrm_spd_getinfo(struct xfrm_spdinfo *si);
+extern void xfrm_sad_getinfo(struct xfrmk_sadinfo *si);
+extern void xfrm_spd_getinfo(struct xfrmk_spdinfo *si);
 extern int xfrm_replay_check(struct xfrm_state *x, __be32 seq);
 extern void xfrm_replay_advance(struct xfrm_state *x, __be32 seq);
 extern void xfrm_replay_notify(struct xfrm_state *x, int event);
index 585d28e..739fa4d 100644 (file)
@@ -39,8 +39,6 @@
 #if !defined( IB_MAD_H )
 #define IB_MAD_H
 
-#include <linux/pci.h>
-
 #include <rdma/ib_verbs.h>
 
 /* Management base version */
index 4a44278..8d1e4e8 100644 (file)
@@ -588,7 +588,17 @@ struct iscsi_reject {
 #define VALUE_MAXLEN           255
 #define TARGET_NAME_MAXLEN     VALUE_MAXLEN
 
-#define DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH   8192
+#define ISCSI_DEF_MAX_RECV_SEG_LEN             8192
+#define ISCSI_MIN_MAX_RECV_SEG_LEN             512
+#define ISCSI_MAX_MAX_RECV_SEG_LEN             16777215
+
+#define ISCSI_DEF_FIRST_BURST_LEN              65536
+#define ISCSI_MIN_FIRST_BURST_LEN              512
+#define ISCSI_MAX_FIRST_BURST_LEN              16777215
+
+#define ISCSI_DEF_MAX_BURST_LEN                        262144
+#define ISCSI_MIN_MAX_BURST_LEN                        512
+#define ISCSI_MAX_MAX_BURST_LEN                        16777215
 
 /************************* RFC 3720 End *****************************/
 
index 5c0e979..9f8f80a 100644 (file)
@@ -203,6 +203,7 @@ static inline int scsi_status_is_good(int status)
 
 /*
  *  DEVICE TYPES
+ *  Please keep them in 0x%02x format for $MODALIAS to work
  */
 
 #define TYPE_DISK           0x00
index d6948d0..a2e0c10 100644 (file)
@@ -73,9 +73,6 @@ struct scsi_cmnd {
        unsigned short use_sg;  /* Number of pieces of scatter-gather */
        unsigned short sglist_len;      /* size of malloc'd scatter-gather list */
 
-       /* offset in cmd we are at (for multi-transfer tgt cmds) */
-       unsigned offset;
-
        unsigned underflow;     /* Return error if less than
                                   this amount is transferred */
 
index 3bbbfbe..5a43a4c 100644 (file)
@@ -5,14 +5,16 @@ struct scsi_cmnd;
 struct scsi_sense_hdr;
 
 extern void scsi_print_command(struct scsi_cmnd *);
-extern void scsi_print_sense_hdr(const char *, struct scsi_sense_hdr *);
 extern void __scsi_print_command(unsigned char *);
-extern void scsi_print_sense(const char *, struct scsi_cmnd *);
+extern void scsi_show_extd_sense(unsigned char, unsigned char);
+extern void scsi_show_sense_hdr(struct scsi_sense_hdr *);
+extern void scsi_print_sense_hdr(const char *, struct scsi_sense_hdr *);
+extern void scsi_print_sense(char *, struct scsi_cmnd *);
 extern void __scsi_print_sense(const char *name,
                               const unsigned char *sense_buffer,
                               int sense_len);
-extern void scsi_print_driverbyte(int);
-extern void scsi_print_hostbyte(int);
+extern void scsi_show_result(int);
+extern void scsi_print_result(struct scsi_cmnd *);
 extern void scsi_print_status(unsigned char);
 extern const char *scsi_sense_key_string(unsigned char);
 extern const char *scsi_extd_sense_format(unsigned char, unsigned char);
index 9dd37e2..2f3c5b8 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
+#include <linux/blkdev.h>
 #include <asm/atomic.h>
 
 struct request_queue;
@@ -119,6 +120,7 @@ struct scsi_device {
        unsigned use_192_bytes_for_3f:1; /* ask for 192 bytes from page 0x3f */
        unsigned no_start_on_add:1;     /* do not issue start on add */
        unsigned allow_restart:1; /* issue START_UNIT in error handler */
+       unsigned manage_start_stop:1;   /* Let HLD (sd) manage start/stop */
        unsigned no_uld_attach:1; /* disable connecting to upper level drivers */
        unsigned select_no_atn:1;
        unsigned fix_capacity:1;        /* READ_CAPACITY is too high by 1 */
@@ -154,8 +156,11 @@ struct scsi_device {
 #define sdev_printk(prefix, sdev, fmt, a...)   \
        dev_printk(prefix, &(sdev)->sdev_gendev, fmt, ##a)
 
-#define scmd_printk(prefix, scmd, fmt, a...)   \
-       dev_printk(prefix, &(scmd)->device->sdev_gendev, fmt, ##a)
+#define scmd_printk(prefix, scmd, fmt, a...)                           \
+        (scmd)->request->rq_disk ?                                     \
+       sdev_printk(prefix, (scmd)->device, "[%s] " fmt,                \
+                   (scmd)->request->rq_disk->disk_name, ##a) :         \
+       sdev_printk(prefix, (scmd)->device, fmt, ##a)
 
 enum scsi_target_state {
        STARGET_RUNNING = 1,
@@ -353,4 +358,9 @@ static inline int scsi_device_qas(struct scsi_device *sdev)
                return 0;
        return sdev->inquiry[56] & 0x02;
 }
+
+#define MODULE_ALIAS_SCSI_DEVICE(type) \
+       MODULE_ALIAS("scsi:t-" __stringify(type) "*")
+#define SCSI_DEVICE_MODALIAS_FMT "scsi:t-0x%02x"
+
 #endif /* _SCSI_SCSI_DEVICE_H */
index 7f1f411..68f461b 100644 (file)
@@ -129,6 +129,11 @@ struct scsi_host_template {
         * the LLD. When the driver is finished processing the command
         * the done callback is invoked.
         *
+        * This is called to inform the LLD to transfer
+        * cmd->request_bufflen bytes. The cmd->use_sg speciefies the
+        * number of scatterlist entried in the command and
+        * cmd->request_buffer contains the scatterlist.
+        *
         * return values: see queuecommand
         *
         * If the LLD accepts the cmd, it should set the result to an
@@ -139,20 +144,6 @@ struct scsi_host_template {
        /* TODO: rename */
        int (* transfer_response)(struct scsi_cmnd *,
                                  void (*done)(struct scsi_cmnd *));
-       /*
-        * This is called to inform the LLD to transfer cmd->request_bufflen
-        * bytes of the cmd at cmd->offset in the cmd. The cmd->use_sg
-        * speciefies the number of scatterlist entried in the command
-        * and cmd->request_buffer contains the scatterlist.
-        *
-        * If the command cannot be processed in one transfer_data call
-        * becuase a scatterlist within the LLD's limits cannot be
-        * created then transfer_data will be called multiple times.
-        * It is initially called from process context, and later
-        * calls are from the interrup context.
-        */
-       int (* transfer_data)(struct scsi_cmnd *,
-                             void (*done)(struct scsi_cmnd *));
 
        /* Used as callback for the completion of task management request. */
        int (* tsk_mgmt_response)(u64 mid, int result);
@@ -335,6 +326,19 @@ struct scsi_host_template {
        int (*proc_info)(struct Scsi_Host *, char *, char **, off_t, int, int);
 
        /*
+        * This is an optional routine that allows the transport to become
+        * involved when a scsi io timer fires. The return value tells the
+        * timer routine how to finish the io timeout handling:
+        * EH_HANDLED:          I fixed the error, please complete the command
+        * EH_RESET_TIMER:      I need more time, reset the timer and
+        *                      begin counting again
+        * EH_NOT_HANDLED       Begin normal error recovery
+        *
+        * Status: OPTIONAL
+        */
+       enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *);
+
+       /*
         * suspend support
         */
        int (*resume)(struct scsi_device *);
index 07d6e77..4cf9dff 100644 (file)
@@ -45,11 +45,13 @@ struct tgt_event {
                /* user-> kernel */
                struct {
                        int host_no;
-                       uint32_t len;
                        int result;
+                       aligned_u64 tag;
                        aligned_u64 uaddr;
+                       aligned_u64 sense_uaddr;
+                       uint32_t len;
+                       uint32_t sense_len;
                        uint8_t rw;
-                       aligned_u64 tag;
                } cmd_rsp;
                struct {
                        int host_no;
index 798f7c7..1e79730 100644 (file)
@@ -108,6 +108,8 @@ enum fc_port_state {
 #define FC_PORTSPEED_2GBIT             2
 #define FC_PORTSPEED_4GBIT             4
 #define FC_PORTSPEED_10GBIT            8
+#define FC_PORTSPEED_8GBIT             0x10
+#define FC_PORTSPEED_16GBIT            0x20
 #define FC_PORTSPEED_NOT_NEGOTIATED    (1 << 15) /* Speed not established */
 
 /*
diff --git a/include/scsi/sd.h b/include/scsi/sd.h
new file mode 100644 (file)
index 0000000..5261488
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef _SCSI_DISK_H
+#define _SCSI_DISK_H
+
+/*
+ * More than enough for everybody ;)  The huge number of majors
+ * is a leftover from 16bit dev_t days, we don't really need that
+ * much numberspace.
+ */
+#define SD_MAJORS      16
+
+/*
+ * This is limited by the naming scheme enforced in sd_probe,
+ * add another character to it if you really need more disks.
+ */
+#define SD_MAX_DISKS   (((26 * 26) + 26 + 1) * 26)
+
+/*
+ * Time out in seconds for disks and Magneto-opticals (which are slower).
+ */
+#define SD_TIMEOUT             (30 * HZ)
+#define SD_MOD_TIMEOUT         (75 * HZ)
+
+/*
+ * Number of allowed retries
+ */
+#define SD_MAX_RETRIES         5
+#define SD_PASSTHROUGH_RETRIES 1
+
+/*
+ * Size of the initial data buffer for mode and read capacity data
+ */
+#define SD_BUF_SIZE            512
+
+struct scsi_disk {
+       struct scsi_driver *driver;     /* always &sd_template */
+       struct scsi_device *device;
+       struct class_device cdev;
+       struct gendisk  *disk;
+       unsigned int    openers;        /* protected by BKL for now, yuck */
+       sector_t        capacity;       /* size in 512-byte sectors */
+       u32             index;
+       u8              media_present;
+       u8              write_prot;
+       unsigned        WCE : 1;        /* state of disk WCE bit */
+       unsigned        RCD : 1;        /* state of disk RCD bit, unused */
+       unsigned        DPOFUA : 1;     /* state of disk DPOFUA bit */
+};
+#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,cdev)
+
+static int  sd_revalidate_disk(struct gendisk *disk);
+static void sd_rw_intr(struct scsi_cmnd * SCpnt);
+static int  sd_probe(struct device *);
+static int  sd_remove(struct device *);
+static void sd_shutdown(struct device *dev);
+static int sd_suspend(struct device *dev, pm_message_t state);
+static int sd_resume(struct device *dev);
+static void sd_rescan(struct device *);
+static int  sd_init_command(struct scsi_cmnd *);
+static int  sd_issue_flush(struct device *, sector_t *);
+static void sd_prepare_flush(request_queue_t *, struct request *);
+static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer);
+static void scsi_disk_release(struct class_device *cdev);
+static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *);
+static void sd_print_result(struct scsi_disk *, int);
+
+#define sd_printk(prefix, sdsk, fmt, a...)                             \
+        (sdsk)->disk ?                                                 \
+       sdev_printk(prefix, (sdsk)->device, "[%s] " fmt,                \
+                   (sdsk)->disk->disk_name, ##a) :                     \
+       sdev_printk(prefix, (sdsk)->device, fmt, ##a)
+
+#endif /* _SCSI_DISK_H */
index 0133f4f..615ce97 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <linux/irq.h>
+#include <linux/msi.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
@@ -185,6 +186,8 @@ int set_irq_msi(unsigned int irq, struct msi_desc *entry)
        desc = irq_desc + irq;
        spin_lock_irqsave(&desc->lock, flags);
        desc->msi_desc = entry;
+       if (entry)
+               entry->irq = irq;
        spin_unlock_irqrestore(&desc->lock, flags);
        return 0;
 }
index e0ffe4a..559deca 100644 (file)
@@ -24,18 +24,18 @@ static struct subsys_attribute _name##_attr = \
 
 #if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
 /* current uevent sequence number */
-static ssize_t uevent_seqnum_show(struct subsystem *subsys, char *page)
+static ssize_t uevent_seqnum_show(struct kset *kset, char *page)
 {
        return sprintf(page, "%llu\n", (unsigned long long)uevent_seqnum);
 }
 KERNEL_ATTR_RO(uevent_seqnum);
 
 /* uevent helper program, used during early boo */
-static ssize_t uevent_helper_show(struct subsystem *subsys, char *page)
+static ssize_t uevent_helper_show(struct kset *kset, char *page)
 {
        return sprintf(page, "%s\n", uevent_helper);
 }
-static ssize_t uevent_helper_store(struct subsystem *subsys, const char *page, size_t count)
+static ssize_t uevent_helper_store(struct kset *kset, const char *page, size_t count)
 {
        if (count+1 > UEVENT_HELPER_PATH_LEN)
                return -ENOENT;
@@ -49,13 +49,13 @@ KERNEL_ATTR_RW(uevent_helper);
 #endif
 
 #ifdef CONFIG_KEXEC
-static ssize_t kexec_loaded_show(struct subsystem *subsys, char *page)
+static ssize_t kexec_loaded_show(struct kset *kset, char *page)
 {
        return sprintf(page, "%d\n", !!kexec_image);
 }
 KERNEL_ATTR_RO(kexec_loaded);
 
-static ssize_t kexec_crash_loaded_show(struct subsystem *subsys, char *page)
+static ssize_t kexec_crash_loaded_show(struct kset *kset, char *page)
 {
        return sprintf(page, "%d\n", !!kexec_crash_image);
 }
@@ -85,7 +85,7 @@ static int __init ksysfs_init(void)
 {
        int error = subsystem_register(&kernel_subsys);
        if (!error)
-               error = sysfs_create_group(&kernel_subsys.kset.kobj,
+               error = sysfs_create_group(&kernel_subsys.kobj,
                                           &kernel_attr_group);
 
        return error;
index 4dc4a25..1eb8ca5 100644 (file)
@@ -45,6 +45,8 @@
 #include <asm/cacheflush.h>
 #include <linux/license.h>
 
+extern int module_sysfs_initialized;
+
 #if 0
 #define DEBUGP printk
 #else
@@ -1117,8 +1119,8 @@ int mod_sysfs_init(struct module *mod)
 {
        int err;
 
-       if (!module_subsys.kset.subsys) {
-               printk(KERN_ERR "%s: module_subsys not initialized\n",
+       if (!module_sysfs_initialized) {
+               printk(KERN_ERR "%s: module sysfs not initialized\n",
                       mod->name);
                err = -EINVAL;
                goto out;
@@ -2385,7 +2387,7 @@ void module_add_driver(struct module *mod, struct device_driver *drv)
                struct kobject *mkobj;
 
                /* Lookup built-in module entry in /sys/modules */
-               mkobj = kset_find_obj(&module_subsys.kset, drv->mod_name);
+               mkobj = kset_find_obj(&module_subsys, drv->mod_name);
                if (mkobj) {
                        mk = container_of(mkobj, struct module_kobject, kobj);
                        /* remember our module structure */
index 1fc4ac7..3121723 100644 (file)
@@ -691,6 +691,7 @@ static struct kset_uevent_ops module_uevent_ops = {
 };
 
 decl_subsys(module, &module_ktype, &module_uevent_ops);
+int module_sysfs_initialized;
 
 static struct kobj_type module_ktype = {
        .sysfs_ops =    &module_sysfs_ops,
@@ -709,6 +710,7 @@ static int __init param_sysfs_init(void)
                        __FILE__, __LINE__, ret);
                return ret;
        }
+       module_sysfs_initialized = 1;
 
        param_sysfs_builtin();
 
index 02e4fb6..8df51c2 100644 (file)
@@ -322,13 +322,13 @@ static const char * const pm_disk_modes[] = {
  *     supports it (as determined from pm_ops->pm_disk_mode).
  */
 
-static ssize_t disk_show(struct subsystem * subsys, char * buf)
+static ssize_t disk_show(struct kset *kset, char *buf)
 {
        return sprintf(buf, "%s\n", pm_disk_modes[pm_disk_mode]);
 }
 
 
-static ssize_t disk_store(struct subsystem * s, const char * buf, size_t n)
+static ssize_t disk_store(struct kset *kset, const char *buf, size_t n)
 {
        int error = 0;
        int i;
@@ -373,13 +373,13 @@ static ssize_t disk_store(struct subsystem * s, const char * buf, size_t n)
 
 power_attr(disk);
 
-static ssize_t resume_show(struct subsystem * subsys, char *buf)
+static ssize_t resume_show(struct kset *kset, char *buf)
 {
        return sprintf(buf,"%d:%d\n", MAJOR(swsusp_resume_device),
                       MINOR(swsusp_resume_device));
 }
 
-static ssize_t resume_store(struct subsystem *subsys, const char *buf, size_t n)
+static ssize_t resume_store(struct kset *kset, const char *buf, size_t n)
 {
        unsigned int maj, min;
        dev_t res;
@@ -405,12 +405,12 @@ static ssize_t resume_store(struct subsystem *subsys, const char *buf, size_t n)
 
 power_attr(resume);
 
-static ssize_t image_size_show(struct subsystem * subsys, char *buf)
+static ssize_t image_size_show(struct kset *kset, char *buf)
 {
        return sprintf(buf, "%lu\n", image_size);
 }
 
-static ssize_t image_size_store(struct subsystem * subsys, const char * buf, size_t n)
+static ssize_t image_size_store(struct kset *kset, const char *buf, size_t n)
 {
        unsigned long size;
 
@@ -439,7 +439,7 @@ static struct attribute_group attr_group = {
 
 static int __init pm_disk_init(void)
 {
-       return sysfs_create_group(&power_subsys.kset.kobj,&attr_group);
+       return sysfs_create_group(&power_subsys.kobj, &attr_group);
 }
 
 core_initcall(pm_disk_init);
index 72419a3..b21c2a5 100644 (file)
@@ -285,7 +285,7 @@ decl_subsys(power,NULL,NULL);
  *     proper enumerated value, and initiates a suspend transition.
  */
 
-static ssize_t state_show(struct subsystem * subsys, char * buf)
+static ssize_t state_show(struct kset *kset, char *buf)
 {
        int i;
        char * s = buf;
@@ -298,7 +298,7 @@ static ssize_t state_show(struct subsystem * subsys, char * buf)
        return (s - buf);
 }
 
-static ssize_t state_store(struct subsystem * subsys, const char * buf, size_t n)
+static ssize_t state_store(struct kset *kset, const char *buf, size_t n)
 {
        suspend_state_t state = PM_SUSPEND_STANDBY;
        const char * const *s;
@@ -325,13 +325,13 @@ power_attr(state);
 #ifdef CONFIG_PM_TRACE
 int pm_trace_enabled;
 
-static ssize_t pm_trace_show(struct subsystem * subsys, char * buf)
+static ssize_t pm_trace_show(struct kset *kset, char *buf)
 {
        return sprintf(buf, "%d\n", pm_trace_enabled);
 }
 
 static ssize_t
-pm_trace_store(struct subsystem * subsys, const char * buf, size_t n)
+pm_trace_store(struct kset *kset, const char *buf, size_t n)
 {
        int val;
 
@@ -365,7 +365,7 @@ static int __init pm_init(void)
 {
        int error = subsystem_register(&power_subsys);
        if (!error)
-               error = sysfs_create_group(&power_subsys.kset.kobj,&attr_group);
+               error = sysfs_create_group(&power_subsys.kobj,&attr_group);
        return error;
 }
 
index 1c6eef8..33bd94c 100644 (file)
@@ -37,7 +37,7 @@ static struct subsys_attribute _name##_attr = {       \
        .store  = _name##_store,                \
 }
 
-extern struct subsystem power_subsys;
+extern struct kset power_subsys;
 
 /* Preferred image size in bytes (default 500 MB) */
 extern unsigned long image_size;
index 4d43f37..a57d262 100644 (file)
 #define PIO_RESERVED   0x40000UL
 #endif
 
+static void bad_io_access(unsigned long port, const char *access)
+{
+       static int count = 10;
+       if (count) {
+               count--;
+               printk(KERN_ERR "Bad IO access at port %lx (%s)\n", port, access);
+               WARN_ON(1);
+       }
+}
+
 /*
  * Ugly macros are a way of life.
  */
-#define VERIFY_PIO(port) BUG_ON((port & ~PIO_MASK) != PIO_OFFSET)
-
 #define IO_COND(addr, is_pio, is_mmio) do {                    \
        unsigned long port = (unsigned long __force)addr;       \
-       if (port < PIO_RESERVED) {                              \
-               VERIFY_PIO(port);                               \
+       if (port >= PIO_RESERVED) {                             \
+               is_mmio;                                        \
+       } else if (port > PIO_OFFSET) {                         \
                port &= PIO_MASK;                               \
                is_pio;                                         \
-       } else {                                                \
-               is_mmio;                                        \
-       }                                                       \
+       } else                                                  \
+               bad_io_access(port, #is_pio );                  \
 } while (0)
 
 #ifndef pio_read16be
 unsigned int fastcall ioread8(void __iomem *addr)
 {
        IO_COND(addr, return inb(port), return readb(addr));
+       return 0xff;
 }
 unsigned int fastcall ioread16(void __iomem *addr)
 {
        IO_COND(addr, return inw(port), return readw(addr));
+       return 0xffff;
 }
 unsigned int fastcall ioread16be(void __iomem *addr)
 {
        IO_COND(addr, return pio_read16be(port), return mmio_read16be(addr));
+       return 0xffff;
 }
 unsigned int fastcall ioread32(void __iomem *addr)
 {
        IO_COND(addr, return inl(port), return readl(addr));
+       return 0xffffffff;
 }
 unsigned int fastcall ioread32be(void __iomem *addr)
 {
        IO_COND(addr, return pio_read32be(port), return mmio_read32be(addr));
+       return 0xffffffff;
 }
 EXPORT_SYMBOL(ioread8);
 EXPORT_SYMBOL(ioread16);
index cecf2fb..fc5f3f6 100644 (file)
@@ -582,22 +582,10 @@ void kset_init(struct kset * k)
 /**
  *     kset_add - add a kset object to the hierarchy.
  *     @k:     kset.
- *
- *     Simply, this adds the kset's embedded kobject to the 
- *     hierarchy. 
- *     We also try to make sure that the kset's embedded kobject
- *     has a parent before it is added. We only care if the embedded
- *     kobject is not part of a kset itself, since kobject_add()
- *     assigns a parent in that case. 
- *     If that is the case, and the kset has a controlling subsystem,
- *     then we set the kset's parent to be said subsystem. 
  */
 
 int kset_add(struct kset * k)
 {
-       if (!k->kobj.parent && !k->kobj.kset && k->subsys)
-               k->kobj.parent = &k->subsys->kset.kobj;
-
        return kobject_add(&k->kobj);
 }
 
@@ -656,53 +644,28 @@ struct kobject * kset_find_obj(struct kset * kset, const char * name)
        return ret;
 }
 
-
-void subsystem_init(struct subsystem * s)
+void subsystem_init(struct kset *s)
 {
-       kset_init(&s->kset);
+       kset_init(s);
 }
 
-/**
- *     subsystem_register - register a subsystem.
- *     @s:     the subsystem we're registering.
- *
- *     Once we register the subsystem, we want to make sure that 
- *     the kset points back to this subsystem.
- */
-
-int subsystem_register(struct subsystem * s)
+int subsystem_register(struct kset *s)
 {
-       int error;
-
-       if (!s)
-               return -EINVAL;
-
-       subsystem_init(s);
-       pr_debug("subsystem %s: registering\n",s->kset.kobj.name);
-
-       if (!(error = kset_add(&s->kset))) {
-               if (!s->kset.subsys)
-                       s->kset.subsys = s;
-       }
-       return error;
+       return kset_register(s);
 }
 
-void subsystem_unregister(struct subsystem * s)
+void subsystem_unregister(struct kset *s)
 {
-       if (!s)
-               return;
-       pr_debug("subsystem %s: unregistering\n",s->kset.kobj.name);
-       kset_unregister(&s->kset);
+       kset_unregister(s);
 }
 
-
 /**
  *     subsystem_create_file - export sysfs attribute file.
  *     @s:     subsystem.
  *     @a:     subsystem attribute descriptor.
  */
 
-int subsys_create_file(struct subsystem * s, struct subsys_attribute * a)
+int subsys_create_file(struct kset *s, struct subsys_attribute *a)
 {
        int error = 0;
 
@@ -710,28 +673,12 @@ int subsys_create_file(struct subsystem * s, struct subsys_attribute * a)
                return -EINVAL;
 
        if (subsys_get(s)) {
-               error = sysfs_create_file(&s->kset.kobj,&a->attr);
+               error = sysfs_create_file(&s->kobj, &a->attr);
                subsys_put(s);
        }
        return error;
 }
 
-
-/**
- *     subsystem_remove_file - remove sysfs attribute file.
- *     @s:     subsystem.
- *     @a:     attribute desciptor.
- */
-#if 0
-void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
-{
-       if (subsys_get(s)) {
-               sysfs_remove_file(&s->kset.kobj,&a->attr);
-               subsys_put(s);
-       }
-}
-#endif  /*  0  */
-
 EXPORT_SYMBOL(kobject_init);
 EXPORT_SYMBOL(kobject_register);
 EXPORT_SYMBOL(kobject_unregister);
index 7ad2a48..703c8c1 100644 (file)
@@ -22,7 +22,7 @@
  * match extremely simple token=arg style patterns. If the pattern is found,
  * the location(s) of the arguments will be returned in the @args array.
  */
-static int match_one(char *s, char *p, substring_t args[])
+static int match_one(char *s, const char *p, substring_t args[])
 {
        char *meta;
        int argc = 0;
@@ -43,7 +43,7 @@ static int match_one(char *s, char *p, substring_t args[])
                p = meta + 1;
 
                if (isdigit(*p))
-                       len = simple_strtoul(p, &p, 10);
+                       len = simple_strtoul(p, (char **) &p, 10);
                else if (*p == '%') {
                        if (*s++ != '%')
                                return 0;
@@ -102,7 +102,7 @@ static int match_one(char *s, char *p, substring_t args[])
  */
 int match_token(char *s, match_table_t table, substring_t args[])
 {
-       struct match_token *p;
+       const struct match_token *p;
 
        for (p = table; !match_one(s, p->pattern, args) ; p++)
                ;
@@ -190,7 +190,7 @@ int match_hex(substring_t *s, int *result)
  * &substring_t @s to the c-style string @to. Caller guarantees that @to is
  * large enough to hold the characters of @s.
  */
-void match_strcpy(char *to, substring_t *s)
+void match_strcpy(char *to, const substring_t *s)
 {
        memcpy(to, s->from, s->to - s->from);
        to[s->to - s->from] = '\0';
@@ -204,7 +204,7 @@ void match_strcpy(char *to, substring_t *s)
  * the &substring_t @s. The caller is responsible for freeing the returned
  * string with kfree().
  */
-char *match_strdup(substring_t *s)
+char *match_strdup(const substring_t *s)
 {
        char *p = kmalloc(s->to - s->from + 1, GFP_KERNEL);
        if (p)
index c0c7bb8..bd93c45 100644 (file)
@@ -117,8 +117,7 @@ static void __exit vlan_cleanup_devices(void)
        struct net_device *dev, *nxt;
 
        rtnl_lock();
-       for (dev = dev_base; dev; dev = nxt) {
-               nxt = dev->next;
+       for_each_netdev_safe(dev, nxt) {
                if (dev->priv_flags & IFF_802_1Q_VLAN) {
                        unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev,
                                            VLAN_DEV_INFO(dev)->vlan_id);
index 5e24f72..d216a64 100644 (file)
@@ -237,13 +237,9 @@ int vlan_proc_rem_dev(struct net_device *vlandev)
  * The following few functions build the content of /proc/net/vlan/config
  */
 
-/* starting at dev, find a VLAN device */
-static struct net_device *vlan_skip(struct net_device *dev)
+static inline int is_vlan_dev(struct net_device *dev)
 {
-       while (dev && !(dev->priv_flags & IFF_802_1Q_VLAN))
-               dev = dev->next;
-
-       return dev;
+       return dev->priv_flags & IFF_802_1Q_VLAN;
 }
 
 /* start read of /proc/net/vlan/config */
@@ -257,19 +253,35 @@ static void *vlan_seq_start(struct seq_file *seq, loff_t *pos)
        if (*pos == 0)
                return SEQ_START_TOKEN;
 
-       for (dev = vlan_skip(dev_base); dev && i < *pos;
-            dev = vlan_skip(dev->next), ++i);
+       for_each_netdev(dev) {
+               if (!is_vlan_dev(dev))
+                       continue;
+
+               if (i++ == *pos)
+                       return dev;
+       }
 
-       return  (i == *pos) ? dev : NULL;
+       return  NULL;
 }
 
 static void *vlan_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
+       struct net_device *dev;
+
        ++*pos;
 
-       return vlan_skip((v == SEQ_START_TOKEN)
-                           ? dev_base
-                           : ((struct net_device *)v)->next);
+       dev = (struct net_device *)v;
+       if (v == SEQ_START_TOKEN)
+               dev = net_device_entry(&dev_base_head);
+
+       for_each_netdev_continue(dev) {
+               if (!is_vlan_dev(dev))
+                       continue;
+
+               return dev;
+       }
+
+       return NULL;
 }
 
 static void vlan_seq_stop(struct seq_file *seq, void *v)
index 2fc8e77..5b22278 100644 (file)
@@ -220,6 +220,7 @@ config FIB_RULES
 menu "Wireless"
 
 source "net/wireless/Kconfig"
+source "net/mac80211/Kconfig"
 source "net/ieee80211/Kconfig"
 
 endmenu
index 6b74d41..9fdb60c 100644 (file)
@@ -45,6 +45,8 @@ obj-$(CONFIG_ECONET)          += econet/
 obj-$(CONFIG_VLAN_8021Q)       += 8021q/
 obj-$(CONFIG_IP_DCCP)          += dccp/
 obj-$(CONFIG_IP_SCTP)          += sctp/
+obj-y                          += wireless/
+obj-$(CONFIG_MAC80211)         += mac80211/
 obj-$(CONFIG_IEEE80211)                += ieee80211/
 obj-$(CONFIG_TIPC)             += tipc/
 obj-$(CONFIG_NETLABEL)         += netlabel/
@@ -53,5 +55,3 @@ obj-$(CONFIG_IUCV)            += iucv/
 ifeq ($(CONFIG_NET),y)
 obj-$(CONFIG_SYSCTL)           += sysctl_net.o
 endif
-
-obj-y                          += wireless/
index 690573b..849deaf 100644 (file)
@@ -475,11 +475,9 @@ void __exit br_cleanup_bridges(void)
        struct net_device *dev, *nxt;
 
        rtnl_lock();
-       for (dev = dev_base; dev; dev = nxt) {
-               nxt = dev->next;
+       for_each_netdev_safe(dev, nxt)
                if (dev->priv_flags & IFF_EBRIDGE)
                        del_br(dev->priv);
-       }
        rtnl_unlock();
 
 }
index eda0fbf..bb15e9e 100644 (file)
@@ -27,7 +27,9 @@ static int get_bridge_ifindices(int *indices, int num)
        struct net_device *dev;
        int i = 0;
 
-       for (dev = dev_base; dev && i < num; dev = dev->next) {
+       for_each_netdev(dev) {
+               if (i >= num)
+                       break;
                if (dev->priv_flags & IFF_EBRIDGE)
                        indices[i++] = dev->ifindex;
        }
index 9b2986b..fa77987 100644 (file)
@@ -142,14 +142,33 @@ static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb)
        return skb->nf_bridge;
 }
 
-static inline void nf_bridge_save_header(struct sk_buff *skb)
+static inline void nf_bridge_push_encap_header(struct sk_buff *skb)
+{
+       unsigned int len = nf_bridge_encap_header_len(skb);
+
+       skb_push(skb, len);
+       skb->network_header -= len;
+}
+
+static inline void nf_bridge_pull_encap_header(struct sk_buff *skb)
 {
-       int header_size = ETH_HLEN;
+       unsigned int len = nf_bridge_encap_header_len(skb);
+
+       skb_pull(skb, len);
+       skb->network_header += len;
+}
 
-       if (skb->protocol == htons(ETH_P_8021Q))
-               header_size += VLAN_HLEN;
-       else if (skb->protocol == htons(ETH_P_PPP_SES))
-               header_size += PPPOE_SES_HLEN;
+static inline void nf_bridge_pull_encap_header_rcsum(struct sk_buff *skb)
+{
+       unsigned int len = nf_bridge_encap_header_len(skb);
+
+       skb_pull_rcsum(skb, len);
+       skb->network_header += len;
+}
+
+static inline void nf_bridge_save_header(struct sk_buff *skb)
+{
+       int header_size = ETH_HLEN + nf_bridge_encap_header_len(skb);
 
        skb_copy_from_linear_data_offset(skb, -header_size,
                                         skb->nf_bridge->data, header_size);
@@ -162,12 +181,7 @@ static inline void nf_bridge_save_header(struct sk_buff *skb)
 int nf_bridge_copy_header(struct sk_buff *skb)
 {
        int err;
-       int header_size = ETH_HLEN;
-
-       if (skb->protocol == htons(ETH_P_8021Q))
-               header_size += VLAN_HLEN;
-       else if (skb->protocol == htons(ETH_P_PPP_SES))
-               header_size += PPPOE_SES_HLEN;
+       int header_size = ETH_HLEN + nf_bridge_encap_header_len(skb);
 
        err = skb_cow(skb, header_size);
        if (err)
@@ -175,11 +189,7 @@ int nf_bridge_copy_header(struct sk_buff *skb)
 
        skb_copy_to_linear_data_offset(skb, -header_size,
                                       skb->nf_bridge->data, header_size);
-
-       if (skb->protocol == htons(ETH_P_8021Q))
-               __skb_push(skb, VLAN_HLEN);
-       else if (skb->protocol == htons(ETH_P_PPP_SES))
-               __skb_push(skb, PPPOE_SES_HLEN);
+       __skb_push(skb, nf_bridge_encap_header_len(skb));
        return 0;
 }
 
@@ -200,13 +210,7 @@ static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb)
        dst_hold(skb->dst);
 
        skb->dev = nf_bridge->physindev;
-       if (skb->protocol == htons(ETH_P_8021Q)) {
-               skb_push(skb, VLAN_HLEN);
-               skb->network_header -= VLAN_HLEN;
-       } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
-               skb_push(skb, PPPOE_SES_HLEN);
-               skb->network_header -= PPPOE_SES_HLEN;
-       }
+       nf_bridge_push_encap_header(skb);
        NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
                       br_handle_frame_finish, 1);
 
@@ -284,13 +288,7 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
        if (!skb->dev)
                kfree_skb(skb);
        else {
-               if (skb->protocol == htons(ETH_P_8021Q)) {
-                       skb_pull(skb, VLAN_HLEN);
-                       skb->network_header += VLAN_HLEN;
-               } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
-                       skb_pull(skb, PPPOE_SES_HLEN);
-                       skb->network_header += PPPOE_SES_HLEN;
-               }
+               nf_bridge_pull_encap_header(skb);
                skb->dst->output(skb);
        }
        return 0;
@@ -356,15 +354,7 @@ bridged_dnat:
                                 * bridged frame */
                                nf_bridge->mask |= BRNF_BRIDGED_DNAT;
                                skb->dev = nf_bridge->physindev;
-                               if (skb->protocol ==
-                                   htons(ETH_P_8021Q)) {
-                                       skb_push(skb, VLAN_HLEN);
-                                       skb->network_header -= VLAN_HLEN;
-                               } else if(skb->protocol ==
-                                   htons(ETH_P_PPP_SES)) {
-                                       skb_push(skb, PPPOE_SES_HLEN);
-                                       skb->network_header -= PPPOE_SES_HLEN;
-                               }
+                               nf_bridge_push_encap_header(skb);
                                NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING,
                                               skb, skb->dev, NULL,
                                               br_nf_pre_routing_finish_bridge,
@@ -380,13 +370,7 @@ bridged_dnat:
        }
 
        skb->dev = nf_bridge->physindev;
-       if (skb->protocol == htons(ETH_P_8021Q)) {
-               skb_push(skb, VLAN_HLEN);
-               skb->network_header -= VLAN_HLEN;
-       } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
-               skb_push(skb, PPPOE_SES_HLEN);
-               skb->network_header -= PPPOE_SES_HLEN;
-       }
+       nf_bridge_push_encap_header(skb);
        NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
                       br_handle_frame_finish, 1);
 
@@ -536,14 +520,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
 #endif
                if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
                        goto out;
-
-               if (skb->protocol == htons(ETH_P_8021Q)) {
-                       skb_pull_rcsum(skb, VLAN_HLEN);
-                       skb->network_header += VLAN_HLEN;
-               } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
-                       skb_pull_rcsum(skb, PPPOE_SES_HLEN);
-                       skb->network_header += PPPOE_SES_HLEN;
-               }
+               nf_bridge_pull_encap_header_rcsum(skb);
                return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn);
        }
 #ifdef CONFIG_SYSCTL
@@ -557,14 +534,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
 
        if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
                goto out;
-
-       if (skb->protocol == htons(ETH_P_8021Q)) {
-               skb_pull_rcsum(skb, VLAN_HLEN);
-               skb->network_header += VLAN_HLEN;
-       } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
-               skb_pull_rcsum(skb, PPPOE_SES_HLEN);
-               skb->network_header += PPPOE_SES_HLEN;
-       }
+       nf_bridge_pull_encap_header_rcsum(skb);
 
        if (!pskb_may_pull(skb, sizeof(struct iphdr)))
                goto inhdr_error;
@@ -642,13 +612,7 @@ static int br_nf_forward_finish(struct sk_buff *skb)
        } else {
                in = *((struct net_device **)(skb->cb));
        }
-       if (skb->protocol == htons(ETH_P_8021Q)) {
-               skb_push(skb, VLAN_HLEN);
-               skb->network_header -= VLAN_HLEN;
-       } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
-               skb_push(skb, PPPOE_SES_HLEN);
-               skb->network_header -= PPPOE_SES_HLEN;
-       }
+       nf_bridge_push_encap_header(skb);
        NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in,
                       skb->dev, br_forward_finish, 1);
        return 0;
@@ -682,13 +646,7 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
        else
                pf = PF_INET6;
 
-       if (skb->protocol == htons(ETH_P_8021Q)) {
-               skb_pull(*pskb, VLAN_HLEN);
-               (*pskb)->network_header += VLAN_HLEN;
-       } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
-               skb_pull(*pskb, PPPOE_SES_HLEN);
-               (*pskb)->network_header += PPPOE_SES_HLEN;
-       }
+       nf_bridge_pull_encap_header(*pskb);
 
        nf_bridge = skb->nf_bridge;
        if (skb->pkt_type == PACKET_OTHERHOST) {
@@ -722,15 +680,12 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
        if (skb->protocol != htons(ETH_P_ARP)) {
                if (!IS_VLAN_ARP(skb))
                        return NF_ACCEPT;
-               skb_pull(*pskb, VLAN_HLEN);
-               (*pskb)->network_header += VLAN_HLEN;
+               nf_bridge_pull_encap_header(*pskb);
        }
 
        if (arp_hdr(skb)->ar_pln != 4) {
-               if (IS_VLAN_ARP(skb)) {
-                       skb_push(*pskb, VLAN_HLEN);
-                       (*pskb)->network_header -= VLAN_HLEN;
-               }
+               if (IS_VLAN_ARP(skb))
+                       nf_bridge_push_encap_header(*pskb);
                return NF_ACCEPT;
        }
        *d = (struct net_device *)in;
@@ -777,13 +732,7 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
                skb->pkt_type = PACKET_OTHERHOST;
                nf_bridge->mask ^= BRNF_PKT_TYPE;
        }
-       if (skb->protocol == htons(ETH_P_8021Q)) {
-               skb_push(skb, VLAN_HLEN);
-               skb->network_header -= VLAN_HLEN;
-       } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
-               skb_push(skb, PPPOE_SES_HLEN);
-               skb->network_header -= PPPOE_SES_HLEN;
-       }
+       nf_bridge_push_encap_header(skb);
 
        NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev, skb->dev,
                br_forward_finish);
@@ -848,14 +797,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
                nf_bridge->mask |= BRNF_PKT_TYPE;
        }
 
-       if (skb->protocol == htons(ETH_P_8021Q)) {
-               skb_pull(skb, VLAN_HLEN);
-               skb->network_header += VLAN_HLEN;
-       } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
-               skb_pull(skb, PPPOE_SES_HLEN);
-               skb->network_header += PPPOE_SES_HLEN;
-       }
-
+       nf_bridge_pull_encap_header(skb);
        nf_bridge_save_header(skb);
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
index 35facc0..0fcf6f0 100644 (file)
@@ -109,7 +109,8 @@ static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
        struct net_device *dev;
        int idx;
 
-       for (dev = dev_base, idx = 0; dev; dev = dev->next) {
+       idx = 0;
+       for_each_netdev(dev) {
                /* not a bridge port */
                if (dev->br_port == NULL || idx < cb->args[0])
                        goto skip;
index eb99900..f27d4ab 100644 (file)
@@ -156,13 +156,13 @@ static spinlock_t net_dma_event_lock;
 #endif
 
 /*
- * The @dev_base list is protected by @dev_base_lock and the rtnl
+ * The @dev_base_head list is protected by @dev_base_lock and the rtnl
  * semaphore.
  *
  * Pure readers hold dev_base_lock for reading.
  *
  * Writers must hold the rtnl semaphore while they loop through the
- * dev_base list, and hold dev_base_lock for writing when they do the
+ * dev_base_head list, and hold dev_base_lock for writing when they do the
  * actual updates.  This allows pure readers to access the list even
  * while a writer is preparing to update it.
  *
@@ -174,11 +174,10 @@ static spinlock_t net_dma_event_lock;
  * unregister_netdevice(), which must be called with the rtnl
  * semaphore held.
  */
-struct net_device *dev_base;
-static struct net_device **dev_tail = &dev_base;
+LIST_HEAD(dev_base_head);
 DEFINE_RWLOCK(dev_base_lock);
 
-EXPORT_SYMBOL(dev_base);
+EXPORT_SYMBOL(dev_base_head);
 EXPORT_SYMBOL(dev_base_lock);
 
 #define NETDEV_HASHBITS        8
@@ -567,26 +566,38 @@ struct net_device *dev_getbyhwaddr(unsigned short type, char *ha)
 
        ASSERT_RTNL();
 
-       for (dev = dev_base; dev; dev = dev->next)
+       for_each_netdev(dev)
                if (dev->type == type &&
                    !memcmp(dev->dev_addr, ha, dev->addr_len))
-                       break;
-       return dev;
+                       return dev;
+
+       return NULL;
 }
 
 EXPORT_SYMBOL(dev_getbyhwaddr);
 
+struct net_device *__dev_getfirstbyhwtype(unsigned short type)
+{
+       struct net_device *dev;
+
+       ASSERT_RTNL();
+       for_each_netdev(dev)
+               if (dev->type == type)
+                       return dev;
+
+       return NULL;
+}
+
+EXPORT_SYMBOL(__dev_getfirstbyhwtype);
+
 struct net_device *dev_getfirstbyhwtype(unsigned short type)
 {
        struct net_device *dev;
 
        rtnl_lock();
-       for (dev = dev_base; dev; dev = dev->next) {
-               if (dev->type == type) {
-                       dev_hold(dev);
-                       break;
-               }
-       }
+       dev = __dev_getfirstbyhwtype(type);
+       if (dev)
+               dev_hold(dev);
        rtnl_unlock();
        return dev;
 }
@@ -606,17 +617,19 @@ EXPORT_SYMBOL(dev_getfirstbyhwtype);
 
 struct net_device * dev_get_by_flags(unsigned short if_flags, unsigned short mask)
 {
-       struct net_device *dev;
+       struct net_device *dev, *ret;
 
+       ret = NULL;
        read_lock(&dev_base_lock);
-       for (dev = dev_base; dev != NULL; dev = dev->next) {
+       for_each_netdev(dev) {
                if (((dev->flags ^ if_flags) & mask) == 0) {
                        dev_hold(dev);
+                       ret = dev;
                        break;
                }
        }
        read_unlock(&dev_base_lock);
-       return dev;
+       return ret;
 }
 
 /**
@@ -682,7 +695,7 @@ int dev_alloc_name(struct net_device *dev, const char *name)
                if (!inuse)
                        return -ENOMEM;
 
-               for (d = dev_base; d; d = d->next) {
+               for_each_netdev(d) {
                        if (!sscanf(d->name, name, &i))
                                continue;
                        if (i < 0 || i >= max_netdevices)
@@ -964,7 +977,7 @@ int register_netdevice_notifier(struct notifier_block *nb)
        rtnl_lock();
        err = raw_notifier_chain_register(&netdev_chain, nb);
        if (!err) {
-               for (dev = dev_base; dev; dev = dev->next) {
+               for_each_netdev(dev) {
                        nb->notifier_call(nb, NETDEV_REGISTER, dev);
 
                        if (dev->flags & IFF_UP)
@@ -2038,7 +2051,7 @@ static int dev_ifconf(char __user *arg)
         */
 
        total = 0;
-       for (dev = dev_base; dev; dev = dev->next) {
+       for_each_netdev(dev) {
                for (i = 0; i < NPROTO; i++) {
                        if (gifconf_list[i]) {
                                int done;
@@ -2070,26 +2083,28 @@ static int dev_ifconf(char __user *arg)
  *     This is invoked by the /proc filesystem handler to display a device
  *     in detail.
  */
-static struct net_device *dev_get_idx(loff_t pos)
+void *dev_seq_start(struct seq_file *seq, loff_t *pos)
 {
+       loff_t off;
        struct net_device *dev;
-       loff_t i;
 
-       for (i = 0, dev = dev_base; dev && i < pos; ++i, dev = dev->next);
+       read_lock(&dev_base_lock);
+       if (!*pos)
+               return SEQ_START_TOKEN;
 
-       return i == pos ? dev : NULL;
-}
+       off = 1;
+       for_each_netdev(dev)
+               if (off++ == *pos)
+                       return dev;
 
-void *dev_seq_start(struct seq_file *seq, loff_t *pos)
-{
-       read_lock(&dev_base_lock);
-       return *pos ? dev_get_idx(*pos - 1) : SEQ_START_TOKEN;
+       return NULL;
 }
 
 void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
        ++*pos;
-       return v == SEQ_START_TOKEN ? dev_base : ((struct net_device *)v)->next;
+       return v == SEQ_START_TOKEN ?
+               first_net_device() : next_net_device((struct net_device *)v);
 }
 
 void dev_seq_stop(struct seq_file *seq, void *v)
@@ -3071,11 +3086,9 @@ int register_netdevice(struct net_device *dev)
 
        set_bit(__LINK_STATE_PRESENT, &dev->state);
 
-       dev->next = NULL;
        dev_init_scheduler(dev);
        write_lock_bh(&dev_base_lock);
-       *dev_tail = dev;
-       dev_tail = &dev->next;
+       list_add_tail(&dev->dev_list, &dev_base_head);
        hlist_add_head(&dev->name_hlist, head);
        hlist_add_head(&dev->index_hlist, dev_index_hash(dev->ifindex));
        dev_hold(dev);
@@ -3349,8 +3362,6 @@ void synchronize_net(void)
 
 void unregister_netdevice(struct net_device *dev)
 {
-       struct net_device *d, **dp;
-
        BUG_ON(dev_boot_phase);
        ASSERT_RTNL();
 
@@ -3370,19 +3381,11 @@ void unregister_netdevice(struct net_device *dev)
                dev_close(dev);
 
        /* And unlink it from device chain. */
-       for (dp = &dev_base; (d = *dp) != NULL; dp = &d->next) {
-               if (d == dev) {
-                       write_lock_bh(&dev_base_lock);
-                       hlist_del(&dev->name_hlist);
-                       hlist_del(&dev->index_hlist);
-                       if (dev_tail == &dev->next)
-                               dev_tail = dp;
-                       *dp = d->next;
-                       write_unlock_bh(&dev_base_lock);
-                       break;
-               }
-       }
-       BUG_ON(!d);
+       write_lock_bh(&dev_base_lock);
+       list_del(&dev->dev_list);
+       hlist_del(&dev->name_hlist);
+       hlist_del(&dev->index_hlist);
+       write_unlock_bh(&dev_base_lock);
 
        dev->reg_state = NETREG_UNREGISTERING;
 
index 7d57bf7..5a54053 100644 (file)
@@ -223,7 +223,7 @@ static void *dev_mc_seq_start(struct seq_file *seq, loff_t *pos)
        loff_t off = 0;
 
        read_lock(&dev_base_lock);
-       for (dev = dev_base; dev; dev = dev->next) {
+       for_each_netdev(dev) {
                if (off++ == *pos)
                        return dev;
        }
@@ -232,9 +232,8 @@ static void *dev_mc_seq_start(struct seq_file *seq, loff_t *pos)
 
 static void *dev_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-       struct net_device *dev = v;
        ++*pos;
-       return dev->next;
+       return next_net_device((struct net_device *)v);
 }
 
 static void dev_mc_seq_stop(struct seq_file *seq, void *v)
index cec1111..8c971a2 100644 (file)
@@ -539,13 +539,16 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
        int s_idx = cb->args[0];
        struct net_device *dev;
 
-       for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
+       idx = 0;
+       for_each_netdev(dev) {
                if (idx < s_idx)
-                       continue;
+                       goto cont;
                if (rtnl_fill_ifinfo(skb, dev, NULL, 0, RTM_NEWLINK,
                                     NETLINK_CB(cb->skb).pid,
                                     cb->nlh->nlmsg_seq, 0, NLM_F_MULTI) <= 0)
                        break;
+cont:
+               idx++;
        }
        cb->args[0] = idx;
 
index a205eaa..9fbe87c 100644 (file)
@@ -721,7 +721,7 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        struct sock *sk = sock->sk;
        struct dn_scp *scp = DN_SK(sk);
        struct sockaddr_dn *saddr = (struct sockaddr_dn *)uaddr;
-       struct net_device *dev;
+       struct net_device *dev, *ldev;
        int rv;
 
        if (addr_len != sizeof(struct sockaddr_dn))
@@ -746,14 +746,17 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        if (!(saddr->sdn_flags & SDF_WILD)) {
                if (dn_ntohs(saddr->sdn_nodeaddrl)) {
                        read_lock(&dev_base_lock);
-                       for(dev = dev_base; dev; dev = dev->next) {
+                       ldev = NULL;
+                       for_each_netdev(dev) {
                                if (!dev->dn_ptr)
                                        continue;
-                               if (dn_dev_islocal(dev, dn_saddr2dn(saddr)))
+                               if (dn_dev_islocal(dev, dn_saddr2dn(saddr))) {
+                                       ldev = dev;
                                        break;
+                               }
                        }
                        read_unlock(&dev_base_lock);
-                       if (dev == NULL)
+                       if (ldev == NULL)
                                return -EADDRNOTAVAIL;
                }
        }
index 5c2a995..764a56a 100644 (file)
@@ -799,9 +799,10 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
        skip_ndevs = cb->args[0];
        skip_naddr = cb->args[1];
 
-       for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
+       idx = 0;
+       for_each_netdev(dev) {
                if (idx < skip_ndevs)
-                       continue;
+                       goto cont;
                else if (idx > skip_ndevs) {
                        /* Only skip over addresses for first dev dumped
                         * in this iteration (idx == skip_ndevs) */
@@ -809,18 +810,20 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
                }
 
                if ((dn_db = dev->dn_ptr) == NULL)
-                       continue;
+                       goto cont;
 
                for (ifa = dn_db->ifa_list, dn_idx = 0; ifa;
                     ifa = ifa->ifa_next, dn_idx++) {
                        if (dn_idx < skip_naddr)
-                               continue;
+                               goto cont;
 
                        if (dn_nl_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
                                              cb->nlh->nlmsg_seq, RTM_NEWADDR,
                                              NLM_F_MULTI) < 0)
                                goto done;
                }
+cont:
+               idx++;
        }
 done:
        cb->args[0] = idx;
@@ -1296,7 +1299,7 @@ void dn_dev_devices_off(void)
        struct net_device *dev;
 
        rtnl_lock();
-       for(dev = dev_base; dev; dev = dev->next)
+       for_each_netdev(dev)
                dn_dev_down(dev);
        rtnl_unlock();
 
@@ -1307,7 +1310,7 @@ void dn_dev_devices_on(void)
        struct net_device *dev;
 
        rtnl_lock();
-       for(dev = dev_base; dev; dev = dev->next) {
+       for_each_netdev(dev) {
                if (dev->flags & IFF_UP)
                        dn_dev_up(dev);
        }
@@ -1325,62 +1328,56 @@ int unregister_dnaddr_notifier(struct notifier_block *nb)
 }
 
 #ifdef CONFIG_PROC_FS
-static inline struct net_device *dn_dev_get_next(struct seq_file *seq, struct net_device *dev)
+static inline int is_dn_dev(struct net_device *dev)
 {
-       do {
-               dev = dev->next;
-       } while(dev && !dev->dn_ptr);
-
-       return dev;
+       return dev->dn_ptr != NULL;
 }
 
-static struct net_device *dn_dev_get_idx(struct seq_file *seq, loff_t pos)
+static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos)
 {
+       int i;
        struct net_device *dev;
 
-       dev = dev_base;
-       if (dev && !dev->dn_ptr)
-               dev = dn_dev_get_next(seq, dev);
-       if (pos) {
-               while(dev && (dev = dn_dev_get_next(seq, dev)))
-                       --pos;
-       }
-       return dev;
-}
+       read_lock(&dev_base_lock);
 
-static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos)
-{
-       if (*pos) {
-               struct net_device *dev;
-               read_lock(&dev_base_lock);
-               dev = dn_dev_get_idx(seq, *pos - 1);
-               if (dev == NULL)
-                       read_unlock(&dev_base_lock);
-               return dev;
+       if (*pos == 0)
+               return SEQ_START_TOKEN;
+
+       i = 1;
+       for_each_netdev(dev) {
+               if (!is_dn_dev(dev))
+                       continue;
+
+               if (i++ == *pos)
+                       return dev;
        }
-       return SEQ_START_TOKEN;
+
+       return NULL;
 }
 
 static void *dn_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-       struct net_device *dev = v;
-       loff_t one = 1;
+       struct net_device *dev;
 
-       if (v == SEQ_START_TOKEN) {
-               dev = dn_dev_seq_start(seq, &one);
-       } else {
-               dev = dn_dev_get_next(seq, dev);
-               if (dev == NULL)
-                       read_unlock(&dev_base_lock);
-       }
        ++*pos;
-       return dev;
+
+       dev = (struct net_device *)v;
+       if (v == SEQ_START_TOKEN)
+               dev = net_device_entry(&dev_base_head);
+
+       for_each_netdev_continue(dev) {
+               if (!is_dn_dev(dev))
+                       continue;
+
+               return dev;
+       }
+
+       return NULL;
 }
 
 static void dn_dev_seq_stop(struct seq_file *seq, void *v)
 {
-       if (v && v != SEQ_START_TOKEN)
-               read_unlock(&dev_base_lock);
+       read_unlock(&dev_base_lock);
 }
 
 static char *dn_type2asc(char type)
index 310a862..d2bc19d 100644 (file)
@@ -602,7 +602,7 @@ static void dn_fib_del_ifaddr(struct dn_ifaddr *ifa)
 
        /* Scan device list */
        read_lock(&dev_base_lock);
-       for(dev = dev_base; dev; dev = dev->next) {
+       for_each_netdev(dev) {
                dn_db = dev->dn_ptr;
                if (dn_db == NULL)
                        continue;
index 5d7337b..a8bf106 100644 (file)
@@ -886,7 +886,7 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old
                            .iif = loopback_dev.ifindex,
                            .oif = oldflp->oif };
        struct dn_route *rt = NULL;
-       struct net_device *dev_out = NULL;
+       struct net_device *dev_out = NULL, *dev;
        struct neighbour *neigh = NULL;
        unsigned hash;
        unsigned flags = 0;
@@ -925,15 +925,17 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old
                        goto out;
                }
                read_lock(&dev_base_lock);
-               for(dev_out = dev_base; dev_out; dev_out = dev_out->next) {
-                       if (!dev_out->dn_ptr)
+               for_each_netdev(dev) {
+                       if (!dev->dn_ptr)
                                continue;
-                       if (!dn_dev_islocal(dev_out, oldflp->fld_src))
+                       if (!dn_dev_islocal(dev, oldflp->fld_src))
                                continue;
-                       if ((dev_out->flags & IFF_LOOPBACK) &&
+                       if ((dev->flags & IFF_LOOPBACK) &&
                            oldflp->fld_dst &&
-                           !dn_dev_islocal(dev_out, oldflp->fld_dst))
+                           !dn_dev_islocal(dev, oldflp->fld_dst))
                                continue;
+
+                       dev_out = dev;
                        break;
                }
                read_unlock(&dev_base_lock);
index 088888d..7f95e6e 100644 (file)
@@ -910,7 +910,7 @@ no_in_dev:
         */
        read_lock(&dev_base_lock);
        rcu_read_lock();
-       for (dev = dev_base; dev; dev = dev->next) {
+       for_each_netdev(dev) {
                if ((in_dev = __in_dev_get_rcu(dev)) == NULL)
                        continue;
 
@@ -989,7 +989,7 @@ __be32 inet_confirm_addr(const struct net_device *dev, __be32 dst, __be32 local,
 
        read_lock(&dev_base_lock);
        rcu_read_lock();
-       for (dev = dev_base; dev; dev = dev->next) {
+       for_each_netdev(dev) {
                if ((in_dev = __in_dev_get_rcu(dev))) {
                        addr = confirm_addr_indev(in_dev, dst, local, scope);
                        if (addr)
@@ -1182,23 +1182,26 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
        int s_ip_idx, s_idx = cb->args[0];
 
        s_ip_idx = ip_idx = cb->args[1];
-       for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
+       idx = 0;
+       for_each_netdev(dev) {
                if (idx < s_idx)
-                       continue;
+                       goto cont;
                if (idx > s_idx)
                        s_ip_idx = 0;
                if ((in_dev = __in_dev_get_rtnl(dev)) == NULL)
-                       continue;
+                       goto cont;
 
                for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
                     ifa = ifa->ifa_next, ip_idx++) {
                        if (ip_idx < s_ip_idx)
-                               continue;
+                               goto cont;
                        if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
                                             cb->nlh->nlmsg_seq,
                                             RTM_NEWADDR, NLM_F_MULTI) <= 0)
                                goto done;
                }
+cont:
+               idx++;
        }
 
 done:
@@ -1243,7 +1246,7 @@ void inet_forward_change(void)
        ipv4_devconf_dflt.forwarding = on;
 
        read_lock(&dev_base_lock);
-       for (dev = dev_base; dev; dev = dev->next) {
+       for_each_netdev(dev) {
                struct in_device *in_dev;
                rcu_read_lock();
                in_dev = __in_dev_get_rcu(dev);
index 2506021..f4dd474 100644 (file)
@@ -2288,9 +2288,8 @@ static inline struct ip_mc_list *igmp_mc_get_first(struct seq_file *seq)
        struct ip_mc_list *im = NULL;
        struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);
 
-       for (state->dev = dev_base, state->in_dev = NULL;
-            state->dev;
-            state->dev = state->dev->next) {
+       state->in_dev = NULL;
+       for_each_netdev(state->dev) {
                struct in_device *in_dev;
                in_dev = in_dev_get(state->dev);
                if (!in_dev)
@@ -2316,7 +2315,7 @@ static struct ip_mc_list *igmp_mc_get_next(struct seq_file *seq, struct ip_mc_li
                        read_unlock(&state->in_dev->mc_list_lock);
                        in_dev_put(state->in_dev);
                }
-               state->dev = state->dev->next;
+               state->dev = next_net_device(state->dev);
                if (!state->dev) {
                        state->in_dev = NULL;
                        break;
@@ -2450,9 +2449,9 @@ static inline struct ip_sf_list *igmp_mcf_get_first(struct seq_file *seq)
        struct ip_mc_list *im = NULL;
        struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);
 
-       for (state->dev = dev_base, state->idev = NULL, state->im = NULL;
-            state->dev;
-            state->dev = state->dev->next) {
+       state->idev = NULL;
+       state->im = NULL;
+       for_each_netdev(state->dev) {
                struct in_device *idev;
                idev = in_dev_get(state->dev);
                if (unlikely(idev == NULL))
@@ -2488,7 +2487,7 @@ static struct ip_sf_list *igmp_mcf_get_next(struct seq_file *seq, struct ip_sf_l
                                read_unlock(&state->idev->mc_list_lock);
                                in_dev_put(state->idev);
                        }
-                       state->dev = state->dev->next;
+                       state->dev = next_net_device(state->dev);
                        if (!state->dev) {
                                state->idev = NULL;
                                goto out;
index 597c800..342ca8d 100644 (file)
@@ -192,7 +192,7 @@ static int __init ic_open_devs(void)
        if (dev_change_flags(&loopback_dev, loopback_dev.flags | IFF_UP) < 0)
                printk(KERN_ERR "IP-Config: Failed to open %s\n", loopback_dev.name);
 
-       for (dev = dev_base; dev; dev = dev->next) {
+       for_each_netdev(dev) {
                if (dev == &loopback_dev)
                        continue;
                if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) :
index e5a34c1..c3908bc 100644 (file)
@@ -72,6 +72,11 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple,
        __be16 *keyptr;
        unsigned int min, i, range_size;
 
+       /* If there is no master conntrack we are not PPTP,
+          do not change tuples */
+       if (!conntrack->master)
+               return 0;
+
        if (maniptype == IP_NAT_MANIP_SRC)
                keyptr = &tuple->src.u.gre.key;
        else
@@ -122,18 +127,9 @@ gre_manip_pkt(struct sk_buff **pskb, unsigned int iphdroff,
        if (maniptype != IP_NAT_MANIP_DST)
                return 1;
        switch (greh->version) {
-       case 0:
-               if (!greh->key) {
-                       DEBUGP("can't nat GRE w/o key\n");
-                       break;
-               }
-               if (greh->csum) {
-                       /* FIXME: Never tested this code... */
-                       nf_proto_csum_replace4(gre_csum(greh), *pskb,
-                                              *(gre_key(greh)),
-                                              tuple->dst.u.gre.key, 0);
-               }
-               *(gre_key(greh)) = tuple->dst.u.gre.key;
+       case GRE_VERSION_1701:
+               /* We do not currently NAT any GREv0 packets.
+                * Try to behave like "nf_nat_proto_unknown" */
                break;
        case GRE_VERSION_PPTP:
                DEBUGP("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key));
index 2a28339..2534f71 100644 (file)
@@ -226,10 +226,6 @@ static int ipt_dnat_checkentry(const char *tablename,
                printk("DNAT: multiple ranges no longer supported\n");
                return 0;
        }
-       if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM) {
-               printk("DNAT: port randomization not supported\n");
-               return 0;
-       }
        return 1;
 }
 
index bfd88e4..fac97cf 100644 (file)
@@ -222,6 +222,29 @@ static unsigned int mangle_sdp(struct sk_buff **pskb,
        return mangle_content_len(pskb, ctinfo, ct, dptr);
 }
 
+static void ip_nat_sdp_expect(struct nf_conn *ct,
+                             struct nf_conntrack_expect *exp)
+{
+       struct nf_nat_range range;
+
+       /* This must be a fresh one. */
+       BUG_ON(ct->status & IPS_NAT_DONE_MASK);
+
+       /* Change src to where master sends to */
+       range.flags = IP_NAT_RANGE_MAP_IPS;
+       range.min_ip = range.max_ip
+               = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip;
+       /* hook doesn't matter, but it has to do source manip */
+       nf_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
+
+       /* For DST manip, map port here to where it's expected. */
+       range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
+       range.min = range.max = exp->saved_proto;
+       range.min_ip = range.max_ip = exp->saved_ip;
+       /* hook doesn't matter, but it has to do destination manip */
+       nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
+}
+
 /* So, this packet has hit the connection tracking matching code.
    Mangle it, and change the expectation to match the new version. */
 static unsigned int ip_nat_sdp(struct sk_buff **pskb,
@@ -239,13 +262,14 @@ static unsigned int ip_nat_sdp(struct sk_buff **pskb,
        /* Connection will come from reply */
        newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
 
+       exp->saved_ip = exp->tuple.dst.u3.ip;
        exp->tuple.dst.u3.ip = newip;
        exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
        exp->dir = !dir;
 
        /* When you see the packet, we need to NAT it the same as the
           this one. */
-       exp->expectfn = nf_nat_follow_master;
+       exp->expectfn = ip_nat_sdp_expect;
 
        /* Try to get same port: if not, try to change it. */
        for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) {
index d6e4886..8b124ea 100644 (file)
@@ -1760,8 +1760,7 @@ int tcp_disconnect(struct sock *sk, int flags)
        tcp_clear_retrans(tp);
        inet_csk_delack_init(sk);
        tcp_init_send_head(sk);
-       tp->rx_opt.saw_tstamp = 0;
-       tcp_sack_reset(&tp->rx_opt);
+       memset(&tp->rx_opt, 0, sizeof(tp->rx_opt));
        __sk_dst_reset(sk);
 
        BUG_TRAP(!inet->num || icsk->icsk_bind_hash);
index a291097..43d624e 100644 (file)
@@ -97,10 +97,6 @@ struct hstcp {
        u32     ai;
 };
 
-static int max_ssthresh = 100;
-module_param(max_ssthresh, int, 0644);
-MODULE_PARM_DESC(max_ssthresh, "limited slow start threshold (RFC3742)");
-
 static void hstcp_init(struct sock *sk)
 {
        struct tcp_sock *tp = tcp_sk(sk);
@@ -122,23 +118,9 @@ static void hstcp_cong_avoid(struct sock *sk, u32 adk, u32 rtt,
        if (!tcp_is_cwnd_limited(sk, in_flight))
                return;
 
-       if (tp->snd_cwnd <= tp->snd_ssthresh) {
-               /* RFC3742: limited slow start
-                * the window is increased by 1/K MSS for each arriving ACK,
-                * for K = int(cwnd/(0.5 max_ssthresh))
-                */
-               if (max_ssthresh > 0 && tp->snd_cwnd > max_ssthresh) {
-                       u32 k = max(tp->snd_cwnd / (max_ssthresh >> 1), 1U);
-                       if (++tp->snd_cwnd_cnt >= k) {
-                               if (tp->snd_cwnd < tp->snd_cwnd_clamp)
-                                       tp->snd_cwnd++;
-                               tp->snd_cwnd_cnt = 0;
-                       }
-               } else {
-                       if (tp->snd_cwnd < tp->snd_cwnd_clamp)
-                               tp->snd_cwnd++;
-               }
-       } else {
+       if (tp->snd_cwnd <= tp->snd_ssthresh)
+               tcp_slow_start(tp);
+       else {
                /* Update AIMD parameters.
                 *
                 * We want to guarantee that:
diff --git a/net/ipv4/tcp_yeah.h b/net/ipv4/tcp_yeah.h
deleted file mode 100644 (file)
index ed3b719..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/inet_diag.h>
-#include <asm/div64.h>
-
-#include <net/tcp.h>
index 3452433..d02685c 100644 (file)
@@ -449,7 +449,7 @@ static void addrconf_forward_change(void)
        struct inet6_dev *idev;
 
        read_lock(&dev_base_lock);
-       for (dev=dev_base; dev; dev=dev->next) {
+       for_each_netdev(dev) {
                rcu_read_lock();
                idev = __in6_dev_get(dev);
                if (idev) {
@@ -911,7 +911,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
        read_lock(&dev_base_lock);
        rcu_read_lock();
 
-       for (dev = dev_base; dev; dev=dev->next) {
+       for_each_netdev(dev) {
                struct inet6_dev *idev;
                struct inet6_ifaddr *ifa;
 
@@ -2064,7 +2064,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev)
                return;
        }
 
-       for (dev = dev_base; dev != NULL; dev = dev->next) {
+       for_each_netdev(dev) {
                struct in_device * in_dev = __in_dev_get_rtnl(dev);
                if (in_dev && (dev->flags & IFF_UP)) {
                        struct in_ifaddr * ifa;
@@ -2225,7 +2225,7 @@ static void ip6_tnl_add_linklocal(struct inet6_dev *idev)
                        return;
        }
        /* then try to inherit it from any device */
-       for (link_dev = dev_base; link_dev; link_dev = link_dev->next) {
+       for_each_netdev(link_dev) {
                if (!ipv6_inherit_linklocal(idev, link_dev))
                        return;
        }
@@ -3257,14 +3257,15 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
        s_idx = cb->args[0];
        s_ip_idx = ip_idx = cb->args[1];
 
-       for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
+       idx = 0;
+       for_each_netdev(dev) {
                if (idx < s_idx)
-                       continue;
+                       goto cont;
                if (idx > s_idx)
                        s_ip_idx = 0;
                ip_idx = 0;
                if ((idev = in6_dev_get(dev)) == NULL)
-                       continue;
+                       goto cont;
                read_lock_bh(&idev->lock);
                switch (type) {
                case UNICAST_ADDR:
@@ -3311,6 +3312,8 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
                }
                read_unlock_bh(&idev->lock);
                in6_dev_put(idev);
+cont:
+               idx++;
        }
 done:
        if (err <= 0) {
@@ -3575,16 +3578,19 @@ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
        struct inet6_dev *idev;
 
        read_lock(&dev_base_lock);
-       for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
+       idx = 0;
+       for_each_netdev(dev) {
                if (idx < s_idx)
-                       continue;
+                       goto cont;
                if ((idev = in6_dev_get(dev)) == NULL)
-                       continue;
+                       goto cont;
                err = inet6_fill_ifinfo(skb, idev, NETLINK_CB(cb->skb).pid,
                                cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI);
                in6_dev_put(idev);
                if (err <= 0)
                        break;
+cont:
+               idx++;
        }
        read_unlock(&dev_base_lock);
        cb->args[0] = idx;
@@ -4247,7 +4253,7 @@ void __exit addrconf_cleanup(void)
         *      clean dev list.
         */
 
-       for (dev=dev_base; dev; dev=dev->next) {
+       for_each_netdev(dev) {
                if ((idev = __in6_dev_get(dev)) == NULL)
                        continue;
                addrconf_ifdown(dev, 1);
index 09117d6..9b81264 100644 (file)
@@ -423,14 +423,18 @@ static int ipv6_chk_acast_dev(struct net_device *dev, struct in6_addr *addr)
  */
 int ipv6_chk_acast_addr(struct net_device *dev, struct in6_addr *addr)
 {
+       int found = 0;
+
        if (dev)
                return ipv6_chk_acast_dev(dev, addr);
        read_lock(&dev_base_lock);
-       for (dev=dev_base; dev; dev=dev->next)
-               if (ipv6_chk_acast_dev(dev, addr))
+       for_each_netdev(dev)
+               if (ipv6_chk_acast_dev(dev, addr)) {
+                       found = 1;
                        break;
+               }
        read_unlock(&dev_base_lock);
-       return dev != 0;
+       return found;
 }
 
 
@@ -447,9 +451,8 @@ static inline struct ifacaddr6 *ac6_get_first(struct seq_file *seq)
        struct ifacaddr6 *im = NULL;
        struct ac6_iter_state *state = ac6_seq_private(seq);
 
-       for (state->dev = dev_base, state->idev = NULL;
-            state->dev;
-            state->dev = state->dev->next) {
+       state->idev = NULL;
+       for_each_netdev(state->dev) {
                struct inet6_dev *idev;
                idev = in6_dev_get(state->dev);
                if (!idev)
@@ -476,7 +479,7 @@ static struct ifacaddr6 *ac6_get_next(struct seq_file *seq, struct ifacaddr6 *im
                        read_unlock_bh(&state->idev->lock);
                        in6_dev_put(state->idev);
                }
-               state->dev = state->dev->next;
+               state->dev = next_net_device(state->dev);
                if (!state->dev) {
                        state->idev = NULL;
                        break;
index 6c27589..3e308fb 100644 (file)
@@ -2331,9 +2331,8 @@ static inline struct ifmcaddr6 *igmp6_mc_get_first(struct seq_file *seq)
        struct ifmcaddr6 *im = NULL;
        struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
 
-       for (state->dev = dev_base, state->idev = NULL;
-            state->dev;
-            state->dev = state->dev->next) {
+       state->idev = NULL;
+       for_each_netdev(state->dev) {
                struct inet6_dev *idev;
                idev = in6_dev_get(state->dev);
                if (!idev)
@@ -2360,7 +2359,7 @@ static struct ifmcaddr6 *igmp6_mc_get_next(struct seq_file *seq, struct ifmcaddr
                        read_unlock_bh(&state->idev->lock);
                        in6_dev_put(state->idev);
                }
-               state->dev = state->dev->next;
+               state->dev = next_net_device(state->dev);
                if (!state->dev) {
                        state->idev = NULL;
                        break;
@@ -2475,9 +2474,9 @@ static inline struct ip6_sf_list *igmp6_mcf_get_first(struct seq_file *seq)
        struct ifmcaddr6 *im = NULL;
        struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
 
-       for (state->dev = dev_base, state->idev = NULL, state->im = NULL;
-            state->dev;
-            state->dev = state->dev->next) {
+       state->idev = NULL;
+       state->im = NULL;
+       for_each_netdev(state->dev) {
                struct inet6_dev *idev;
                idev = in6_dev_get(state->dev);
                if (unlikely(idev == NULL))
@@ -2513,7 +2512,7 @@ static struct ip6_sf_list *igmp6_mcf_get_next(struct seq_file *seq, struct ip6_s
                                read_unlock_bh(&state->idev->lock);
                                in6_dev_put(state->idev);
                        }
-                       state->dev = state->dev->next;
+                       state->dev = next_net_device(state->dev);
                        if (!state->dev) {
                                state->idev = NULL;
                                goto out;
index e84c924..d9e9ddb 100644 (file)
@@ -45,7 +45,8 @@ static struct proto iucv_proto = {
 static void iucv_callback_rx(struct iucv_path *, struct iucv_message *);
 static void iucv_callback_txdone(struct iucv_path *, struct iucv_message *);
 static void iucv_callback_connack(struct iucv_path *, u8 ipuser[16]);
-static int iucv_callback_connreq(struct iucv_path *, u8 ipvmid[8], u8 ipuser[16]);
+static int iucv_callback_connreq(struct iucv_path *, u8 ipvmid[8],
+                                u8 ipuser[16]);
 static void iucv_callback_connrej(struct iucv_path *, u8 ipuser[16]);
 
 static struct iucv_sock_list iucv_sk_list = {
@@ -147,11 +148,12 @@ static void iucv_sock_close(struct sock *sk)
        unsigned char user_data[16];
        struct iucv_sock *iucv = iucv_sk(sk);
        int err;
+       unsigned long timeo;
 
        iucv_sock_clear_timer(sk);
        lock_sock(sk);
 
-       switch(sk->sk_state) {
+       switch (sk->sk_state) {
        case IUCV_LISTEN:
                iucv_sock_cleanup_listen(sk);
                break;
@@ -159,6 +161,21 @@ static void iucv_sock_close(struct sock *sk)
        case IUCV_CONNECTED:
        case IUCV_DISCONN:
                err = 0;
+
+               sk->sk_state = IUCV_CLOSING;
+               sk->sk_state_change(sk);
+
+               if (!skb_queue_empty(&iucv->send_skb_q)) {
+                       if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
+                               timeo = sk->sk_lingertime;
+                       else
+                               timeo = IUCV_DISCONN_TIMEOUT;
+                       err = iucv_sock_wait_state(sk, IUCV_CLOSED, 0, timeo);
+               }
+
+               sk->sk_state = IUCV_CLOSED;
+               sk->sk_state_change(sk);
+
                if (iucv->path) {
                        low_nmcpy(user_data, iucv->src_name);
                        high_nmcpy(user_data, iucv->dst_name);
@@ -168,12 +185,11 @@ static void iucv_sock_close(struct sock *sk)
                        iucv->path = NULL;
                }
 
-               sk->sk_state = IUCV_CLOSED;
-               sk->sk_state_change(sk);
                sk->sk_err = ECONNRESET;
                sk->sk_state_change(sk);
 
                skb_queue_purge(&iucv->send_skb_q);
+               skb_queue_purge(&iucv->backlog_skb_q);
 
                sock_set_flag(sk, SOCK_ZAPPED);
                break;
@@ -204,6 +220,7 @@ static struct sock *iucv_sock_alloc(struct socket *sock, int proto, gfp_t prio)
        sock_init_data(sock, sk);
        INIT_LIST_HEAD(&iucv_sk(sk)->accept_q);
        skb_queue_head_init(&iucv_sk(sk)->send_skb_q);
+       skb_queue_head_init(&iucv_sk(sk)->backlog_skb_q);
        iucv_sk(sk)->send_tag = 0;
 
        sk->sk_destruct = iucv_sock_destruct;
@@ -276,7 +293,7 @@ struct sock *iucv_accept_dequeue(struct sock *parent, struct socket *newsock)
        struct iucv_sock *isk, *n;
        struct sock *sk;
 
-       list_for_each_entry_safe(isk, n, &iucv_sk(parent)->accept_q, accept_q){
+       list_for_each_entry_safe(isk, n, &iucv_sk(parent)->accept_q, accept_q) {
                sk = (struct sock *) isk;
                lock_sock(sk);
 
@@ -510,7 +527,7 @@ static int iucv_sock_accept(struct socket *sock, struct socket *newsock,
        long timeo;
        int err = 0;
 
-       lock_sock(sk);
+       lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
 
        if (sk->sk_state != IUCV_LISTEN) {
                err = -EBADFD;
@@ -521,7 +538,7 @@ static int iucv_sock_accept(struct socket *sock, struct socket *newsock,
 
        /* Wait for an incoming connection */
        add_wait_queue_exclusive(sk->sk_sleep, &wait);
-       while (!(nsk = iucv_accept_dequeue(sk, newsock))){
+       while (!(nsk = iucv_accept_dequeue(sk, newsock))) {
                set_current_state(TASK_INTERRUPTIBLE);
                if (!timeo) {
                        err = -EAGAIN;
@@ -530,7 +547,7 @@ static int iucv_sock_accept(struct socket *sock, struct socket *newsock,
 
                release_sock(sk);
                timeo = schedule_timeout(timeo);
-               lock_sock(sk);
+               lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
 
                if (sk->sk_state != IUCV_LISTEN) {
                        err = -EBADFD;
@@ -602,13 +619,13 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
                goto out;
        }
 
-       if (sk->sk_state == IUCV_CONNECTED){
-               if(!(skb = sock_alloc_send_skb(sk, len,
-                                      msg->msg_flags & MSG_DONTWAIT,
-                                      &err)))
-                       return err;
+       if (sk->sk_state == IUCV_CONNECTED) {
+               if (!(skb = sock_alloc_send_skb(sk, len,
+                                               msg->msg_flags & MSG_DONTWAIT,
+                                               &err)))
+                       goto out;
 
-               if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)){
+               if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
                        err = -EFAULT;
                        goto fail;
                }
@@ -647,10 +664,16 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 {
        int noblock = flags & MSG_DONTWAIT;
        struct sock *sk = sock->sk;
+       struct iucv_sock *iucv = iucv_sk(sk);
        int target, copied = 0;
-       struct sk_buff *skb;
+       struct sk_buff *skb, *rskb, *cskb;
        int err = 0;
 
+       if ((sk->sk_state == IUCV_DISCONN || sk->sk_state == IUCV_SEVERED) &&
+               skb_queue_empty(&iucv->backlog_skb_q) &&
+               skb_queue_empty(&sk->sk_receive_queue))
+               return 0;
+
        if (flags & (MSG_OOB))
                return -EOPNOTSUPP;
 
@@ -665,10 +688,12 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 
        copied = min_t(unsigned int, skb->len, len);
 
-       if (memcpy_toiovec(msg->msg_iov, skb->data, copied)) {
+       cskb = skb;
+       if (memcpy_toiovec(msg->msg_iov, cskb->data, copied)) {
                skb_queue_head(&sk->sk_receive_queue, skb);
                if (copied == 0)
                        return -EFAULT;
+               goto done;
        }
 
        len -= copied;
@@ -683,6 +708,18 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
                }
 
                kfree_skb(skb);
+
+               /* Queue backlog skbs */
+               rskb = skb_dequeue(&iucv_sk(sk)->backlog_skb_q);
+               while (rskb) {
+                       if (sock_queue_rcv_skb(sk, rskb)) {
+                               skb_queue_head(&iucv_sk(sk)->backlog_skb_q,
+                                               rskb);
+                               break;
+                       } else {
+                               rskb = skb_dequeue(&iucv_sk(sk)->backlog_skb_q);
+                       }
+               }
        } else
                skb_queue_head(&sk->sk_receive_queue, skb);
 
@@ -695,7 +732,7 @@ static inline unsigned int iucv_accept_poll(struct sock *parent)
        struct iucv_sock *isk, *n;
        struct sock *sk;
 
-       list_for_each_entry_safe(isk, n, &iucv_sk(parent)->accept_q, accept_q){
+       list_for_each_entry_safe(isk, n, &iucv_sk(parent)->accept_q, accept_q) {
                sk = (struct sock *) isk;
 
                if (sk->sk_state == IUCV_CONNECTED)
@@ -726,12 +763,15 @@ unsigned int iucv_sock_poll(struct file *file, struct socket *sock,
                mask |= POLLHUP;
 
        if (!skb_queue_empty(&sk->sk_receive_queue) ||
-                       (sk->sk_shutdown & RCV_SHUTDOWN))
+           (sk->sk_shutdown & RCV_SHUTDOWN))
                mask |= POLLIN | POLLRDNORM;
 
        if (sk->sk_state == IUCV_CLOSED)
                mask |= POLLHUP;
 
+       if (sk->sk_state == IUCV_DISCONN || sk->sk_state == IUCV_SEVERED)
+               mask |= POLLIN;
+
        if (sock_writeable(sk))
                mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
        else
@@ -754,7 +794,7 @@ static int iucv_sock_shutdown(struct socket *sock, int how)
                return -EINVAL;
 
        lock_sock(sk);
-       switch(sk->sk_state) {
+       switch (sk->sk_state) {
        case IUCV_CLOSED:
                err = -ENOTCONN;
                goto fail;
@@ -770,7 +810,7 @@ static int iucv_sock_shutdown(struct socket *sock, int how)
                err = iucv_message_send(iucv->path, &txmsg, IUCV_IPRMDATA, 0,
                                        (void *) prmmsg, 8);
                if (err) {
-                       switch(err) {
+                       switch (err) {
                        case 1:
                                err = -ENOTCONN;
                                break;
@@ -817,13 +857,6 @@ static int iucv_sock_release(struct socket *sock)
                iucv_sk(sk)->path = NULL;
        }
 
-       if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime){
-               lock_sock(sk);
-               err = iucv_sock_wait_state(sk, IUCV_CLOSED, 0,
-                                          sk->sk_lingertime);
-               release_sock(sk);
-       }
-
        sock_orphan(sk);
        iucv_sock_kill(sk);
        return err;
@@ -880,7 +913,7 @@ static int iucv_callback_connreq(struct iucv_path *path,
 
        /* Create the new socket */
        nsk = iucv_sock_alloc(NULL, SOCK_STREAM, GFP_ATOMIC);
-       if (!nsk){
+       if (!nsk) {
                err = iucv_path_sever(path, user_data);
                goto fail;
        }
@@ -903,7 +936,7 @@ static int iucv_callback_connreq(struct iucv_path *path,
 
        path->msglim = IUCV_QUEUELEN_DEFAULT;
        err = iucv_path_accept(path, &af_iucv_handler, nuser_data, nsk);
-       if (err){
+       if (err) {
                err = iucv_path_sever(path, user_data);
                goto fail;
        }
@@ -927,18 +960,53 @@ static void iucv_callback_connack(struct iucv_path *path, u8 ipuser[16])
        sk->sk_state_change(sk);
 }
 
+static int iucv_fragment_skb(struct sock *sk, struct sk_buff *skb, int len,
+                            struct sk_buff_head *fragmented_skb_q)
+{
+       int dataleft, size, copied = 0;
+       struct sk_buff *nskb;
+
+       dataleft = len;
+       while (dataleft) {
+               if (dataleft >= sk->sk_rcvbuf / 4)
+                       size = sk->sk_rcvbuf / 4;
+               else
+                       size = dataleft;
+
+               nskb = alloc_skb(size, GFP_ATOMIC | GFP_DMA);
+               if (!nskb)
+                       return -ENOMEM;
+
+               memcpy(nskb->data, skb->data + copied, size);
+               copied += size;
+               dataleft -= size;
+
+               skb_reset_transport_header(nskb);
+               skb_reset_network_header(nskb);
+               nskb->len = size;
+
+               skb_queue_tail(fragmented_skb_q, nskb);
+       }
+
+       return 0;
+}
+
 static void iucv_callback_rx(struct iucv_path *path, struct iucv_message *msg)
 {
        struct sock *sk = path->private;
-       struct sk_buff *skb;
+       struct iucv_sock *iucv = iucv_sk(sk);
+       struct sk_buff *skb, *fskb;
+       struct sk_buff_head fragmented_skb_q;
        int rc;
 
+       skb_queue_head_init(&fragmented_skb_q);
+
        if (sk->sk_shutdown & RCV_SHUTDOWN)
                return;
 
        skb = alloc_skb(msg->length, GFP_ATOMIC | GFP_DMA);
        if (!skb) {
-               iucv_message_reject(path, msg);
+               iucv_path_sever(path, NULL);
                return;
        }
 
@@ -952,14 +1020,39 @@ static void iucv_callback_rx(struct iucv_path *path, struct iucv_message *msg)
                        kfree_skb(skb);
                        return;
                }
+               if (skb->truesize >= sk->sk_rcvbuf / 4) {
+                       rc = iucv_fragment_skb(sk, skb, msg->length,
+                                              &fragmented_skb_q);
+                       kfree_skb(skb);
+                       skb = NULL;
+                       if (rc) {
+                               iucv_path_sever(path, NULL);
+                               return;
+                       }
+               } else {
+                       skb_reset_transport_header(skb);
+                       skb_reset_network_header(skb);
+                       skb->len = msg->length;
+               }
+       }
+       /* Queue the fragmented skb */
+       fskb = skb_dequeue(&fragmented_skb_q);
+       while (fskb) {
+               if (!skb_queue_empty(&iucv->backlog_skb_q))
+                       skb_queue_tail(&iucv->backlog_skb_q, fskb);
+               else if (sock_queue_rcv_skb(sk, fskb))
+                       skb_queue_tail(&iucv_sk(sk)->backlog_skb_q, fskb);
+               fskb = skb_dequeue(&fragmented_skb_q);
+       }
 
-               skb_reset_transport_header(skb);
-               skb_reset_network_header(skb);
-               skb->len = msg->length;
+       /* Queue the original skb if it exists (was not fragmented) */
+       if (skb) {
+               if (!skb_queue_empty(&iucv->backlog_skb_q))
+                       skb_queue_tail(&iucv_sk(sk)->backlog_skb_q, skb);
+               else if (sock_queue_rcv_skb(sk, skb))
+                       skb_queue_tail(&iucv_sk(sk)->backlog_skb_q, skb);
        }
 
-       if (sock_queue_rcv_skb(sk, skb))
-               kfree_skb(skb);
 }
 
 static void iucv_callback_txdone(struct iucv_path *path,
@@ -971,17 +1064,27 @@ static void iucv_callback_txdone(struct iucv_path *path,
        struct sk_buff *list_skb = list->next;
        unsigned long flags;
 
-       spin_lock_irqsave(&list->lock, flags);
+       if (list_skb) {
+               spin_lock_irqsave(&list->lock, flags);
+
+               do {
+                       this = list_skb;
+                       list_skb = list_skb->next;
+               } while (memcmp(&msg->tag, this->cb, 4) && list_skb);
+
+               spin_unlock_irqrestore(&list->lock, flags);
 
-       do {
-               this = list_skb;
-               list_skb = list_skb->next;
-       } while (memcmp(&msg->tag, this->cb, 4));
+               skb_unlink(this, &iucv_sk(sk)->send_skb_q);
+               kfree_skb(this);
+       }
 
-       spin_unlock_irqrestore(&list->lock, flags);
+       if (sk->sk_state == IUCV_CLOSING) {
+               if (skb_queue_empty(&iucv_sk(sk)->send_skb_q)) {
+                       sk->sk_state = IUCV_CLOSED;
+                       sk->sk_state_change(sk);
+               }
+       }
 
-       skb_unlink(this, &iucv_sk(sk)->send_skb_q);
-       kfree_skb(this);
 }
 
 static void iucv_callback_connrej(struct iucv_path *path, u8 ipuser[16])
@@ -1022,7 +1125,7 @@ static struct net_proto_family iucv_sock_family_ops = {
        .create = iucv_sock_create,
 };
 
-static int afiucv_init(void)
+static int __init afiucv_init(void)
 {
        int err;
 
index 903bdb6..fb3faf7 100644 (file)
@@ -32,7 +32,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-
 #include <linux/spinlock.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -69,7 +68,7 @@
 #define IUCV_IPNORPY   0x10
 #define IUCV_IPALL     0x80
 
-static int iucv_bus_match (struct device *dev, struct device_driver *drv)
+static int iucv_bus_match(struct device *dev, struct device_driver *drv)
 {
        return 0;
 }
@@ -78,8 +77,11 @@ struct bus_type iucv_bus = {
        .name = "iucv",
        .match = iucv_bus_match,
 };
+EXPORT_SYMBOL(iucv_bus);
 
 struct device *iucv_root;
+EXPORT_SYMBOL(iucv_root);
+
 static int iucv_available;
 
 /* General IUCV interrupt structure */
@@ -405,7 +407,7 @@ static void iucv_declare_cpu(void *data)
        rc = iucv_call_b2f0(IUCV_DECLARE_BUFFER, parm);
        if (rc) {
                char *err = "Unknown";
-               switch(rc) {
+               switch (rc) {
                case 0x03:
                        err = "Directory error";
                        break;
@@ -588,7 +590,7 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self,
        return NOTIFY_OK;
 }
 
-static struct notifier_block iucv_cpu_notifier = {
+static struct notifier_block __cpuinitdata iucv_cpu_notifier = {
        .notifier_call = iucv_cpu_notify,
 };
 
@@ -691,6 +693,7 @@ out_mutex:
        mutex_unlock(&iucv_register_mutex);
        return rc;
 }
+EXPORT_SYMBOL(iucv_register);
 
 /**
  * iucv_unregister
@@ -723,6 +726,7 @@ void iucv_unregister(struct iucv_handler *handler, int smp)
                iucv_setmask_mp();
        mutex_unlock(&iucv_register_mutex);
 }
+EXPORT_SYMBOL(iucv_unregister);
 
 /**
  * iucv_path_accept
@@ -761,6 +765,7 @@ int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler,
        local_bh_enable();
        return rc;
 }
+EXPORT_SYMBOL(iucv_path_accept);
 
 /**
  * iucv_path_connect
@@ -824,6 +829,7 @@ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler,
        spin_unlock_bh(&iucv_table_lock);
        return rc;
 }
+EXPORT_SYMBOL(iucv_path_connect);
 
 /**
  * iucv_path_quiesce:
@@ -850,6 +856,7 @@ int iucv_path_quiesce(struct iucv_path *path, u8 userdata[16])
        local_bh_enable();
        return rc;
 }
+EXPORT_SYMBOL(iucv_path_quiesce);
 
 /**
  * iucv_path_resume:
@@ -890,7 +897,6 @@ int iucv_path_sever(struct iucv_path *path, u8 userdata[16])
 {
        int rc;
 
-
        preempt_disable();
        if (iucv_active_cpu != smp_processor_id())
                spin_lock_bh(&iucv_table_lock);
@@ -904,6 +910,7 @@ int iucv_path_sever(struct iucv_path *path, u8 userdata[16])
        preempt_enable();
        return rc;
 }
+EXPORT_SYMBOL(iucv_path_sever);
 
 /**
  * iucv_message_purge
@@ -936,6 +943,7 @@ int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg,
        local_bh_enable();
        return rc;
 }
+EXPORT_SYMBOL(iucv_message_purge);
 
 /**
  * iucv_message_receive
@@ -1006,6 +1014,7 @@ int iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
        local_bh_enable();
        return rc;
 }
+EXPORT_SYMBOL(iucv_message_receive);
 
 /**
  * iucv_message_reject
@@ -1034,6 +1043,7 @@ int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg)
        local_bh_enable();
        return rc;
 }
+EXPORT_SYMBOL(iucv_message_reject);
 
 /**
  * iucv_message_reply
@@ -1077,6 +1087,7 @@ int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg,
        local_bh_enable();
        return rc;
 }
+EXPORT_SYMBOL(iucv_message_reply);
 
 /**
  * iucv_message_send
@@ -1125,6 +1136,7 @@ int iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
        local_bh_enable();
        return rc;
 }
+EXPORT_SYMBOL(iucv_message_send);
 
 /**
  * iucv_message_send2way
@@ -1181,6 +1193,7 @@ int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg,
        local_bh_enable();
        return rc;
 }
+EXPORT_SYMBOL(iucv_message_send2way);
 
 /**
  * iucv_path_pending
@@ -1572,7 +1585,7 @@ static void iucv_external_interrupt(u16 code)
  *
  * Allocates and initializes various data structures.
  */
-static int iucv_init(void)
+static int __init iucv_init(void)
 {
        int rc;
 
@@ -1583,7 +1596,7 @@ static int iucv_init(void)
        rc = iucv_query_maxconn();
        if (rc)
                goto out;
-       rc = register_external_interrupt (0x4000, iucv_external_interrupt);
+       rc = register_external_interrupt(0x4000, iucv_external_interrupt);
        if (rc)
                goto out;
        rc = bus_register(&iucv_bus);
@@ -1594,7 +1607,7 @@ static int iucv_init(void)
                rc = PTR_ERR(iucv_root);
                goto out_bus;
        }
-       /* Note: GFP_DMA used used to get memory below 2G */
+       /* Note: GFP_DMA used to get memory below 2G */
        iucv_irq_data = percpu_alloc(sizeof(struct iucv_irq_data),
                                     GFP_KERNEL|GFP_DMA);
        if (!iucv_irq_data) {
@@ -1632,7 +1645,7 @@ out:
  *
  * Frees everything allocated from iucv_init.
  */
-static void iucv_exit(void)
+static void __exit iucv_exit(void)
 {
        struct iucv_irq_list *p, *n;
 
@@ -1653,24 +1666,6 @@ static void iucv_exit(void)
 subsys_initcall(iucv_init);
 module_exit(iucv_exit);
 
-/**
- * Export all public stuff
- */
-EXPORT_SYMBOL (iucv_bus);
-EXPORT_SYMBOL (iucv_root);
-EXPORT_SYMBOL (iucv_register);
-EXPORT_SYMBOL (iucv_unregister);
-EXPORT_SYMBOL (iucv_path_accept);
-EXPORT_SYMBOL (iucv_path_connect);
-EXPORT_SYMBOL (iucv_path_quiesce);
-EXPORT_SYMBOL (iucv_path_sever);
-EXPORT_SYMBOL (iucv_message_purge);
-EXPORT_SYMBOL (iucv_message_receive);
-EXPORT_SYMBOL (iucv_message_reject);
-EXPORT_SYMBOL (iucv_message_reply);
-EXPORT_SYMBOL (iucv_message_send);
-EXPORT_SYMBOL (iucv_message_send2way);
-
 MODULE_AUTHOR("(C) 2001 IBM Corp. by Fritz Elfert (felfert@millenux.com)");
 MODULE_DESCRIPTION("Linux for S/390 IUCV lowlevel driver");
 MODULE_LICENSE("GPL");
index d12413c..d4b13a0 100644 (file)
@@ -160,8 +160,14 @@ static struct packet_type llc_tr_packet_type = {
 
 static int __init llc_init(void)
 {
-       if (dev_base->next)
-               memcpy(llc_station_mac_sa, dev_base->next->dev_addr, ETH_ALEN);
+       struct net_device *dev;
+
+       dev = first_net_device();
+       if (dev != NULL)
+               dev = next_net_device(dev);
+
+       if (dev != NULL)
+               memcpy(llc_station_mac_sa, dev->dev_addr, ETH_ALEN);
        else
                memset(llc_station_mac_sa, 0, ETH_ALEN);
        dev_add_pack(&llc_packet_type);
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
new file mode 100644 (file)
index 0000000..6fffb38
--- /dev/null
@@ -0,0 +1,78 @@
+config MAC80211
+       tristate "Generic IEEE 802.11 Networking Stack (mac80211)"
+       depends on EXPERIMENTAL
+       select CRYPTO
+       select CRYPTO_ECB
+       select CRYPTO_ARC4
+       select CRYPTO_AES
+       select CRC32
+       select WIRELESS_EXT
+       select CFG80211
+       select NET_SCH_FIFO
+       ---help---
+       This option enables the hardware independent IEEE 802.11
+       networking stack.
+
+config MAC80211_LEDS
+       bool "Enable LED triggers"
+       depends on MAC80211 && LEDS_TRIGGERS
+       ---help---
+       This option enables a few LED triggers for different
+       packet receive/transmit events.
+
+config MAC80211_DEBUGFS
+       bool "Export mac80211 internals in DebugFS"
+       depends on MAC80211 && DEBUG_FS
+       ---help---
+         Select this to see extensive information about
+         the internal state of mac80211 in debugfs.
+
+         Say N unless you know you need this.
+
+config MAC80211_DEBUG
+       bool "Enable debugging output"
+       depends on MAC80211
+       ---help---
+         This option will enable debug tracing output for the
+         ieee80211 network stack.
+
+         If you are not trying to debug or develop the ieee80211
+         subsystem, you most likely want to say N here.
+
+config MAC80211_VERBOSE_DEBUG
+       bool "Verbose debugging output"
+       depends on MAC80211_DEBUG
+
+config MAC80211_LOWTX_FRAME_DUMP
+       bool "Debug frame dumping"
+       depends on MAC80211_DEBUG
+       ---help---
+         Selecting this option will cause the stack to
+         print a message for each frame that is handed
+         to the lowlevel driver for transmission. This
+         message includes all MAC addresses and the
+         frame control field.
+
+         If unsure, say N and insert the debugging code
+         you require into the driver you are debugging.
+
+config TKIP_DEBUG
+       bool "TKIP debugging"
+       depends on MAC80211_DEBUG
+
+config MAC80211_DEBUG_COUNTERS
+       bool "Extra statistics for TX/RX debugging"
+       depends on MAC80211_DEBUG
+
+config MAC80211_IBSS_DEBUG
+       bool "Support for IBSS testing"
+       depends on MAC80211_DEBUG
+       ---help---
+         Say Y here if you intend to debug the IBSS code.
+
+config MAC80211_VERBOSE_PS_DEBUG
+       bool "Verbose powersave mode debugging"
+       depends on MAC80211_DEBUG
+       ---help---
+         Say Y here to print out verbose powersave
+         mode debug messages.
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
new file mode 100644 (file)
index 0000000..e9738da
--- /dev/null
@@ -0,0 +1,20 @@
+obj-$(CONFIG_MAC80211) += mac80211.o rc80211_simple.o
+
+mac80211-objs-$(CONFIG_MAC80211_LEDS) += ieee80211_led.o
+mac80211-objs-$(CONFIG_MAC80211_DEBUGFS) += debugfs.o debugfs_sta.o debugfs_netdev.o debugfs_key.o
+
+mac80211-objs := \
+       ieee80211.o \
+       ieee80211_ioctl.o \
+       sta_info.o \
+       wep.o \
+       wpa.o \
+       ieee80211_sta.o \
+       ieee80211_iface.o \
+       ieee80211_rate.o \
+       michael.o \
+       tkip.o \
+       aes_ccm.o \
+       wme.o \
+       ieee80211_cfg.o \
+       $(mac80211-objs-y)
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
new file mode 100644 (file)
index 0000000..e55569b
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2003-2004, Instant802 Networks, Inc.
+ * Copyright 2005-2006, Devicescape Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <asm/scatterlist.h>
+
+#include <net/mac80211.h>
+#include "ieee80211_key.h"
+#include "aes_ccm.h"
+
+
+static void ieee80211_aes_encrypt(struct crypto_cipher *tfm,
+                                 const u8 pt[16], u8 ct[16])
+{
+       crypto_cipher_encrypt_one(tfm, ct, pt);
+}
+
+
+static inline void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
+                                  u8 *b, u8 *s_0, u8 *a)
+{
+       int i;
+
+       ieee80211_aes_encrypt(tfm, b_0, b);
+
+       /* Extra Authenticate-only data (always two AES blocks) */
+       for (i = 0; i < AES_BLOCK_LEN; i++)
+               aad[i] ^= b[i];
+       ieee80211_aes_encrypt(tfm, aad, b);
+
+       aad += AES_BLOCK_LEN;
+
+       for (i = 0; i < AES_BLOCK_LEN; i++)
+               aad[i] ^= b[i];
+       ieee80211_aes_encrypt(tfm, aad, a);
+
+       /* Mask out bits from auth-only-b_0 */
+       b_0[0] &= 0x07;
+
+       /* S_0 is used to encrypt T (= MIC) */
+       b_0[14] = 0;
+       b_0[15] = 0;
+       ieee80211_aes_encrypt(tfm, b_0, s_0);
+}
+
+
+void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
+                              u8 *b_0, u8 *aad, u8 *data, size_t data_len,
+                              u8 *cdata, u8 *mic)
+{
+       int i, j, last_len, num_blocks;
+       u8 *pos, *cpos, *b, *s_0, *e;
+
+       b = scratch;
+       s_0 = scratch + AES_BLOCK_LEN;
+       e = scratch + 2 * AES_BLOCK_LEN;
+
+       num_blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
+       last_len = data_len % AES_BLOCK_LEN;
+       aes_ccm_prepare(tfm, b_0, aad, b, s_0, b);
+
+       /* Process payload blocks */
+       pos = data;
+       cpos = cdata;
+       for (j = 1; j <= num_blocks; j++) {
+               int blen = (j == num_blocks && last_len) ?
+                       last_len : AES_BLOCK_LEN;
+
+               /* Authentication followed by encryption */
+               for (i = 0; i < blen; i++)
+                       b[i] ^= pos[i];
+               ieee80211_aes_encrypt(tfm, b, b);
+
+               b_0[14] = (j >> 8) & 0xff;
+               b_0[15] = j & 0xff;
+               ieee80211_aes_encrypt(tfm, b_0, e);
+               for (i = 0; i < blen; i++)
+                       *cpos++ = *pos++ ^ e[i];
+       }
+
+       for (i = 0; i < CCMP_MIC_LEN; i++)
+               mic[i] = b[i] ^ s_0[i];
+}
+
+
+int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
+                             u8 *b_0, u8 *aad, u8 *cdata, size_t data_len,
+                             u8 *mic, u8 *data)
+{
+       int i, j, last_len, num_blocks;
+       u8 *pos, *cpos, *b, *s_0, *a;
+
+       b = scratch;
+       s_0 = scratch + AES_BLOCK_LEN;
+       a = scratch + 2 * AES_BLOCK_LEN;
+
+       num_blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
+       last_len = data_len % AES_BLOCK_LEN;
+       aes_ccm_prepare(tfm, b_0, aad, b, s_0, a);
+
+       /* Process payload blocks */
+       cpos = cdata;
+       pos = data;
+       for (j = 1; j <= num_blocks; j++) {
+               int blen = (j == num_blocks && last_len) ?
+                       last_len : AES_BLOCK_LEN;
+
+               /* Decryption followed by authentication */
+               b_0[14] = (j >> 8) & 0xff;
+               b_0[15] = j & 0xff;
+               ieee80211_aes_encrypt(tfm, b_0, b);
+               for (i = 0; i < blen; i++) {
+                       *pos = *cpos++ ^ b[i];
+                       a[i] ^= *pos++;
+               }
+
+               ieee80211_aes_encrypt(tfm, a, a);
+       }
+
+       for (i = 0; i < CCMP_MIC_LEN; i++) {
+               if ((mic[i] ^ s_0[i]) != a[i])
+                       return -1;
+       }
+
+       return 0;
+}
+
+
+struct crypto_cipher * ieee80211_aes_key_setup_encrypt(const u8 key[])
+{
+       struct crypto_cipher *tfm;
+
+       tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
+       if (IS_ERR(tfm))
+               return NULL;
+
+       crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN);
+
+       return tfm;
+}
+
+
+void ieee80211_aes_key_free(struct crypto_cipher *tfm)
+{
+       if (tfm)
+               crypto_free_cipher(tfm);
+}
diff --git a/net/mac80211/aes_ccm.h b/net/mac80211/aes_ccm.h
new file mode 100644 (file)
index 0000000..885f190
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2003-2004, Instant802 Networks, Inc.
+ * Copyright 2006, Devicescape Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef AES_CCM_H
+#define AES_CCM_H
+
+#include <linux/crypto.h>
+
+#define AES_BLOCK_LEN 16
+
+struct crypto_cipher * ieee80211_aes_key_setup_encrypt(const u8 key[]);
+void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
+                              u8 *b_0, u8 *aad, u8 *data, size_t data_len,
+                              u8 *cdata, u8 *mic);
+int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
+                             u8 *b_0, u8 *aad, u8 *cdata, size_t data_len,
+                             u8 *mic, u8 *data);
+void ieee80211_aes_key_free(struct crypto_cipher *tfm);
+
+#endif /* AES_CCM_H */
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
new file mode 100644 (file)
index 0000000..bb6c0fe
--- /dev/null
@@ -0,0 +1,433 @@
+/*
+ * mac80211 debugfs for wireless PHYs
+ *
+ * Copyright 2007      Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPLv2
+ *
+ */
+
+#include <linux/debugfs.h>
+#include <linux/rtnetlink.h>
+#include "ieee80211_i.h"
+#include "ieee80211_rate.h"
+#include "debugfs.h"
+
+int mac80211_open_file_generic(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+static const char *ieee80211_mode_str(int mode)
+{
+       switch (mode) {
+       case MODE_IEEE80211A:
+               return "IEEE 802.11a";
+       case MODE_IEEE80211B:
+               return "IEEE 802.11b";
+       case MODE_IEEE80211G:
+               return "IEEE 802.11g";
+       case MODE_ATHEROS_TURBO:
+               return "Atheros Turbo (5 GHz)";
+       default:
+               return "UNKNOWN";
+       }
+}
+
+static ssize_t modes_read(struct file *file, char __user *userbuf,
+                         size_t count, loff_t *ppos)
+{
+       struct ieee80211_local *local = file->private_data;
+       struct ieee80211_hw_mode *mode;
+       char buf[150], *p = buf;
+
+       /* FIXME: locking! */
+       list_for_each_entry(mode, &local->modes_list, list) {
+               p += scnprintf(p, sizeof(buf)+buf-p,
+                              "%s\n", ieee80211_mode_str(mode->mode));
+       }
+
+       return simple_read_from_buffer(userbuf, count, ppos, buf, p-buf);
+}
+
+static const struct file_operations modes_ops = {
+       .read = modes_read,
+       .open = mac80211_open_file_generic,
+};
+
+#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...)             \
+static ssize_t name## _read(struct file *file, char __user *userbuf,   \
+                           size_t count, loff_t *ppos)                 \
+{                                                                      \
+       struct ieee80211_local *local = file->private_data;             \
+       char buf[buflen];                                               \
+       int res;                                                        \
+                                                                       \
+       res = scnprintf(buf, buflen, fmt "\n", ##value);                \
+       return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
+}                                                                      \
+                                                                       \
+static const struct file_operations name## _ops = {                    \
+       .read = name## _read,                                           \
+       .open = mac80211_open_file_generic,                             \
+};
+
+#define DEBUGFS_ADD(name)                                              \
+       local->debugfs.name = debugfs_create_file(#name, 0444, phyd,    \
+                                                 local, &name## _ops);
+
+#define DEBUGFS_DEL(name)                                              \
+       debugfs_remove(local->debugfs.name);                            \
+       local->debugfs.name = NULL;
+
+
+DEBUGFS_READONLY_FILE(channel, 20, "%d",
+                     local->hw.conf.channel);
+DEBUGFS_READONLY_FILE(frequency, 20, "%d",
+                     local->hw.conf.freq);
+DEBUGFS_READONLY_FILE(radar_detect, 20, "%d",
+                     local->hw.conf.radar_detect);
+DEBUGFS_READONLY_FILE(antenna_sel_tx, 20, "%d",
+                     local->hw.conf.antenna_sel_tx);
+DEBUGFS_READONLY_FILE(antenna_sel_rx, 20, "%d",
+                     local->hw.conf.antenna_sel_rx);
+DEBUGFS_READONLY_FILE(bridge_packets, 20, "%d",
+                     local->bridge_packets);
+DEBUGFS_READONLY_FILE(key_tx_rx_threshold, 20, "%d",
+                     local->key_tx_rx_threshold);
+DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
+                     local->rts_threshold);
+DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d",
+                     local->fragmentation_threshold);
+DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d",
+                     local->short_retry_limit);
+DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d",
+                     local->long_retry_limit);
+DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d",
+                     local->total_ps_buffered);
+DEBUGFS_READONLY_FILE(mode, 20, "%s",
+                     ieee80211_mode_str(local->hw.conf.phymode));
+DEBUGFS_READONLY_FILE(wep_iv, 20, "%#06x",
+                     local->wep_iv & 0xffffff);
+DEBUGFS_READONLY_FILE(tx_power_reduction, 20, "%d.%d dBm",
+                     local->hw.conf.tx_power_reduction / 10,
+                     local->hw.conf.tx_power_reduction & 10);
+DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s",
+                     local->rate_ctrl ? local->rate_ctrl->ops->name : "<unset>");
+
+/* statistics stuff */
+
+static inline int rtnl_lock_local(struct ieee80211_local *local)
+{
+       rtnl_lock();
+       if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) {
+               rtnl_unlock();
+               return -ENODEV;
+       }
+       return 0;
+}
+
+#define DEBUGFS_STATS_FILE(name, buflen, fmt, value...)                        \
+       DEBUGFS_READONLY_FILE(stats_ ##name, buflen, fmt, ##value)
+
+static ssize_t format_devstat_counter(struct ieee80211_local *local,
+       char __user *userbuf,
+       size_t count, loff_t *ppos,
+       int (*printvalue)(struct ieee80211_low_level_stats *stats, char *buf,
+                         int buflen))
+{
+       struct ieee80211_low_level_stats stats;
+       char buf[20];
+       int res;
+
+       if (!local->ops->get_stats)
+               return -EOPNOTSUPP;
+
+       res = rtnl_lock_local(local);
+       if (res)
+               return res;
+
+       res = local->ops->get_stats(local_to_hw(local), &stats);
+       rtnl_unlock();
+       if (!res)
+               res = printvalue(&stats, buf, sizeof(buf));
+       return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+
+#define DEBUGFS_DEVSTATS_FILE(name)                                    \
+static int print_devstats_##name(struct ieee80211_low_level_stats *stats,\
+                                char *buf, int buflen)                 \
+{                                                                      \
+       return scnprintf(buf, buflen, "%u\n", stats->name);             \
+}                                                                      \
+static ssize_t stats_ ##name## _read(struct file *file,                        \
+                                    char __user *userbuf,              \
+                                    size_t count, loff_t *ppos)        \
+{                                                                      \
+       return format_devstat_counter(file->private_data,               \
+                                     userbuf,                          \
+                                     count,                            \
+                                     ppos,                             \
+                                     print_devstats_##name);           \
+}                                                                      \
+                                                                       \
+static const struct file_operations stats_ ##name## _ops = {           \
+       .read = stats_ ##name## _read,                                  \
+       .open = mac80211_open_file_generic,                             \
+};
+
+#define DEBUGFS_STATS_ADD(name)                                                \
+       local->debugfs.stats.name = debugfs_create_file(#name, 0444, statsd,\
+               local, &stats_ ##name## _ops);
+
+#define DEBUGFS_STATS_DEL(name)                                                \
+       debugfs_remove(local->debugfs.stats.name);                      \
+       local->debugfs.stats.name = NULL;
+
+DEBUGFS_STATS_FILE(transmitted_fragment_count, 20, "%u",
+                  local->dot11TransmittedFragmentCount);
+DEBUGFS_STATS_FILE(multicast_transmitted_frame_count, 20, "%u",
+                  local->dot11MulticastTransmittedFrameCount);
+DEBUGFS_STATS_FILE(failed_count, 20, "%u",
+                  local->dot11FailedCount);
+DEBUGFS_STATS_FILE(retry_count, 20, "%u",
+                  local->dot11RetryCount);
+DEBUGFS_STATS_FILE(multiple_retry_count, 20, "%u",
+                  local->dot11MultipleRetryCount);
+DEBUGFS_STATS_FILE(frame_duplicate_count, 20, "%u",
+                  local->dot11FrameDuplicateCount);
+DEBUGFS_STATS_FILE(received_fragment_count, 20, "%u",
+                  local->dot11ReceivedFragmentCount);
+DEBUGFS_STATS_FILE(multicast_received_frame_count, 20, "%u",
+                  local->dot11MulticastReceivedFrameCount);
+DEBUGFS_STATS_FILE(transmitted_frame_count, 20, "%u",
+                  local->dot11TransmittedFrameCount);
+DEBUGFS_STATS_FILE(wep_undecryptable_count, 20, "%u",
+                  local->dot11WEPUndecryptableCount);
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+DEBUGFS_STATS_FILE(tx_handlers_drop, 20, "%u",
+                  local->tx_handlers_drop);
+DEBUGFS_STATS_FILE(tx_handlers_queued, 20, "%u",
+                  local->tx_handlers_queued);
+DEBUGFS_STATS_FILE(tx_handlers_drop_unencrypted, 20, "%u",
+                  local->tx_handlers_drop_unencrypted);
+DEBUGFS_STATS_FILE(tx_handlers_drop_fragment, 20, "%u",
+                  local->tx_handlers_drop_fragment);
+DEBUGFS_STATS_FILE(tx_handlers_drop_wep, 20, "%u",
+                  local->tx_handlers_drop_wep);
+DEBUGFS_STATS_FILE(tx_handlers_drop_not_assoc, 20, "%u",
+                  local->tx_handlers_drop_not_assoc);
+DEBUGFS_STATS_FILE(tx_handlers_drop_unauth_port, 20, "%u",
+                  local->tx_handlers_drop_unauth_port);
+DEBUGFS_STATS_FILE(rx_handlers_drop, 20, "%u",
+                  local->rx_handlers_drop);
+DEBUGFS_STATS_FILE(rx_handlers_queued, 20, "%u",
+                  local->rx_handlers_queued);
+DEBUGFS_STATS_FILE(rx_handlers_drop_nullfunc, 20, "%u",
+                  local->rx_handlers_drop_nullfunc);
+DEBUGFS_STATS_FILE(rx_handlers_drop_defrag, 20, "%u",
+                  local->rx_handlers_drop_defrag);
+DEBUGFS_STATS_FILE(rx_handlers_drop_short, 20, "%u",
+                  local->rx_handlers_drop_short);
+DEBUGFS_STATS_FILE(rx_handlers_drop_passive_scan, 20, "%u",
+                  local->rx_handlers_drop_passive_scan);
+DEBUGFS_STATS_FILE(tx_expand_skb_head, 20, "%u",
+                  local->tx_expand_skb_head);
+DEBUGFS_STATS_FILE(tx_expand_skb_head_cloned, 20, "%u",
+                  local->tx_expand_skb_head_cloned);
+DEBUGFS_STATS_FILE(rx_expand_skb_head, 20, "%u",
+                  local->rx_expand_skb_head);
+DEBUGFS_STATS_FILE(rx_expand_skb_head2, 20, "%u",
+                  local->rx_expand_skb_head2);
+DEBUGFS_STATS_FILE(rx_handlers_fragments, 20, "%u",
+                  local->rx_handlers_fragments);
+DEBUGFS_STATS_FILE(tx_status_drop, 20, "%u",
+                  local->tx_status_drop);
+
+static ssize_t stats_wme_rx_queue_read(struct file *file,
+                                      char __user *userbuf,
+                                      size_t count, loff_t *ppos)
+{
+       struct ieee80211_local *local = file->private_data;
+       char buf[NUM_RX_DATA_QUEUES*15], *p = buf;
+       int i;
+
+       for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+               p += scnprintf(p, sizeof(buf)+buf-p,
+                              "%u\n", local->wme_rx_queue[i]);
+
+       return simple_read_from_buffer(userbuf, count, ppos, buf, p-buf);
+}
+
+static const struct file_operations stats_wme_rx_queue_ops = {
+       .read = stats_wme_rx_queue_read,
+       .open = mac80211_open_file_generic,
+};
+
+static ssize_t stats_wme_tx_queue_read(struct file *file,
+                                      char __user *userbuf,
+                                      size_t count, loff_t *ppos)
+{
+       struct ieee80211_local *local = file->private_data;
+       char buf[NUM_TX_DATA_QUEUES*15], *p = buf;
+       int i;
+
+       for (i = 0; i < NUM_TX_DATA_QUEUES; i++)
+               p += scnprintf(p, sizeof(buf)+buf-p,
+                              "%u\n", local->wme_tx_queue[i]);
+
+       return simple_read_from_buffer(userbuf, count, ppos, buf, p-buf);
+}
+
+static const struct file_operations stats_wme_tx_queue_ops = {
+       .read = stats_wme_tx_queue_read,
+       .open = mac80211_open_file_generic,
+};
+#endif
+
+DEBUGFS_DEVSTATS_FILE(dot11ACKFailureCount);
+DEBUGFS_DEVSTATS_FILE(dot11RTSFailureCount);
+DEBUGFS_DEVSTATS_FILE(dot11FCSErrorCount);
+DEBUGFS_DEVSTATS_FILE(dot11RTSSuccessCount);
+
+
+void debugfs_hw_add(struct ieee80211_local *local)
+{
+       struct dentry *phyd = local->hw.wiphy->debugfsdir;
+       struct dentry *statsd;
+
+       if (!phyd)
+               return;
+
+       local->debugfs.stations = debugfs_create_dir("stations", phyd);
+       local->debugfs.keys = debugfs_create_dir("keys", phyd);
+
+       DEBUGFS_ADD(channel);
+       DEBUGFS_ADD(frequency);
+       DEBUGFS_ADD(radar_detect);
+       DEBUGFS_ADD(antenna_sel_tx);
+       DEBUGFS_ADD(antenna_sel_rx);
+       DEBUGFS_ADD(bridge_packets);
+       DEBUGFS_ADD(key_tx_rx_threshold);
+       DEBUGFS_ADD(rts_threshold);
+       DEBUGFS_ADD(fragmentation_threshold);
+       DEBUGFS_ADD(short_retry_limit);
+       DEBUGFS_ADD(long_retry_limit);
+       DEBUGFS_ADD(total_ps_buffered);
+       DEBUGFS_ADD(mode);
+       DEBUGFS_ADD(wep_iv);
+       DEBUGFS_ADD(tx_power_reduction);
+       DEBUGFS_ADD(modes);
+
+       statsd = debugfs_create_dir("statistics", phyd);
+       local->debugfs.statistics = statsd;
+
+       /* if the dir failed, don't put all the other things into the root! */
+       if (!statsd)
+               return;
+
+       DEBUGFS_STATS_ADD(transmitted_fragment_count);
+       DEBUGFS_STATS_ADD(multicast_transmitted_frame_count);
+       DEBUGFS_STATS_ADD(failed_count);
+       DEBUGFS_STATS_ADD(retry_count);
+       DEBUGFS_STATS_ADD(multiple_retry_count);
+       DEBUGFS_STATS_ADD(frame_duplicate_count);
+       DEBUGFS_STATS_ADD(received_fragment_count);
+       DEBUGFS_STATS_ADD(multicast_received_frame_count);
+       DEBUGFS_STATS_ADD(transmitted_frame_count);
+       DEBUGFS_STATS_ADD(wep_undecryptable_count);
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+       DEBUGFS_STATS_ADD(tx_handlers_drop);
+       DEBUGFS_STATS_ADD(tx_handlers_queued);
+       DEBUGFS_STATS_ADD(tx_handlers_drop_unencrypted);
+       DEBUGFS_STATS_ADD(tx_handlers_drop_fragment);
+       DEBUGFS_STATS_ADD(tx_handlers_drop_wep);
+       DEBUGFS_STATS_ADD(tx_handlers_drop_not_assoc);
+       DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port);
+       DEBUGFS_STATS_ADD(rx_handlers_drop);
+       DEBUGFS_STATS_ADD(rx_handlers_queued);
+       DEBUGFS_STATS_ADD(rx_handlers_drop_nullfunc);
+       DEBUGFS_STATS_ADD(rx_handlers_drop_defrag);
+       DEBUGFS_STATS_ADD(rx_handlers_drop_short);
+       DEBUGFS_STATS_ADD(rx_handlers_drop_passive_scan);
+       DEBUGFS_STATS_ADD(tx_expand_skb_head);
+       DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned);
+       DEBUGFS_STATS_ADD(rx_expand_skb_head);
+       DEBUGFS_STATS_ADD(rx_expand_skb_head2);
+       DEBUGFS_STATS_ADD(rx_handlers_fragments);
+       DEBUGFS_STATS_ADD(tx_status_drop);
+       DEBUGFS_STATS_ADD(wme_tx_queue);
+       DEBUGFS_STATS_ADD(wme_rx_queue);
+#endif
+       DEBUGFS_STATS_ADD(dot11ACKFailureCount);
+       DEBUGFS_STATS_ADD(dot11RTSFailureCount);
+       DEBUGFS_STATS_ADD(dot11FCSErrorCount);
+       DEBUGFS_STATS_ADD(dot11RTSSuccessCount);
+}
+
+void debugfs_hw_del(struct ieee80211_local *local)
+{
+       DEBUGFS_DEL(channel);
+       DEBUGFS_DEL(frequency);
+       DEBUGFS_DEL(radar_detect);
+       DEBUGFS_DEL(antenna_sel_tx);
+       DEBUGFS_DEL(antenna_sel_rx);
+       DEBUGFS_DEL(bridge_packets);
+       DEBUGFS_DEL(key_tx_rx_threshold);
+       DEBUGFS_DEL(rts_threshold);
+       DEBUGFS_DEL(fragmentation_threshold);
+       DEBUGFS_DEL(short_retry_limit);
+       DEBUGFS_DEL(long_retry_limit);
+       DEBUGFS_DEL(total_ps_buffered);
+       DEBUGFS_DEL(mode);
+       DEBUGFS_DEL(wep_iv);
+       DEBUGFS_DEL(tx_power_reduction);
+       DEBUGFS_DEL(modes);
+
+       DEBUGFS_STATS_DEL(transmitted_fragment_count);
+       DEBUGFS_STATS_DEL(multicast_transmitted_frame_count);
+       DEBUGFS_STATS_DEL(failed_count);
+       DEBUGFS_STATS_DEL(retry_count);
+       DEBUGFS_STATS_DEL(multiple_retry_count);
+       DEBUGFS_STATS_DEL(frame_duplicate_count);
+       DEBUGFS_STATS_DEL(received_fragment_count);
+       DEBUGFS_STATS_DEL(multicast_received_frame_count);
+       DEBUGFS_STATS_DEL(transmitted_frame_count);
+       DEBUGFS_STATS_DEL(wep_undecryptable_count);
+       DEBUGFS_STATS_DEL(num_scans);
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+       DEBUGFS_STATS_DEL(tx_handlers_drop);
+       DEBUGFS_STATS_DEL(tx_handlers_queued);
+       DEBUGFS_STATS_DEL(tx_handlers_drop_unencrypted);
+       DEBUGFS_STATS_DEL(tx_handlers_drop_fragment);
+       DEBUGFS_STATS_DEL(tx_handlers_drop_wep);
+       DEBUGFS_STATS_DEL(tx_handlers_drop_not_assoc);
+       DEBUGFS_STATS_DEL(tx_handlers_drop_unauth_port);
+       DEBUGFS_STATS_DEL(rx_handlers_drop);
+       DEBUGFS_STATS_DEL(rx_handlers_queued);
+       DEBUGFS_STATS_DEL(rx_handlers_drop_nullfunc);
+       DEBUGFS_STATS_DEL(rx_handlers_drop_defrag);
+       DEBUGFS_STATS_DEL(rx_handlers_drop_short);
+       DEBUGFS_STATS_DEL(rx_handlers_drop_passive_scan);
+       DEBUGFS_STATS_DEL(tx_expand_skb_head);
+       DEBUGFS_STATS_DEL(tx_expand_skb_head_cloned);
+       DEBUGFS_STATS_DEL(rx_expand_skb_head);
+       DEBUGFS_STATS_DEL(rx_expand_skb_head2);
+       DEBUGFS_STATS_DEL(rx_handlers_fragments);
+       DEBUGFS_STATS_DEL(tx_status_drop);
+       DEBUGFS_STATS_DEL(wme_tx_queue);
+       DEBUGFS_STATS_DEL(wme_rx_queue);
+#endif
+       DEBUGFS_STATS_DEL(dot11ACKFailureCount);
+       DEBUGFS_STATS_DEL(dot11RTSFailureCount);
+       DEBUGFS_STATS_DEL(dot11FCSErrorCount);
+       DEBUGFS_STATS_DEL(dot11RTSSuccessCount);
+
+       debugfs_remove(local->debugfs.statistics);
+       local->debugfs.statistics = NULL;
+       debugfs_remove(local->debugfs.stations);
+       local->debugfs.stations = NULL;
+       debugfs_remove(local->debugfs.keys);
+       local->debugfs.keys = NULL;
+}
diff --git a/net/mac80211/debugfs.h b/net/mac80211/debugfs.h
new file mode 100644 (file)
index 0000000..dd25419
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __MAC80211_DEBUGFS_H
+#define __MAC80211_DEBUGFS_H
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+extern void debugfs_hw_add(struct ieee80211_local *local);
+extern void debugfs_hw_del(struct ieee80211_local *local);
+extern int mac80211_open_file_generic(struct inode *inode, struct file *file);
+#else
+static inline void debugfs_hw_add(struct ieee80211_local *local)
+{
+       return;
+}
+static inline void debugfs_hw_del(struct ieee80211_local *local) {}
+#endif
+
+#endif /* __MAC80211_DEBUGFS_H */
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
new file mode 100644 (file)
index 0000000..7d56dc9
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2003-2005 Devicescape Software, Inc.
+ * Copyright (c) 2006  Jiri Benc <jbenc@suse.cz>
+ * Copyright 2007      Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kobject.h>
+#include "ieee80211_i.h"
+#include "ieee80211_key.h"
+#include "debugfs.h"
+#include "debugfs_key.h"
+
+#define KEY_READ(name, buflen, format_string)                          \
+static ssize_t key_##name##_read(struct file *file,                    \
+                                char __user *userbuf,                  \
+                                size_t count, loff_t *ppos)            \
+{                                                                      \
+       char buf[buflen];                                               \
+       struct ieee80211_key *key = file->private_data;                 \
+       int res = scnprintf(buf, buflen, format_string, key->name);     \
+       return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
+}
+#define KEY_READ_D(name) KEY_READ(name, 20, "%d\n")
+
+#define KEY_OPS(name)                                                  \
+static const struct file_operations key_ ##name## _ops = {             \
+       .read = key_##name##_read,                                      \
+       .open = mac80211_open_file_generic,                             \
+}
+
+#define KEY_FILE(name, format)                                         \
+                KEY_READ_##format(name)                                \
+                KEY_OPS(name)
+
+KEY_FILE(keylen, D);
+KEY_FILE(force_sw_encrypt, D);
+KEY_FILE(keyidx, D);
+KEY_FILE(hw_key_idx, D);
+KEY_FILE(tx_rx_count, D);
+
+static ssize_t key_algorithm_read(struct file *file,
+                                 char __user *userbuf,
+                                 size_t count, loff_t *ppos)
+{
+       char *alg;
+       struct ieee80211_key *key = file->private_data;
+
+       switch (key->alg) {
+       case ALG_WEP:
+               alg = "WEP\n";
+               break;
+       case ALG_TKIP:
+               alg = "TKIP\n";
+               break;
+       case ALG_CCMP:
+               alg = "CCMP\n";
+               break;
+       default:
+               return 0;
+       }
+       return simple_read_from_buffer(userbuf, count, ppos, alg, strlen(alg));
+}
+KEY_OPS(algorithm);
+
+static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
+                               size_t count, loff_t *ppos)
+{
+       const u8 *tpn;
+       char buf[20];
+       int len;
+       struct ieee80211_key *key = file->private_data;
+
+       switch (key->alg) {
+       case ALG_WEP:
+               len = scnprintf(buf, sizeof(buf), "\n");
+       case ALG_TKIP:
+               len = scnprintf(buf, sizeof(buf), "%08x %04x\n",
+                               key->u.tkip.iv32,
+                               key->u.tkip.iv16);
+       case ALG_CCMP:
+               tpn = key->u.ccmp.tx_pn;
+               len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
+                               tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]);
+       default:
+               return 0;
+       }
+       return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+KEY_OPS(tx_spec);
+
+static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
+                               size_t count, loff_t *ppos)
+{
+       struct ieee80211_key *key = file->private_data;
+       char buf[14*NUM_RX_DATA_QUEUES+1], *p = buf;
+       int i, len;
+       const u8 *rpn;
+
+       switch (key->alg) {
+       case ALG_WEP:
+               len = scnprintf(buf, sizeof(buf), "\n");
+       case ALG_TKIP:
+               for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+                       p += scnprintf(p, sizeof(buf)+buf-p,
+                                      "%08x %04x\n",
+                                      key->u.tkip.iv32_rx[i],
+                                      key->u.tkip.iv16_rx[i]);
+               len = p - buf;
+       case ALG_CCMP:
+               for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
+                       rpn = key->u.ccmp.rx_pn[i];
+                       p += scnprintf(p, sizeof(buf)+buf-p,
+                                      "%02x%02x%02x%02x%02x%02x\n",
+                                      rpn[0], rpn[1], rpn[2],
+                                      rpn[3], rpn[4], rpn[5]);
+               }
+               len = p - buf;
+       default:
+               return 0;
+       }
+       return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+KEY_OPS(rx_spec);
+
+static ssize_t key_replays_read(struct file *file, char __user *userbuf,
+                               size_t count, loff_t *ppos)
+{
+       struct ieee80211_key *key = file->private_data;
+       char buf[20];
+       int len;
+
+       if (key->alg != ALG_CCMP)
+               return 0;
+       len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays);
+       return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+KEY_OPS(replays);
+
+static ssize_t key_key_read(struct file *file, char __user *userbuf,
+                           size_t count, loff_t *ppos)
+{
+       struct ieee80211_key *key = file->private_data;
+       int i, res, bufsize = 2*key->keylen+2;
+       char *buf = kmalloc(bufsize, GFP_KERNEL);
+       char *p = buf;
+
+       for (i = 0; i < key->keylen; i++)
+               p += scnprintf(p, bufsize+buf-p, "%02x", key->key[i]);
+       p += scnprintf(p, bufsize+buf-p, "\n");
+       res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+       kfree(buf);
+       return res;
+}
+KEY_OPS(key);
+
+#define DEBUGFS_ADD(name) \
+       key->debugfs.name = debugfs_create_file(#name, 0400,\
+                               key->debugfs.dir, key, &key_##name##_ops);
+
+void ieee80211_debugfs_key_add(struct ieee80211_local *local,
+                              struct ieee80211_key *key)
+{
+       char buf[20];
+
+       if (!local->debugfs.keys)
+               return;
+
+       sprintf(buf, "%d", key->keyidx);
+       key->debugfs.dir = debugfs_create_dir(buf,
+                                       local->debugfs.keys);
+
+       if (!key->debugfs.dir)
+               return;
+
+       DEBUGFS_ADD(keylen);
+       DEBUGFS_ADD(force_sw_encrypt);
+       DEBUGFS_ADD(keyidx);
+       DEBUGFS_ADD(hw_key_idx);
+       DEBUGFS_ADD(tx_rx_count);
+       DEBUGFS_ADD(algorithm);
+       DEBUGFS_ADD(tx_spec);
+       DEBUGFS_ADD(rx_spec);
+       DEBUGFS_ADD(replays);
+       DEBUGFS_ADD(key);
+};
+
+#define DEBUGFS_DEL(name) \
+       debugfs_remove(key->debugfs.name); key->debugfs.name = NULL;
+
+void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
+{
+       if (!key)
+               return;
+
+       DEBUGFS_DEL(keylen);
+       DEBUGFS_DEL(force_sw_encrypt);
+       DEBUGFS_DEL(keyidx);
+       DEBUGFS_DEL(hw_key_idx);
+       DEBUGFS_DEL(tx_rx_count);
+       DEBUGFS_DEL(algorithm);
+       DEBUGFS_DEL(tx_spec);
+       DEBUGFS_DEL(rx_spec);
+       DEBUGFS_DEL(replays);
+       DEBUGFS_DEL(key);
+
+       debugfs_remove(key->debugfs.stalink);
+       key->debugfs.stalink = NULL;
+       debugfs_remove(key->debugfs.dir);
+       key->debugfs.dir = NULL;
+}
+void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata)
+{
+       char buf[50];
+
+       if (!sdata->debugfsdir)
+               return;
+
+       sprintf(buf, "../keys/%d", sdata->default_key->keyidx);
+       sdata->debugfs.default_key =
+               debugfs_create_symlink("default_key", sdata->debugfsdir, buf);
+}
+void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata)
+{
+       if (!sdata)
+               return;
+
+       debugfs_remove(sdata->debugfs.default_key);
+       sdata->debugfs.default_key = NULL;
+}
+void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
+                                   struct sta_info *sta)
+{
+       char buf[50];
+
+       if (!key->debugfs.dir)
+               return;
+
+       sprintf(buf, "../sta/" MAC_FMT, MAC_ARG(sta->addr));
+       key->debugfs.stalink =
+               debugfs_create_symlink("station", key->debugfs.dir, buf);
+}
+
+void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
+                                  struct sta_info *sta)
+{
+       debugfs_remove(key->debugfs.stalink);
+       key->debugfs.stalink = NULL;
+}
diff --git a/net/mac80211/debugfs_key.h b/net/mac80211/debugfs_key.h
new file mode 100644 (file)
index 0000000..aecfce3
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef __MAC80211_DEBUGFS_KEY_H
+#define __MAC80211_DEBUGFS_KEY_H
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+void ieee80211_debugfs_key_add(struct ieee80211_local *local,
+                              struct ieee80211_key *key);
+void ieee80211_debugfs_key_remove(struct ieee80211_key *key);
+void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata);
+void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata);
+void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
+                                   struct sta_info *sta);
+void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
+                                  struct sta_info *sta);
+#else
+static inline void ieee80211_debugfs_key_add(struct ieee80211_local *local,
+                                            struct ieee80211_key *key)
+{}
+static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
+{}
+static inline void ieee80211_debugfs_key_add_default(
+       struct ieee80211_sub_if_data *sdata)
+{}
+static inline void ieee80211_debugfs_key_remove_default(
+       struct ieee80211_sub_if_data *sdata)
+{}
+static inline void ieee80211_debugfs_key_sta_link(
+       struct ieee80211_key *key, struct sta_info *sta)
+{}
+static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
+                                                struct sta_info *sta)
+{}
+#endif
+
+#endif /* __MAC80211_DEBUGFS_KEY_H */
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
new file mode 100644 (file)
index 0000000..9e39646
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 2006  Jiri Benc <jbenc@suse.cz>
+ * Copyright 2007      Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/if.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/notifier.h>
+#include <net/mac80211.h>
+#include <net/cfg80211.h>
+#include "ieee80211_i.h"
+#include "ieee80211_rate.h"
+#include "debugfs.h"
+#include "debugfs_netdev.h"
+
+static ssize_t ieee80211_if_read(
+       struct ieee80211_sub_if_data *sdata,
+       char __user *userbuf,
+       size_t count, loff_t *ppos,
+       ssize_t (*format)(const struct ieee80211_sub_if_data *, char *, int))
+{
+       char buf[70];
+       ssize_t ret = -EINVAL;
+
+       read_lock(&dev_base_lock);
+       if (sdata->dev->reg_state == NETREG_REGISTERED) {
+               ret = (*format)(sdata, buf, sizeof(buf));
+               ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
+       }
+       read_unlock(&dev_base_lock);
+       return ret;
+}
+
+#define IEEE80211_IF_FMT(name, field, format_string)                   \
+static ssize_t ieee80211_if_fmt_##name(                                        \
+       const struct ieee80211_sub_if_data *sdata, char *buf,           \
+       int buflen)                                                     \
+{                                                                      \
+       return scnprintf(buf, buflen, format_string, sdata->field);     \
+}
+#define IEEE80211_IF_FMT_DEC(name, field)                              \
+               IEEE80211_IF_FMT(name, field, "%d\n")
+#define IEEE80211_IF_FMT_HEX(name, field)                              \
+               IEEE80211_IF_FMT(name, field, "%#x\n")
+#define IEEE80211_IF_FMT_SIZE(name, field)                             \
+               IEEE80211_IF_FMT(name, field, "%zd\n")
+
+#define IEEE80211_IF_FMT_ATOMIC(name, field)                           \
+static ssize_t ieee80211_if_fmt_##name(                                        \
+       const struct ieee80211_sub_if_data *sdata,                      \
+       char *buf, int buflen)                                          \
+{                                                                      \
+       return scnprintf(buf, buflen, "%d\n", atomic_read(&sdata->field));\
+}
+
+#define IEEE80211_IF_FMT_MAC(name, field)                              \
+static ssize_t ieee80211_if_fmt_##name(                                        \
+       const struct ieee80211_sub_if_data *sdata, char *buf,           \
+       int buflen)                                                     \
+{                                                                      \
+       return scnprintf(buf, buflen, MAC_FMT "\n", MAC_ARG(sdata->field));\
+}
+
+#define __IEEE80211_IF_FILE(name)                                      \
+static ssize_t ieee80211_if_read_##name(struct file *file,             \
+                                       char __user *userbuf,           \
+                                       size_t count, loff_t *ppos)     \
+{                                                                      \
+       return ieee80211_if_read(file->private_data,                    \
+                                userbuf, count, ppos,                  \
+                                ieee80211_if_fmt_##name);              \
+}                                                                      \
+static const struct file_operations name##_ops = {                     \
+       .read = ieee80211_if_read_##name,                               \
+       .open = mac80211_open_file_generic,                             \
+}
+
+#define IEEE80211_IF_FILE(name, field, format)                         \
+               IEEE80211_IF_FMT_##format(name, field)                  \
+               __IEEE80211_IF_FILE(name)
+
+/* common attributes */
+IEEE80211_IF_FILE(channel_use, channel_use, DEC);
+IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
+IEEE80211_IF_FILE(eapol, eapol, DEC);
+IEEE80211_IF_FILE(ieee8021_x, ieee802_1x, DEC);
+
+/* STA/IBSS attributes */
+IEEE80211_IF_FILE(state, u.sta.state, DEC);
+IEEE80211_IF_FILE(bssid, u.sta.bssid, MAC);
+IEEE80211_IF_FILE(prev_bssid, u.sta.prev_bssid, MAC);
+IEEE80211_IF_FILE(ssid_len, u.sta.ssid_len, SIZE);
+IEEE80211_IF_FILE(aid, u.sta.aid, DEC);
+IEEE80211_IF_FILE(ap_capab, u.sta.ap_capab, HEX);
+IEEE80211_IF_FILE(capab, u.sta.capab, HEX);
+IEEE80211_IF_FILE(extra_ie_len, u.sta.extra_ie_len, SIZE);
+IEEE80211_IF_FILE(auth_tries, u.sta.auth_tries, DEC);
+IEEE80211_IF_FILE(assoc_tries, u.sta.assoc_tries, DEC);
+IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX);
+IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC);
+IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC);
+
+static ssize_t ieee80211_if_fmt_flags(
+       const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+{
+       return scnprintf(buf, buflen, "%s%s%s%s%s%s%s\n",
+                        sdata->u.sta.ssid_set ? "SSID\n" : "",
+                        sdata->u.sta.bssid_set ? "BSSID\n" : "",
+                        sdata->u.sta.prev_bssid_set ? "prev BSSID\n" : "",
+                        sdata->u.sta.authenticated ? "AUTH\n" : "",
+                        sdata->u.sta.associated ? "ASSOC\n" : "",
+                        sdata->u.sta.probereq_poll ? "PROBEREQ POLL\n" : "",
+                        sdata->u.sta.use_protection ? "CTS prot\n" : "");
+}
+__IEEE80211_IF_FILE(flags);
+
+/* AP attributes */
+IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
+IEEE80211_IF_FILE(dtim_period, u.ap.dtim_period, DEC);
+IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC);
+IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC);
+IEEE80211_IF_FILE(force_unicast_rateidx, u.ap.force_unicast_rateidx, DEC);
+IEEE80211_IF_FILE(max_ratectrl_rateidx, u.ap.max_ratectrl_rateidx, DEC);
+
+static ssize_t ieee80211_if_fmt_num_buffered_multicast(
+       const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+{
+       return scnprintf(buf, buflen, "%u\n",
+                        skb_queue_len(&sdata->u.ap.ps_bc_buf));
+}
+__IEEE80211_IF_FILE(num_buffered_multicast);
+
+static ssize_t ieee80211_if_fmt_beacon_head_len(
+       const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+{
+       if (sdata->u.ap.beacon_head)
+               return scnprintf(buf, buflen, "%d\n",
+                                sdata->u.ap.beacon_head_len);
+       return scnprintf(buf, buflen, "\n");
+}
+__IEEE80211_IF_FILE(beacon_head_len);
+
+static ssize_t ieee80211_if_fmt_beacon_tail_len(
+       const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+{
+       if (sdata->u.ap.beacon_tail)
+               return scnprintf(buf, buflen, "%d\n",
+                                sdata->u.ap.beacon_tail_len);
+       return scnprintf(buf, buflen, "\n");
+}
+__IEEE80211_IF_FILE(beacon_tail_len);
+
+/* WDS attributes */
+IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
+
+/* VLAN attributes */
+IEEE80211_IF_FILE(vlan_id, u.vlan.id, DEC);
+
+/* MONITOR attributes */
+static ssize_t ieee80211_if_fmt_mode(
+       const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+{
+       struct ieee80211_local *local = sdata->local;
+
+       return scnprintf(buf, buflen, "%s\n",
+                        ((local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) ||
+                         local->open_count == local->monitors) ?
+                        "hard" : "soft");
+}
+__IEEE80211_IF_FILE(mode);
+
+
+#define DEBUGFS_ADD(name, type)\
+       sdata->debugfs.type.name = debugfs_create_file(#name, 0444,\
+               sdata->debugfsdir, sdata, &name##_ops);
+
+static void add_sta_files(struct ieee80211_sub_if_data *sdata)
+{
+       DEBUGFS_ADD(channel_use, sta);
+       DEBUGFS_ADD(drop_unencrypted, sta);
+       DEBUGFS_ADD(eapol, sta);
+       DEBUGFS_ADD(ieee8021_x, sta);
+       DEBUGFS_ADD(state, sta);
+       DEBUGFS_ADD(bssid, sta);
+       DEBUGFS_ADD(prev_bssid, sta);
+       DEBUGFS_ADD(ssid_len, sta);
+       DEBUGFS_ADD(aid, sta);
+       DEBUGFS_ADD(ap_capab, sta);
+       DEBUGFS_ADD(capab, sta);
+       DEBUGFS_ADD(extra_ie_len, sta);
+       DEBUGFS_ADD(auth_tries, sta);
+       DEBUGFS_ADD(assoc_tries, sta);
+       DEBUGFS_ADD(auth_algs, sta);
+       DEBUGFS_ADD(auth_alg, sta);
+       DEBUGFS_ADD(auth_transaction, sta);
+       DEBUGFS_ADD(flags, sta);
+}
+
+static void add_ap_files(struct ieee80211_sub_if_data *sdata)
+{
+       DEBUGFS_ADD(channel_use, ap);
+       DEBUGFS_ADD(drop_unencrypted, ap);
+       DEBUGFS_ADD(eapol, ap);
+       DEBUGFS_ADD(ieee8021_x, ap);
+       DEBUGFS_ADD(num_sta_ps, ap);
+       DEBUGFS_ADD(dtim_period, ap);
+       DEBUGFS_ADD(dtim_count, ap);
+       DEBUGFS_ADD(num_beacons, ap);
+       DEBUGFS_ADD(force_unicast_rateidx, ap);
+       DEBUGFS_ADD(max_ratectrl_rateidx, ap);
+       DEBUGFS_ADD(num_buffered_multicast, ap);
+       DEBUGFS_ADD(beacon_head_len, ap);
+       DEBUGFS_ADD(beacon_tail_len, ap);
+}
+
+static void add_wds_files(struct ieee80211_sub_if_data *sdata)
+{
+       DEBUGFS_ADD(channel_use, wds);
+       DEBUGFS_ADD(drop_unencrypted, wds);
+       DEBUGFS_ADD(eapol, wds);
+       DEBUGFS_ADD(ieee8021_x, wds);
+       DEBUGFS_ADD(peer, wds);
+}
+
+static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
+{
+       DEBUGFS_ADD(channel_use, vlan);
+       DEBUGFS_ADD(drop_unencrypted, vlan);
+       DEBUGFS_ADD(eapol, vlan);
+       DEBUGFS_ADD(ieee8021_x, vlan);
+       DEBUGFS_ADD(vlan_id, vlan);
+}
+
+static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
+{
+       DEBUGFS_ADD(mode, monitor);
+}
+
+static void add_files(struct ieee80211_sub_if_data *sdata)
+{
+       if (!sdata->debugfsdir)
+               return;
+
+       switch (sdata->type) {
+       case IEEE80211_IF_TYPE_STA:
+       case IEEE80211_IF_TYPE_IBSS:
+               add_sta_files(sdata);
+               break;
+       case IEEE80211_IF_TYPE_AP:
+               add_ap_files(sdata);
+               break;
+       case IEEE80211_IF_TYPE_WDS:
+               add_wds_files(sdata);
+               break;
+       case IEEE80211_IF_TYPE_MNTR:
+               add_monitor_files(sdata);
+               break;
+       case IEEE80211_IF_TYPE_VLAN:
+               add_vlan_files(sdata);
+               break;
+       default:
+               break;
+       }
+}
+
+#define DEBUGFS_DEL(name, type)\
+       debugfs_remove(sdata->debugfs.type.name);\
+       sdata->debugfs.type.name = NULL;
+
+static void del_sta_files(struct ieee80211_sub_if_data *sdata)
+{
+       DEBUGFS_DEL(channel_use, sta);
+       DEBUGFS_DEL(drop_unencrypted, sta);
+       DEBUGFS_DEL(eapol, sta);
+       DEBUGFS_DEL(ieee8021_x, sta);
+       DEBUGFS_DEL(state, sta);
+       DEBUGFS_DEL(bssid, sta);
+       DEBUGFS_DEL(prev_bssid, sta);
+       DEBUGFS_DEL(ssid_len, sta);
+       DEBUGFS_DEL(aid, sta);
+       DEBUGFS_DEL(ap_capab, sta);
+       DEBUGFS_DEL(capab, sta);
+       DEBUGFS_DEL(extra_ie_len, sta);
+       DEBUGFS_DEL(auth_tries, sta);
+       DEBUGFS_DEL(assoc_tries, sta);
+       DEBUGFS_DEL(auth_algs, sta);
+       DEBUGFS_DEL(auth_alg, sta);
+       DEBUGFS_DEL(auth_transaction, sta);
+       DEBUGFS_DEL(flags, sta);
+}
+
+static void del_ap_files(struct ieee80211_sub_if_data *sdata)
+{
+       DEBUGFS_DEL(channel_use, ap);
+       DEBUGFS_DEL(drop_unencrypted, ap);
+       DEBUGFS_DEL(eapol, ap);
+       DEBUGFS_DEL(ieee8021_x, ap);
+       DEBUGFS_DEL(num_sta_ps, ap);
+       DEBUGFS_DEL(dtim_period, ap);
+       DEBUGFS_DEL(dtim_count, ap);
+       DEBUGFS_DEL(num_beacons, ap);
+       DEBUGFS_DEL(force_unicast_rateidx, ap);
+       DEBUGFS_DEL(max_ratectrl_rateidx, ap);
+       DEBUGFS_DEL(num_buffered_multicast, ap);
+       DEBUGFS_DEL(beacon_head_len, ap);
+       DEBUGFS_DEL(beacon_tail_len, ap);
+}
+
+static void del_wds_files(struct ieee80211_sub_if_data *sdata)
+{
+       DEBUGFS_DEL(channel_use, wds);
+       DEBUGFS_DEL(drop_unencrypted, wds);
+       DEBUGFS_DEL(eapol, wds);
+       DEBUGFS_DEL(ieee8021_x, wds);
+       DEBUGFS_DEL(peer, wds);
+}
+
+static void del_vlan_files(struct ieee80211_sub_if_data *sdata)
+{
+       DEBUGFS_DEL(channel_use, vlan);
+       DEBUGFS_DEL(drop_unencrypted, vlan);
+       DEBUGFS_DEL(eapol, vlan);
+       DEBUGFS_DEL(ieee8021_x, vlan);
+       DEBUGFS_DEL(vlan_id, vlan);
+}
+
+static void del_monitor_files(struct ieee80211_sub_if_data *sdata)
+{
+       DEBUGFS_DEL(mode, monitor);
+}
+
+static void del_files(struct ieee80211_sub_if_data *sdata, int type)
+{
+       if (!sdata->debugfsdir)
+               return;
+
+       switch (type) {
+       case IEEE80211_IF_TYPE_STA:
+       case IEEE80211_IF_TYPE_IBSS:
+               del_sta_files(sdata);
+               break;
+       case IEEE80211_IF_TYPE_AP:
+               del_ap_files(sdata);
+               break;
+       case IEEE80211_IF_TYPE_WDS:
+               del_wds_files(sdata);
+               break;
+       case IEEE80211_IF_TYPE_MNTR:
+               del_monitor_files(sdata);
+               break;
+       case IEEE80211_IF_TYPE_VLAN:
+               del_vlan_files(sdata);
+               break;
+       default:
+               break;
+       }
+}
+
+static int notif_registered;
+
+void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
+{
+       char buf[10+IFNAMSIZ];
+
+       if (!notif_registered)
+               return;
+
+       sprintf(buf, "netdev:%s", sdata->dev->name);
+       sdata->debugfsdir = debugfs_create_dir(buf,
+               sdata->local->hw.wiphy->debugfsdir);
+}
+
+void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
+{
+       del_files(sdata, sdata->type);
+       debugfs_remove(sdata->debugfsdir);
+       sdata->debugfsdir = NULL;
+}
+
+void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata,
+                                     int oldtype)
+{
+       del_files(sdata, oldtype);
+       add_files(sdata);
+}
+
+static int netdev_notify(struct notifier_block * nb,
+                        unsigned long state,
+                        void *ndev)
+{
+       struct net_device *dev = ndev;
+       char buf[10+IFNAMSIZ];
+
+       if (state != NETDEV_CHANGENAME)
+               return 0;
+
+       if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
+               return 0;
+
+       if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
+               return 0;
+
+       /* TODO
+       sprintf(buf, "netdev:%s", dev->name);
+       debugfs_rename(IEEE80211_DEV_TO_SUB_IF(dev)->debugfsdir, buf);
+       */
+
+       return 0;
+}
+
+static struct notifier_block mac80211_debugfs_netdev_notifier = {
+       .notifier_call = netdev_notify,
+};
+
+void ieee80211_debugfs_netdev_init(void)
+{
+       int err;
+
+       err = register_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
+       if (err) {
+               printk(KERN_ERR
+                      "mac80211: failed to install netdev notifier,"
+                      " disabling per-netdev debugfs!\n");
+       } else
+               notif_registered = 1;
+}
+
+void ieee80211_debugfs_netdev_exit(void)
+{
+       unregister_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
+       notif_registered = 0;
+}
diff --git a/net/mac80211/debugfs_netdev.h b/net/mac80211/debugfs_netdev.h
new file mode 100644 (file)
index 0000000..a690071
--- /dev/null
@@ -0,0 +1,30 @@
+/* routines exported for debugfs handling */
+
+#ifndef __IEEE80211_DEBUGFS_NETDEV_H
+#define __IEEE80211_DEBUGFS_NETDEV_H
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata);
+void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata);
+void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata,
+                                    int oldtype);
+void ieee80211_debugfs_netdev_init(void);
+void ieee80211_debugfs_netdev_exit(void);
+#else
+static inline void ieee80211_debugfs_add_netdev(
+       struct ieee80211_sub_if_data *sdata)
+{}
+static inline void ieee80211_debugfs_remove_netdev(
+       struct ieee80211_sub_if_data *sdata)
+{}
+static inline void ieee80211_debugfs_change_if_type(
+       struct ieee80211_sub_if_data *sdata, int oldtype)
+{}
+static inline void ieee80211_debugfs_netdev_init(void)
+{}
+
+static inline void ieee80211_debugfs_netdev_exit(void)
+{}
+#endif
+
+#endif /* __IEEE80211_DEBUGFS_NETDEV_H */
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
new file mode 100644 (file)
index 0000000..d41e696
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2003-2005 Devicescape Software, Inc.
+ * Copyright (c) 2006  Jiri Benc <jbenc@suse.cz>
+ * Copyright 2007      Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/ieee80211.h>
+#include "ieee80211_i.h"
+#include "debugfs.h"
+#include "debugfs_sta.h"
+#include "sta_info.h"
+
+/* sta attributtes */
+
+#define STA_READ(name, buflen, field, format_string)                   \
+static ssize_t sta_ ##name## _read(struct file *file,                  \
+                                  char __user *userbuf,                \
+                                  size_t count, loff_t *ppos)          \
+{                                                                      \
+       int res;                                                        \
+       struct sta_info *sta = file->private_data;                      \
+       char buf[buflen];                                               \
+       res = scnprintf(buf, buflen, format_string, sta->field);        \
+       return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
+}
+#define STA_READ_D(name, field) STA_READ(name, 20, field, "%d\n")
+#define STA_READ_U(name, field) STA_READ(name, 20, field, "%u\n")
+#define STA_READ_LU(name, field) STA_READ(name, 20, field, "%lu\n")
+#define STA_READ_S(name, field) STA_READ(name, 20, field, "%s\n")
+
+#define STA_READ_RATE(name, field)                                     \
+static ssize_t sta_##name##_read(struct file *file,                    \
+                                char __user *userbuf,                  \
+                                size_t count, loff_t *ppos)            \
+{                                                                      \
+       struct sta_info *sta = file->private_data;                      \
+       struct ieee80211_local *local = wdev_priv(sta->dev->ieee80211_ptr);\
+       struct ieee80211_hw_mode *mode = local->oper_hw_mode;           \
+       char buf[20];                                                   \
+       int res = scnprintf(buf, sizeof(buf), "%d\n",                   \
+                           (sta->field >= 0 &&                         \
+                           sta->field < mode->num_rates) ?             \
+                           mode->rates[sta->field].rate : -1);         \
+       return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
+}
+
+#define STA_OPS(name)                                                  \
+static const struct file_operations sta_ ##name## _ops = {             \
+       .read = sta_##name##_read,                                      \
+       .open = mac80211_open_file_generic,                             \
+}
+
+#define STA_FILE(name, field, format)                                  \
+               STA_READ_##format(name, field)                          \
+               STA_OPS(name)
+
+STA_FILE(aid, aid, D);
+STA_FILE(key_idx_compression, key_idx_compression, D);
+STA_FILE(dev, dev->name, S);
+STA_FILE(vlan_id, vlan_id, D);
+STA_FILE(rx_packets, rx_packets, LU);
+STA_FILE(tx_packets, tx_packets, LU);
+STA_FILE(rx_bytes, rx_bytes, LU);
+STA_FILE(tx_bytes, tx_bytes, LU);
+STA_FILE(rx_duplicates, num_duplicates, LU);
+STA_FILE(rx_fragments, rx_fragments, LU);
+STA_FILE(rx_dropped, rx_dropped, LU);
+STA_FILE(tx_fragments, tx_fragments, LU);
+STA_FILE(tx_filtered, tx_filtered_count, LU);
+STA_FILE(txrate, txrate, RATE);
+STA_FILE(last_txrate, last_txrate, RATE);
+STA_FILE(tx_retry_failed, tx_retry_failed, LU);
+STA_FILE(tx_retry_count, tx_retry_count, LU);
+STA_FILE(last_rssi, last_rssi, D);
+STA_FILE(last_signal, last_signal, D);
+STA_FILE(last_noise, last_noise, D);
+STA_FILE(channel_use, channel_use, D);
+STA_FILE(wep_weak_iv_count, wep_weak_iv_count, D);
+
+static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
+                             size_t count, loff_t *ppos)
+{
+       char buf[100];
+       struct sta_info *sta = file->private_data;
+       int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s",
+               sta->flags & WLAN_STA_AUTH ? "AUTH\n" : "",
+               sta->flags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
+               sta->flags & WLAN_STA_PS ? "PS\n" : "",
+               sta->flags & WLAN_STA_TIM ? "TIM\n" : "",
+               sta->flags & WLAN_STA_PERM ? "PERM\n" : "",
+               sta->flags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
+               sta->flags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "",
+               sta->flags & WLAN_STA_WME ? "WME\n" : "",
+               sta->flags & WLAN_STA_WDS ? "WDS\n" : "");
+       return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+STA_OPS(flags);
+
+static ssize_t sta_num_ps_buf_frames_read(struct file *file,
+                                         char __user *userbuf,
+                                         size_t count, loff_t *ppos)
+{
+       char buf[20];
+       struct sta_info *sta = file->private_data;
+       int res = scnprintf(buf, sizeof(buf), "%u\n",
+                           skb_queue_len(&sta->ps_tx_buf));
+       return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+STA_OPS(num_ps_buf_frames);
+
+static ssize_t sta_last_ack_rssi_read(struct file *file, char __user *userbuf,
+                                     size_t count, loff_t *ppos)
+{
+       char buf[100];
+       struct sta_info *sta = file->private_data;
+       int res = scnprintf(buf, sizeof(buf), "%d %d %d\n",
+                           sta->last_ack_rssi[0],
+                           sta->last_ack_rssi[1],
+                           sta->last_ack_rssi[2]);
+       return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+STA_OPS(last_ack_rssi);
+
+static ssize_t sta_last_ack_ms_read(struct file *file, char __user *userbuf,
+                                   size_t count, loff_t *ppos)
+{
+       char buf[20];
+       struct sta_info *sta = file->private_data;
+       int res = scnprintf(buf, sizeof(buf), "%d\n",
+                           sta->last_ack ?
+                           jiffies_to_msecs(jiffies - sta->last_ack) : -1);
+       return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+STA_OPS(last_ack_ms);
+
+static ssize_t sta_inactive_ms_read(struct file *file, char __user *userbuf,
+                                   size_t count, loff_t *ppos)
+{
+       char buf[20];
+       struct sta_info *sta = file->private_data;
+       int res = scnprintf(buf, sizeof(buf), "%d\n",
+                           jiffies_to_msecs(jiffies - sta->last_rx));
+       return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+STA_OPS(inactive_ms);
+
+static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf,
+                                     size_t count, loff_t *ppos)
+{
+       char buf[15*NUM_RX_DATA_QUEUES], *p = buf;
+       int i;
+       struct sta_info *sta = file->private_data;
+       for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+               p += scnprintf(p, sizeof(buf)+buf-p, "%x ",
+                              sta->last_seq_ctrl[i]);
+       p += scnprintf(p, sizeof(buf)+buf-p, "\n");
+       return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+}
+STA_OPS(last_seq_ctrl);
+
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+static ssize_t sta_wme_rx_queue_read(struct file *file, char __user *userbuf,
+                                    size_t count, loff_t *ppos)
+{
+       char buf[15*NUM_RX_DATA_QUEUES], *p = buf;
+       int i;
+       struct sta_info *sta = file->private_data;
+       for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+               p += scnprintf(p, sizeof(buf)+buf-p, "%u ",
+                              sta->wme_rx_queue[i]);
+       p += scnprintf(p, sizeof(buf)+buf-p, "\n");
+       return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+}
+STA_OPS(wme_rx_queue);
+
+static ssize_t sta_wme_tx_queue_read(struct file *file, char __user *userbuf,
+                                    size_t count, loff_t *ppos)
+{
+       char buf[15*NUM_TX_DATA_QUEUES], *p = buf;
+       int i;
+       struct sta_info *sta = file->private_data;
+       for (i = 0; i < NUM_TX_DATA_QUEUES; i++)
+               p += scnprintf(p, sizeof(buf)+buf-p, "%u ",
+                              sta->wme_tx_queue[i]);
+       p += scnprintf(p, sizeof(buf)+buf-p, "\n");
+       return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+}
+STA_OPS(wme_tx_queue);
+#endif
+
+#define DEBUGFS_ADD(name) \
+       sta->debugfs.name = debugfs_create_file(#name, 0444, \
+               sta->debugfs.dir, sta, &sta_ ##name## _ops);
+
+#define DEBUGFS_DEL(name) \
+       debugfs_remove(sta->debugfs.name);\
+       sta->debugfs.name = NULL;
+
+
+void ieee80211_sta_debugfs_add(struct sta_info *sta)
+{
+       char buf[3*6];
+       struct dentry *stations_dir = sta->local->debugfs.stations;
+
+       if (!stations_dir)
+               return;
+
+       sprintf(buf, MAC_FMT, MAC_ARG(sta->addr));
+
+       sta->debugfs.dir = debugfs_create_dir(buf, stations_dir);
+       if (!sta->debugfs.dir)
+               return;
+
+       DEBUGFS_ADD(flags);
+       DEBUGFS_ADD(num_ps_buf_frames);
+       DEBUGFS_ADD(last_ack_rssi);
+       DEBUGFS_ADD(last_ack_ms);
+       DEBUGFS_ADD(inactive_ms);
+       DEBUGFS_ADD(last_seq_ctrl);
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+       DEBUGFS_ADD(wme_rx_queue);
+       DEBUGFS_ADD(wme_tx_queue);
+#endif
+}
+
+void ieee80211_sta_debugfs_remove(struct sta_info *sta)
+{
+       DEBUGFS_DEL(flags);
+       DEBUGFS_DEL(num_ps_buf_frames);
+       DEBUGFS_DEL(last_ack_rssi);
+       DEBUGFS_DEL(last_ack_ms);
+       DEBUGFS_DEL(inactive_ms);
+       DEBUGFS_DEL(last_seq_ctrl);
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+       DEBUGFS_DEL(wme_rx_queue);
+       DEBUGFS_DEL(wme_tx_queue);
+#endif
+
+       debugfs_remove(sta->debugfs.dir);
+       sta->debugfs.dir = NULL;
+}
diff --git a/net/mac80211/debugfs_sta.h b/net/mac80211/debugfs_sta.h
new file mode 100644 (file)
index 0000000..574a1cd
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __MAC80211_DEBUGFS_STA_H
+#define __MAC80211_DEBUGFS_STA_H
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+void ieee80211_sta_debugfs_add(struct sta_info *sta);
+void ieee80211_sta_debugfs_remove(struct sta_info *sta);
+#else
+static inline void ieee80211_sta_debugfs_add(struct sta_info *sta) {}
+static inline void ieee80211_sta_debugfs_remove(struct sta_info *sta) {}
+#endif
+
+#endif /* __MAC80211_DEBUGFS_STA_H */
diff --git a/net/mac80211/hostapd_ioctl.h b/net/mac80211/hostapd_ioctl.h
new file mode 100644 (file)
index 0000000..34fa128
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Host AP (software wireless LAN access point) user space daemon for
+ * Host AP kernel driver
+ * Copyright 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright 2002-2004, Instant802 Networks, Inc.
+ * Copyright 2005, Devicescape Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef HOSTAPD_IOCTL_H
+#define HOSTAPD_IOCTL_H
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#endif /* __KERNEL__ */
+
+#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0)
+#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1)
+#define PRISM2_IOCTL_HOSTAPD (SIOCIWFIRSTPRIV + 3)
+
+/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes:
+ * This table is no longer added to, the whole sub-ioctl
+ * mess shall be deleted completely. */
+enum {
+       PRISM2_PARAM_IEEE_802_1X = 23,
+       PRISM2_PARAM_ANTSEL_TX = 24,
+       PRISM2_PARAM_ANTSEL_RX = 25,
+
+       /* Instant802 additions */
+       PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES = 1001,
+       PRISM2_PARAM_DROP_UNENCRYPTED = 1002,
+       PRISM2_PARAM_PREAMBLE = 1003,
+       PRISM2_PARAM_SHORT_SLOT_TIME = 1006,
+       PRISM2_PARAM_NEXT_MODE = 1008,
+       PRISM2_PARAM_CLEAR_KEYS = 1009,
+       PRISM2_PARAM_RADIO_ENABLED = 1010,
+       PRISM2_PARAM_ANTENNA_MODE = 1013,
+       PRISM2_PARAM_STAT_TIME = 1016,
+       PRISM2_PARAM_STA_ANTENNA_SEL = 1017,
+       PRISM2_PARAM_FORCE_UNICAST_RATE = 1018,
+       PRISM2_PARAM_RATE_CTRL_NUM_UP = 1019,
+       PRISM2_PARAM_RATE_CTRL_NUM_DOWN = 1020,
+       PRISM2_PARAM_MAX_RATECTRL_RATE = 1021,
+       PRISM2_PARAM_TX_POWER_REDUCTION = 1022,
+       PRISM2_PARAM_KEY_TX_RX_THRESHOLD = 1024,
+       PRISM2_PARAM_DEFAULT_WEP_ONLY = 1026,
+       PRISM2_PARAM_WIFI_WME_NOACK_TEST = 1033,
+       PRISM2_PARAM_SCAN_FLAGS = 1035,
+       PRISM2_PARAM_HW_MODES = 1036,
+       PRISM2_PARAM_CREATE_IBSS = 1037,
+       PRISM2_PARAM_WMM_ENABLED = 1038,
+       PRISM2_PARAM_MIXED_CELL = 1039,
+       PRISM2_PARAM_RADAR_DETECT = 1043,
+       PRISM2_PARAM_SPECTRUM_MGMT = 1044,
+};
+
+enum {
+       IEEE80211_KEY_MGMT_NONE = 0,
+       IEEE80211_KEY_MGMT_IEEE8021X = 1,
+       IEEE80211_KEY_MGMT_WPA_PSK = 2,
+       IEEE80211_KEY_MGMT_WPA_EAP = 3,
+};
+
+
+/* Data structures used for get_hw_features ioctl */
+struct hostapd_ioctl_hw_modes_hdr {
+       int mode;
+       int num_channels;
+       int num_rates;
+};
+
+struct ieee80211_channel_data {
+       short chan; /* channel number (IEEE 802.11) */
+       short freq; /* frequency in MHz */
+       int flag; /* flag for hostapd use (IEEE80211_CHAN_*) */
+};
+
+struct ieee80211_rate_data {
+       int rate; /* rate in 100 kbps */
+       int flags; /* IEEE80211_RATE_ flags */
+};
+
+
+/* ADD_IF, REMOVE_IF, and UPDATE_IF 'type' argument */
+enum {
+       HOSTAP_IF_WDS = 1, HOSTAP_IF_VLAN = 2, HOSTAP_IF_BSS = 3,
+       HOSTAP_IF_STA = 4
+};
+
+struct hostapd_if_wds {
+       u8 remote_addr[ETH_ALEN];
+};
+
+struct hostapd_if_vlan {
+       u8 id;
+};
+
+struct hostapd_if_bss {
+       u8 bssid[ETH_ALEN];
+};
+
+struct hostapd_if_sta {
+};
+
+#endif /* HOSTAPD_IOCTL_H */
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
new file mode 100644 (file)
index 0000000..6e36df6
--- /dev/null
@@ -0,0 +1,4984 @@
+/*
+ * Copyright 2002-2005, Instant802 Networks, Inc.
+ * Copyright 2005-2006, Devicescape Software, Inc.
+ * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <net/mac80211.h>
+#include <net/ieee80211_radiotap.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+#include <linux/wireless.h>
+#include <linux/rtnetlink.h>
+#include <net/iw_handler.h>
+#include <linux/compiler.h>
+#include <linux/bitmap.h>
+#include <net/cfg80211.h>
+
+#include "ieee80211_common.h"
+#include "ieee80211_i.h"
+#include "ieee80211_rate.h"
+#include "wep.h"
+#include "wpa.h"
+#include "tkip.h"
+#include "wme.h"
+#include "aes_ccm.h"
+#include "ieee80211_led.h"
+#include "ieee80211_cfg.h"
+#include "debugfs.h"
+#include "debugfs_netdev.h"
+#include "debugfs_key.h"
+
+/* privid for wiphys to determine whether they belong to us or not */
+void *mac80211_wiphy_privid = &mac80211_wiphy_privid;
+
+/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
+/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
+static const unsigned char rfc1042_header[] =
+       { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+
+/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
+static const unsigned char bridge_tunnel_header[] =
+       { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
+
+/* No encapsulation header if EtherType < 0x600 (=length) */
+static const unsigned char eapol_header[] =
+       { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e };
+
+
+static inline void ieee80211_include_sequence(struct ieee80211_sub_if_data *sdata,
+                                             struct ieee80211_hdr *hdr)
+{
+       /* Set the sequence number for this frame. */
+       hdr->seq_ctrl = cpu_to_le16(sdata->sequence);
+
+       /* Increase the sequence number. */
+       sdata->sequence = (sdata->sequence + 0x10) & IEEE80211_SCTL_SEQ;
+}
+
+struct ieee80211_key_conf *
+ieee80211_key_data2conf(struct ieee80211_local *local,
+                       const struct ieee80211_key *data)
+{
+       struct ieee80211_key_conf *conf;
+
+       conf = kmalloc(sizeof(*conf) + data->keylen, GFP_ATOMIC);
+       if (!conf)
+               return NULL;
+
+       conf->hw_key_idx = data->hw_key_idx;
+       conf->alg = data->alg;
+       conf->keylen = data->keylen;
+       conf->flags = 0;
+       if (data->force_sw_encrypt)
+               conf->flags |= IEEE80211_KEY_FORCE_SW_ENCRYPT;
+       conf->keyidx = data->keyidx;
+       if (data->default_tx_key)
+               conf->flags |= IEEE80211_KEY_DEFAULT_TX_KEY;
+       if (local->default_wep_only)
+               conf->flags |= IEEE80211_KEY_DEFAULT_WEP_ONLY;
+       memcpy(conf->key, data->key, data->keylen);
+
+       return conf;
+}
+
+struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
+                                         int idx, size_t key_len, gfp_t flags)
+{
+       struct ieee80211_key *key;
+
+       key = kzalloc(sizeof(struct ieee80211_key) + key_len, flags);
+       if (!key)
+               return NULL;
+       kref_init(&key->kref);
+       return key;
+}
+
+static void ieee80211_key_release(struct kref *kref)
+{
+       struct ieee80211_key *key;
+
+       key = container_of(kref, struct ieee80211_key, kref);
+       if (key->alg == ALG_CCMP)
+               ieee80211_aes_key_free(key->u.ccmp.tfm);
+       ieee80211_debugfs_key_remove(key);
+       kfree(key);
+}
+
+void ieee80211_key_free(struct ieee80211_key *key)
+{
+       if (key)
+               kref_put(&key->kref, ieee80211_key_release);
+}
+
+static int rate_list_match(const int *rate_list, int rate)
+{
+       int i;
+
+       if (!rate_list)
+               return 0;
+
+       for (i = 0; rate_list[i] >= 0; i++)
+               if (rate_list[i] == rate)
+                       return 1;
+
+       return 0;
+}
+
+
+void ieee80211_prepare_rates(struct ieee80211_local *local,
+                            struct ieee80211_hw_mode *mode)
+{
+       int i;
+
+       for (i = 0; i < mode->num_rates; i++) {
+               struct ieee80211_rate *rate = &mode->rates[i];
+
+               rate->flags &= ~(IEEE80211_RATE_SUPPORTED |
+                                IEEE80211_RATE_BASIC);
+
+               if (local->supp_rates[mode->mode]) {
+                       if (!rate_list_match(local->supp_rates[mode->mode],
+                                            rate->rate))
+                               continue;
+               }
+
+               rate->flags |= IEEE80211_RATE_SUPPORTED;
+
+               /* Use configured basic rate set if it is available. If not,
+                * use defaults that are sane for most cases. */
+               if (local->basic_rates[mode->mode]) {
+                       if (rate_list_match(local->basic_rates[mode->mode],
+                                           rate->rate))
+                               rate->flags |= IEEE80211_RATE_BASIC;
+               } else switch (mode->mode) {
+               case MODE_IEEE80211A:
+                       if (rate->rate == 60 || rate->rate == 120 ||
+                           rate->rate == 240)
+                               rate->flags |= IEEE80211_RATE_BASIC;
+                       break;
+               case MODE_IEEE80211B:
+                       if (rate->rate == 10 || rate->rate == 20)
+                               rate->flags |= IEEE80211_RATE_BASIC;
+                       break;
+               case MODE_ATHEROS_TURBO:
+                       if (rate->rate == 120 || rate->rate == 240 ||
+                           rate->rate == 480)
+                               rate->flags |= IEEE80211_RATE_BASIC;
+                       break;
+               case MODE_IEEE80211G:
+                       if (rate->rate == 10 || rate->rate == 20 ||
+                           rate->rate == 55 || rate->rate == 110)
+                               rate->flags |= IEEE80211_RATE_BASIC;
+                       break;
+               }
+
+               /* Set ERP and MANDATORY flags based on phymode */
+               switch (mode->mode) {
+               case MODE_IEEE80211A:
+                       if (rate->rate == 60 || rate->rate == 120 ||
+                           rate->rate == 240)
+                               rate->flags |= IEEE80211_RATE_MANDATORY;
+                       break;
+               case MODE_IEEE80211B:
+                       if (rate->rate == 10)
+                               rate->flags |= IEEE80211_RATE_MANDATORY;
+                       break;
+               case MODE_ATHEROS_TURBO:
+                       break;
+               case MODE_IEEE80211G:
+                       if (rate->rate == 10 || rate->rate == 20 ||
+                           rate->rate == 55 || rate->rate == 110 ||
+                           rate->rate == 60 || rate->rate == 120 ||
+                           rate->rate == 240)
+                               rate->flags |= IEEE80211_RATE_MANDATORY;
+                       break;
+               }
+               if (ieee80211_is_erp_rate(mode->mode, rate->rate))
+                       rate->flags |= IEEE80211_RATE_ERP;
+       }
+}
+
+
+static void ieee80211_key_threshold_notify(struct net_device *dev,
+                                          struct ieee80211_key *key,
+                                          struct sta_info *sta)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct sk_buff *skb;
+       struct ieee80211_msg_key_notification *msg;
+
+       /* if no one will get it anyway, don't even allocate it.
+        * unlikely because this is only relevant for APs
+        * where the device must be open... */
+       if (unlikely(!local->apdev))
+               return;
+
+       skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) +
+                           sizeof(struct ieee80211_msg_key_notification));
+       if (!skb)
+               return;
+
+       skb_reserve(skb, sizeof(struct ieee80211_frame_info));
+       msg = (struct ieee80211_msg_key_notification *)
+               skb_put(skb, sizeof(struct ieee80211_msg_key_notification));
+       msg->tx_rx_count = key->tx_rx_count;
+       memcpy(msg->ifname, dev->name, IFNAMSIZ);
+       if (sta)
+               memcpy(msg->addr, sta->addr, ETH_ALEN);
+       else
+               memset(msg->addr, 0xff, ETH_ALEN);
+
+       key->tx_rx_count = 0;
+
+       ieee80211_rx_mgmt(local, skb, NULL,
+                         ieee80211_msg_key_threshold_notification);
+}
+
+
+static u8 * ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len)
+{
+       u16 fc;
+
+       if (len < 24)
+               return NULL;
+
+       fc = le16_to_cpu(hdr->frame_control);
+
+       switch (fc & IEEE80211_FCTL_FTYPE) {
+       case IEEE80211_FTYPE_DATA:
+               switch (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
+               case IEEE80211_FCTL_TODS:
+                       return hdr->addr1;
+               case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
+                       return NULL;
+               case IEEE80211_FCTL_FROMDS:
+                       return hdr->addr2;
+               case 0:
+                       return hdr->addr3;
+               }
+               break;
+       case IEEE80211_FTYPE_MGMT:
+               return hdr->addr3;
+       case IEEE80211_FTYPE_CTL:
+               if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)
+                       return hdr->addr1;
+               else
+                       return NULL;
+       }
+
+       return NULL;
+}
+
+int ieee80211_get_hdrlen(u16 fc)
+{
+       int hdrlen = 24;
+
+       switch (fc & IEEE80211_FCTL_FTYPE) {
+       case IEEE80211_FTYPE_DATA:
+               if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
+                       hdrlen = 30; /* Addr4 */
+               /*
+                * The QoS Control field is two bytes and its presence is
+                * indicated by the IEEE80211_STYPE_QOS_DATA bit. Add 2 to
+                * hdrlen if that bit is set.
+                * This works by masking out the bit and shifting it to
+                * bit position 1 so the result has the value 0 or 2.
+                */
+               hdrlen += (fc & IEEE80211_STYPE_QOS_DATA)
+                               >> (ilog2(IEEE80211_STYPE_QOS_DATA)-1);
+               break;
+       case IEEE80211_FTYPE_CTL:
+               /*
+                * ACK and CTS are 10 bytes, all others 16. To see how
+                * to get this condition consider
+                *   subtype mask:   0b0000000011110000 (0x00F0)
+                *   ACK subtype:    0b0000000011010000 (0x00D0)
+                *   CTS subtype:    0b0000000011000000 (0x00C0)
+                *   bits that matter:         ^^^      (0x00E0)
+                *   value of those: 0b0000000011000000 (0x00C0)
+                */
+               if ((fc & 0xE0) == 0xC0)
+                       hdrlen = 10;
+               else
+                       hdrlen = 16;
+               break;
+       }
+
+       return hdrlen;
+}
+EXPORT_SYMBOL(ieee80211_get_hdrlen);
+
+int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
+{
+       const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) skb->data;
+       int hdrlen;
+
+       if (unlikely(skb->len < 10))
+               return 0;
+       hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
+       if (unlikely(hdrlen > skb->len))
+               return 0;
+       return hdrlen;
+}
+EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
+
+static int ieee80211_get_radiotap_len(struct sk_buff *skb)
+{
+       struct ieee80211_radiotap_header *hdr =
+               (struct ieee80211_radiotap_header *) skb->data;
+
+       return le16_to_cpu(hdr->it_len);
+}
+
+#ifdef CONFIG_MAC80211_LOWTX_FRAME_DUMP
+static void ieee80211_dump_frame(const char *ifname, const char *title,
+                                const struct sk_buff *skb)
+{
+       const struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       u16 fc;
+       int hdrlen;
+
+       printk(KERN_DEBUG "%s: %s (len=%d)", ifname, title, skb->len);
+       if (skb->len < 4) {
+               printk("\n");
+               return;
+       }
+
+       fc = le16_to_cpu(hdr->frame_control);
+       hdrlen = ieee80211_get_hdrlen(fc);
+       if (hdrlen > skb->len)
+               hdrlen = skb->len;
+       if (hdrlen >= 4)
+               printk(" FC=0x%04x DUR=0x%04x",
+                      fc, le16_to_cpu(hdr->duration_id));
+       if (hdrlen >= 10)
+               printk(" A1=" MAC_FMT, MAC_ARG(hdr->addr1));
+       if (hdrlen >= 16)
+               printk(" A2=" MAC_FMT, MAC_ARG(hdr->addr2));
+       if (hdrlen >= 24)
+               printk(" A3=" MAC_FMT, MAC_ARG(hdr->addr3));
+       if (hdrlen >= 30)
+               printk(" A4=" MAC_FMT, MAC_ARG(hdr->addr4));
+       printk("\n");
+}
+#else /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */
+static inline void ieee80211_dump_frame(const char *ifname, const char *title,
+                                       struct sk_buff *skb)
+{
+}
+#endif /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */
+
+
+static int ieee80211_is_eapol(const struct sk_buff *skb)
+{
+       const struct ieee80211_hdr *hdr;
+       u16 fc;
+       int hdrlen;
+
+       if (unlikely(skb->len < 10))
+               return 0;
+
+       hdr = (const struct ieee80211_hdr *) skb->data;
+       fc = le16_to_cpu(hdr->frame_control);
+
+       if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
+               return 0;
+
+       hdrlen = ieee80211_get_hdrlen(fc);
+
+       if (unlikely(skb->len >= hdrlen + sizeof(eapol_header) &&
+                    memcmp(skb->data + hdrlen, eapol_header,
+                           sizeof(eapol_header)) == 0))
+               return 1;
+
+       return 0;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx)
+{
+       struct rate_control_extra extra;
+
+       memset(&extra, 0, sizeof(extra));
+       extra.mode = tx->u.tx.mode;
+       extra.mgmt_data = tx->sdata &&
+               tx->sdata->type == IEEE80211_IF_TYPE_MGMT;
+       extra.ethertype = tx->ethertype;
+
+       tx->u.tx.rate = rate_control_get_rate(tx->local, tx->dev, tx->skb,
+                                             &extra);
+       if (unlikely(extra.probe != NULL)) {
+               tx->u.tx.control->flags |= IEEE80211_TXCTL_RATE_CTRL_PROBE;
+               tx->u.tx.probe_last_frag = 1;
+               tx->u.tx.control->alt_retry_rate = tx->u.tx.rate->val;
+               tx->u.tx.rate = extra.probe;
+       } else {
+               tx->u.tx.control->alt_retry_rate = -1;
+       }
+       if (!tx->u.tx.rate)
+               return TXRX_DROP;
+       if (tx->u.tx.mode->mode == MODE_IEEE80211G &&
+           tx->local->cts_protect_erp_frames && tx->fragmented &&
+           extra.nonerp) {
+               tx->u.tx.last_frag_rate = tx->u.tx.rate;
+               tx->u.tx.probe_last_frag = extra.probe ? 1 : 0;
+
+               tx->u.tx.rate = extra.nonerp;
+               tx->u.tx.control->rate = extra.nonerp;
+               tx->u.tx.control->flags &= ~IEEE80211_TXCTL_RATE_CTRL_PROBE;
+       } else {
+               tx->u.tx.last_frag_rate = tx->u.tx.rate;
+               tx->u.tx.control->rate = tx->u.tx.rate;
+       }
+       tx->u.tx.control->tx_rate = tx->u.tx.rate->val;
+       if ((tx->u.tx.rate->flags & IEEE80211_RATE_PREAMBLE2) &&
+           tx->local->short_preamble &&
+           (!tx->sta || (tx->sta->flags & WLAN_STA_SHORT_PREAMBLE))) {
+               tx->u.tx.short_preamble = 1;
+               tx->u.tx.control->tx_rate = tx->u.tx.rate->val2;
+       }
+
+       return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
+{
+       if (tx->sta)
+               tx->u.tx.control->key_idx = tx->sta->key_idx_compression;
+       else
+               tx->u.tx.control->key_idx = HW_KEY_IDX_INVALID;
+
+       if (unlikely(tx->u.tx.control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
+               tx->key = NULL;
+       else if (tx->sta && tx->sta->key)
+               tx->key = tx->sta->key;
+       else if (tx->sdata->default_key)
+               tx->key = tx->sdata->default_key;
+       else if (tx->sdata->drop_unencrypted &&
+                !(tx->sdata->eapol && ieee80211_is_eapol(tx->skb))) {
+               I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
+               return TXRX_DROP;
+       } else
+               tx->key = NULL;
+
+       if (tx->key) {
+               tx->key->tx_rx_count++;
+               if (unlikely(tx->local->key_tx_rx_threshold &&
+                            tx->key->tx_rx_count >
+                            tx->local->key_tx_rx_threshold)) {
+                       ieee80211_key_threshold_notify(tx->dev, tx->key,
+                                                      tx->sta);
+               }
+       }
+
+       return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
+       size_t hdrlen, per_fragm, num_fragm, payload_len, left;
+       struct sk_buff **frags, *first, *frag;
+       int i;
+       u16 seq;
+       u8 *pos;
+       int frag_threshold = tx->local->fragmentation_threshold;
+
+       if (!tx->fragmented)
+               return TXRX_CONTINUE;
+
+       first = tx->skb;
+
+       hdrlen = ieee80211_get_hdrlen(tx->fc);
+       payload_len = first->len - hdrlen;
+       per_fragm = frag_threshold - hdrlen - FCS_LEN;
+       num_fragm = (payload_len + per_fragm - 1) / per_fragm;
+
+       frags = kzalloc(num_fragm * sizeof(struct sk_buff *), GFP_ATOMIC);
+       if (!frags)
+               goto fail;
+
+       hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS);
+       seq = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ;
+       pos = first->data + hdrlen + per_fragm;
+       left = payload_len - per_fragm;
+       for (i = 0; i < num_fragm - 1; i++) {
+               struct ieee80211_hdr *fhdr;
+               size_t copylen;
+
+               if (left <= 0)
+                       goto fail;
+
+               /* reserve enough extra head and tail room for possible
+                * encryption */
+               frag = frags[i] =
+                       dev_alloc_skb(tx->local->hw.extra_tx_headroom +
+                                     frag_threshold +
+                                     IEEE80211_ENCRYPT_HEADROOM +
+                                     IEEE80211_ENCRYPT_TAILROOM);
+               if (!frag)
+                       goto fail;
+               /* Make sure that all fragments use the same priority so
+                * that they end up using the same TX queue */
+               frag->priority = first->priority;
+               skb_reserve(frag, tx->local->hw.extra_tx_headroom +
+                       IEEE80211_ENCRYPT_HEADROOM);
+               fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen);
+               memcpy(fhdr, first->data, hdrlen);
+               if (i == num_fragm - 2)
+                       fhdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREFRAGS);
+               fhdr->seq_ctrl = cpu_to_le16(seq | ((i + 1) & IEEE80211_SCTL_FRAG));
+               copylen = left > per_fragm ? per_fragm : left;
+               memcpy(skb_put(frag, copylen), pos, copylen);
+
+               pos += copylen;
+               left -= copylen;
+       }
+       skb_trim(first, hdrlen + per_fragm);
+
+       tx->u.tx.num_extra_frag = num_fragm - 1;
+       tx->u.tx.extra_frag = frags;
+
+       return TXRX_CONTINUE;
+
+ fail:
+       printk(KERN_DEBUG "%s: failed to fragment frame\n", tx->dev->name);
+       if (frags) {
+               for (i = 0; i < num_fragm - 1; i++)
+                       if (frags[i])
+                               dev_kfree_skb(frags[i]);
+               kfree(frags);
+       }
+       I802_DEBUG_INC(tx->local->tx_handlers_drop_fragment);
+       return TXRX_DROP;
+}
+
+
+static int wep_encrypt_skb(struct ieee80211_txrx_data *tx, struct sk_buff *skb)
+{
+       if (tx->key->force_sw_encrypt) {
+               if (ieee80211_wep_encrypt(tx->local, skb, tx->key))
+                       return -1;
+       } else {
+               tx->u.tx.control->key_idx = tx->key->hw_key_idx;
+               if (tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) {
+                       if (ieee80211_wep_add_iv(tx->local, skb, tx->key) ==
+                           NULL)
+                               return -1;
+               }
+       }
+       return 0;
+}
+
+
+void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
+
+       hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+       if (tx->u.tx.extra_frag) {
+               struct ieee80211_hdr *fhdr;
+               int i;
+               for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+                       fhdr = (struct ieee80211_hdr *)
+                               tx->u.tx.extra_frag[i]->data;
+                       fhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+               }
+       }
+}
+
+
+static ieee80211_txrx_result
+ieee80211_tx_h_wep_encrypt(struct ieee80211_txrx_data *tx)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
+       u16 fc;
+
+       fc = le16_to_cpu(hdr->frame_control);
+
+       if (!tx->key || tx->key->alg != ALG_WEP ||
+           ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA &&
+            ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
+             (fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH)))
+               return TXRX_CONTINUE;
+
+       tx->u.tx.control->iv_len = WEP_IV_LEN;
+       tx->u.tx.control->icv_len = WEP_ICV_LEN;
+       ieee80211_tx_set_iswep(tx);
+
+       if (wep_encrypt_skb(tx, tx->skb) < 0) {
+               I802_DEBUG_INC(tx->local->tx_handlers_drop_wep);
+               return TXRX_DROP;
+       }
+
+       if (tx->u.tx.extra_frag) {
+               int i;
+               for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+                       if (wep_encrypt_skb(tx, tx->u.tx.extra_frag[i]) < 0) {
+                               I802_DEBUG_INC(tx->local->
+                                              tx_handlers_drop_wep);
+                               return TXRX_DROP;
+                       }
+               }
+       }
+
+       return TXRX_CONTINUE;
+}
+
+
+static int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
+                                   int rate, int erp, int short_preamble)
+{
+       int dur;
+
+       /* calculate duration (in microseconds, rounded up to next higher
+        * integer if it includes a fractional microsecond) to send frame of
+        * len bytes (does not include FCS) at the given rate. Duration will
+        * also include SIFS.
+        *
+        * rate is in 100 kbps, so divident is multiplied by 10 in the
+        * DIV_ROUND_UP() operations.
+        */
+
+       if (local->hw.conf.phymode == MODE_IEEE80211A || erp ||
+           local->hw.conf.phymode == MODE_ATHEROS_TURBO) {
+               /*
+                * OFDM:
+                *
+                * N_DBPS = DATARATE x 4
+                * N_SYM = Ceiling((16+8xLENGTH+6) / N_DBPS)
+                *      (16 = SIGNAL time, 6 = tail bits)
+                * TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext
+                *
+                * T_SYM = 4 usec
+                * 802.11a - 17.5.2: aSIFSTime = 16 usec
+                * 802.11g - 19.8.4: aSIFSTime = 10 usec +
+                *      signal ext = 6 usec
+                */
+               /* FIX: Atheros Turbo may have different (shorter) duration? */
+               dur = 16; /* SIFS + signal ext */
+               dur += 16; /* 17.3.2.3: T_PREAMBLE = 16 usec */
+               dur += 4; /* 17.3.2.3: T_SIGNAL = 4 usec */
+               dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10,
+                                       4 * rate); /* T_SYM x N_SYM */
+       } else {
+               /*
+                * 802.11b or 802.11g with 802.11b compatibility:
+                * 18.3.4: TXTIME = PreambleLength + PLCPHeaderTime +
+                * Ceiling(((LENGTH+PBCC)x8)/DATARATE). PBCC=0.
+                *
+                * 802.11 (DS): 15.3.3, 802.11b: 18.3.4
+                * aSIFSTime = 10 usec
+                * aPreambleLength = 144 usec or 72 usec with short preamble
+                * aPLCPHeaderLength = 48 usec or 24 usec with short preamble
+                */
+               dur = 10; /* aSIFSTime = 10 usec */
+               dur += short_preamble ? (72 + 24) : (144 + 48);
+
+               dur += DIV_ROUND_UP(8 * (len + 4) * 10, rate);
+       }
+
+       return dur;
+}
+
+
+/* Exported duration function for driver use */
+__le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
+                                       size_t frame_len, int rate)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+       u16 dur;
+       int erp;
+
+       erp = ieee80211_is_erp_rate(hw->conf.phymode, rate);
+       dur = ieee80211_frame_duration(local, frame_len, rate,
+                                      erp, local->short_preamble);
+
+       return cpu_to_le16(dur);
+}
+EXPORT_SYMBOL(ieee80211_generic_frame_duration);
+
+
+static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr,
+                             int next_frag_len)
+{
+       int rate, mrate, erp, dur, i;
+       struct ieee80211_rate *txrate = tx->u.tx.rate;
+       struct ieee80211_local *local = tx->local;
+       struct ieee80211_hw_mode *mode = tx->u.tx.mode;
+
+       erp = txrate->flags & IEEE80211_RATE_ERP;
+
+       /*
+        * data and mgmt (except PS Poll):
+        * - during CFP: 32768
+        * - during contention period:
+        *   if addr1 is group address: 0
+        *   if more fragments = 0 and addr1 is individual address: time to
+        *      transmit one ACK plus SIFS
+        *   if more fragments = 1 and addr1 is individual address: time to
+        *      transmit next fragment plus 2 x ACK plus 3 x SIFS
+        *
+        * IEEE 802.11, 9.6:
+        * - control response frame (CTS or ACK) shall be transmitted using the
+        *   same rate as the immediately previous frame in the frame exchange
+        *   sequence, if this rate belongs to the PHY mandatory rates, or else
+        *   at the highest possible rate belonging to the PHY rates in the
+        *   BSSBasicRateSet
+        */
+
+       if ((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) {
+               /* TODO: These control frames are not currently sent by
+                * 80211.o, but should they be implemented, this function
+                * needs to be updated to support duration field calculation.
+                *
+                * RTS: time needed to transmit pending data/mgmt frame plus
+                *    one CTS frame plus one ACK frame plus 3 x SIFS
+                * CTS: duration of immediately previous RTS minus time
+                *    required to transmit CTS and its SIFS
+                * ACK: 0 if immediately previous directed data/mgmt had
+                *    more=0, with more=1 duration in ACK frame is duration
+                *    from previous frame minus time needed to transmit ACK
+                *    and its SIFS
+                * PS Poll: BIT(15) | BIT(14) | aid
+                */
+               return 0;
+       }
+
+       /* data/mgmt */
+       if (0 /* FIX: data/mgmt during CFP */)
+               return 32768;
+
+       if (group_addr) /* Group address as the destination - no ACK */
+               return 0;
+
+       /* Individual destination address:
+        * IEEE 802.11, Ch. 9.6 (after IEEE 802.11g changes)
+        * CTS and ACK frames shall be transmitted using the highest rate in
+        * basic rate set that is less than or equal to the rate of the
+        * immediately previous frame and that is using the same modulation
+        * (CCK or OFDM). If no basic rate set matches with these requirements,
+        * the highest mandatory rate of the PHY that is less than or equal to
+        * the rate of the previous frame is used.
+        * Mandatory rates for IEEE 802.11g PHY: 1, 2, 5.5, 11, 6, 12, 24 Mbps
+        */
+       rate = -1;
+       mrate = 10; /* use 1 Mbps if everything fails */
+       for (i = 0; i < mode->num_rates; i++) {
+               struct ieee80211_rate *r = &mode->rates[i];
+               if (r->rate > txrate->rate)
+                       break;
+
+               if (IEEE80211_RATE_MODULATION(txrate->flags) !=
+                   IEEE80211_RATE_MODULATION(r->flags))
+                       continue;
+
+               if (r->flags & IEEE80211_RATE_BASIC)
+                       rate = r->rate;
+               else if (r->flags & IEEE80211_RATE_MANDATORY)
+                       mrate = r->rate;
+       }
+       if (rate == -1) {
+               /* No matching basic rate found; use highest suitable mandatory
+                * PHY rate */
+               rate = mrate;
+       }
+
+       /* Time needed to transmit ACK
+        * (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up
+        * to closest integer */
+
+       dur = ieee80211_frame_duration(local, 10, rate, erp,
+                                      local->short_preamble);
+
+       if (next_frag_len) {
+               /* Frame is fragmented: duration increases with time needed to
+                * transmit next fragment plus ACK and 2 x SIFS. */
+               dur *= 2; /* ACK + SIFS */
+               /* next fragment */
+               dur += ieee80211_frame_duration(local, next_frag_len,
+                                               txrate->rate, erp,
+                                               local->short_preamble);
+       }
+
+       return dur;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
+       u16 dur;
+       struct ieee80211_tx_control *control = tx->u.tx.control;
+       struct ieee80211_hw_mode *mode = tx->u.tx.mode;
+
+       if (!is_multicast_ether_addr(hdr->addr1)) {
+               if (tx->skb->len + FCS_LEN > tx->local->rts_threshold &&
+                   tx->local->rts_threshold < IEEE80211_MAX_RTS_THRESHOLD) {
+                       control->flags |= IEEE80211_TXCTL_USE_RTS_CTS;
+                       control->retry_limit =
+                               tx->local->long_retry_limit;
+               } else {
+                       control->retry_limit =
+                               tx->local->short_retry_limit;
+               }
+       } else {
+               control->retry_limit = 1;
+       }
+
+       if (tx->fragmented) {
+               /* Do not use multiple retry rates when sending fragmented
+                * frames.
+                * TODO: The last fragment could still use multiple retry
+                * rates. */
+               control->alt_retry_rate = -1;
+       }
+
+       /* Use CTS protection for unicast frames sent using extended rates if
+        * there are associated non-ERP stations and RTS/CTS is not configured
+        * for the frame. */
+       if (mode->mode == MODE_IEEE80211G &&
+           (tx->u.tx.rate->flags & IEEE80211_RATE_ERP) &&
+           tx->u.tx.unicast &&
+           tx->local->cts_protect_erp_frames &&
+           !(control->flags & IEEE80211_TXCTL_USE_RTS_CTS))
+               control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT;
+
+       /* Setup duration field for the first fragment of the frame. Duration
+        * for remaining fragments will be updated when they are being sent
+        * to low-level driver in ieee80211_tx(). */
+       dur = ieee80211_duration(tx, is_multicast_ether_addr(hdr->addr1),
+                                tx->fragmented ? tx->u.tx.extra_frag[0]->len :
+                                0);
+       hdr->duration_id = cpu_to_le16(dur);
+
+       if ((control->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||
+           (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) {
+               struct ieee80211_rate *rate;
+
+               /* Do not use multiple retry rates when using RTS/CTS */
+               control->alt_retry_rate = -1;
+
+               /* Use min(data rate, max base rate) as CTS/RTS rate */
+               rate = tx->u.tx.rate;
+               while (rate > mode->rates &&
+                      !(rate->flags & IEEE80211_RATE_BASIC))
+                       rate--;
+
+               control->rts_cts_rate = rate->val;
+               control->rts_rate = rate;
+       }
+
+       if (tx->sta) {
+               tx->sta->tx_packets++;
+               tx->sta->tx_fragments++;
+               tx->sta->tx_bytes += tx->skb->len;
+               if (tx->u.tx.extra_frag) {
+                       int i;
+                       tx->sta->tx_fragments += tx->u.tx.num_extra_frag;
+                       for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+                               tx->sta->tx_bytes +=
+                                       tx->u.tx.extra_frag[i]->len;
+                       }
+               }
+       }
+
+       return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx)
+{
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+       struct sk_buff *skb = tx->skb;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+       u32 sta_flags;
+
+       if (unlikely(tx->local->sta_scanning != 0) &&
+           ((tx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
+            (tx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PROBE_REQ))
+               return TXRX_DROP;
+
+       if (tx->u.tx.ps_buffered)
+               return TXRX_CONTINUE;
+
+       sta_flags = tx->sta ? tx->sta->flags : 0;
+
+       if (likely(tx->u.tx.unicast)) {
+               if (unlikely(!(sta_flags & WLAN_STA_ASSOC) &&
+                            tx->sdata->type != IEEE80211_IF_TYPE_IBSS &&
+                            (tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+                       printk(KERN_DEBUG "%s: dropped data frame to not "
+                              "associated station " MAC_FMT "\n",
+                              tx->dev->name, MAC_ARG(hdr->addr1));
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+                       I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc);
+                       return TXRX_DROP;
+               }
+       } else {
+               if (unlikely((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
+                            tx->local->num_sta == 0 &&
+                            !tx->local->allow_broadcast_always &&
+                            tx->sdata->type != IEEE80211_IF_TYPE_IBSS)) {
+                       /*
+                        * No associated STAs - no need to send multicast
+                        * frames.
+                        */
+                       return TXRX_DROP;
+               }
+               return TXRX_CONTINUE;
+       }
+
+       if (unlikely(!tx->u.tx.mgmt_interface && tx->sdata->ieee802_1x &&
+                    !(sta_flags & WLAN_STA_AUTHORIZED))) {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+               printk(KERN_DEBUG "%s: dropped frame to " MAC_FMT
+                      " (unauthorized port)\n", tx->dev->name,
+                      MAC_ARG(hdr->addr1));
+#endif
+               I802_DEBUG_INC(tx->local->tx_handlers_drop_unauth_port);
+               return TXRX_DROP;
+       }
+
+       return TXRX_CONTINUE;
+}
+
+static ieee80211_txrx_result
+ieee80211_tx_h_sequence(struct ieee80211_txrx_data *tx)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
+
+       if (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)) >= 24)
+               ieee80211_include_sequence(tx->sdata, hdr);
+
+       return TXRX_CONTINUE;
+}
+
+/* This function is called whenever the AP is about to exceed the maximum limit
+ * of buffered frames for power saving STAs. This situation should not really
+ * happen often during normal operation, so dropping the oldest buffered packet
+ * from each queue should be OK to make some room for new frames. */
+static void purge_old_ps_buffers(struct ieee80211_local *local)
+{
+       int total = 0, purged = 0;
+       struct sk_buff *skb;
+       struct ieee80211_sub_if_data *sdata;
+       struct sta_info *sta;
+
+       read_lock(&local->sub_if_lock);
+       list_for_each_entry(sdata, &local->sub_if_list, list) {
+               struct ieee80211_if_ap *ap;
+               if (sdata->dev == local->mdev ||
+                   sdata->type != IEEE80211_IF_TYPE_AP)
+                       continue;
+               ap = &sdata->u.ap;
+               skb = skb_dequeue(&ap->ps_bc_buf);
+               if (skb) {
+                       purged++;
+                       dev_kfree_skb(skb);
+               }
+               total += skb_queue_len(&ap->ps_bc_buf);
+       }
+       read_unlock(&local->sub_if_lock);
+
+       spin_lock_bh(&local->sta_lock);
+       list_for_each_entry(sta, &local->sta_list, list) {
+               skb = skb_dequeue(&sta->ps_tx_buf);
+               if (skb) {
+                       purged++;
+                       dev_kfree_skb(skb);
+               }
+               total += skb_queue_len(&sta->ps_tx_buf);
+       }
+       spin_unlock_bh(&local->sta_lock);
+
+       local->total_ps_buffered = total;
+       printk(KERN_DEBUG "%s: PS buffers full - purged %d frames\n",
+              local->mdev->name, purged);
+}
+
+
+static inline ieee80211_txrx_result
+ieee80211_tx_h_multicast_ps_buf(struct ieee80211_txrx_data *tx)
+{
+       /* broadcast/multicast frame */
+       /* If any of the associated stations is in power save mode,
+        * the frame is buffered to be sent after DTIM beacon frame */
+       if ((tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) &&
+           tx->sdata->type != IEEE80211_IF_TYPE_WDS &&
+           tx->sdata->bss && atomic_read(&tx->sdata->bss->num_sta_ps) &&
+           !(tx->fc & IEEE80211_FCTL_ORDER)) {
+               if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
+                       purge_old_ps_buffers(tx->local);
+               if (skb_queue_len(&tx->sdata->bss->ps_bc_buf) >=
+                   AP_MAX_BC_BUFFER) {
+                       if (net_ratelimit()) {
+                               printk(KERN_DEBUG "%s: BC TX buffer full - "
+                                      "dropping the oldest frame\n",
+                                      tx->dev->name);
+                       }
+                       dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf));
+               } else
+                       tx->local->total_ps_buffered++;
+               skb_queue_tail(&tx->sdata->bss->ps_bc_buf, tx->skb);
+               return TXRX_QUEUED;
+       }
+
+       return TXRX_CONTINUE;
+}
+
+
+static inline ieee80211_txrx_result
+ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
+{
+       struct sta_info *sta = tx->sta;
+
+       if (unlikely(!sta ||
+                    ((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT &&
+                     (tx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP)))
+               return TXRX_CONTINUE;
+
+       if (unlikely((sta->flags & WLAN_STA_PS) && !sta->pspoll)) {
+               struct ieee80211_tx_packet_data *pkt_data;
+#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+               printk(KERN_DEBUG "STA " MAC_FMT " aid %d: PS buffer (entries "
+                      "before %d)\n",
+                      MAC_ARG(sta->addr), sta->aid,
+                      skb_queue_len(&sta->ps_tx_buf));
+#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+               sta->flags |= WLAN_STA_TIM;
+               if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
+                       purge_old_ps_buffers(tx->local);
+               if (skb_queue_len(&sta->ps_tx_buf) >= STA_MAX_TX_BUFFER) {
+                       struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf);
+                       if (net_ratelimit()) {
+                               printk(KERN_DEBUG "%s: STA " MAC_FMT " TX "
+                                      "buffer full - dropping oldest frame\n",
+                                      tx->dev->name, MAC_ARG(sta->addr));
+                       }
+                       dev_kfree_skb(old);
+               } else
+                       tx->local->total_ps_buffered++;
+               /* Queue frame to be sent after STA sends an PS Poll frame */
+               if (skb_queue_empty(&sta->ps_tx_buf)) {
+                       if (tx->local->ops->set_tim)
+                               tx->local->ops->set_tim(local_to_hw(tx->local),
+                                                      sta->aid, 1);
+                       if (tx->sdata->bss)
+                               bss_tim_set(tx->local, tx->sdata->bss, sta->aid);
+               }
+               pkt_data = (struct ieee80211_tx_packet_data *)tx->skb->cb;
+               pkt_data->jiffies = jiffies;
+               skb_queue_tail(&sta->ps_tx_buf, tx->skb);
+               return TXRX_QUEUED;
+       }
+#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+       else if (unlikely(sta->flags & WLAN_STA_PS)) {
+               printk(KERN_DEBUG "%s: STA " MAC_FMT " in PS mode, but pspoll "
+                      "set -> send frame\n", tx->dev->name,
+                      MAC_ARG(sta->addr));
+       }
+#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+       sta->pspoll = 0;
+
+       return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx)
+{
+       if (unlikely(tx->u.tx.ps_buffered))
+               return TXRX_CONTINUE;
+
+       if (tx->u.tx.unicast)
+               return ieee80211_tx_h_unicast_ps_buf(tx);
+       else
+               return ieee80211_tx_h_multicast_ps_buf(tx);
+}
+
+
+static void inline
+__ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
+                      struct sk_buff *skb,
+                      struct net_device *dev,
+                      struct ieee80211_tx_control *control)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       int hdrlen;
+
+       memset(tx, 0, sizeof(*tx));
+       tx->skb = skb;
+       tx->dev = dev; /* use original interface */
+       tx->local = local;
+       tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       tx->sta = sta_info_get(local, hdr->addr1);
+       tx->fc = le16_to_cpu(hdr->frame_control);
+       control->power_level = local->hw.conf.power_level;
+       tx->u.tx.control = control;
+       tx->u.tx.unicast = !is_multicast_ether_addr(hdr->addr1);
+       if (is_multicast_ether_addr(hdr->addr1))
+               control->flags |= IEEE80211_TXCTL_NO_ACK;
+       else
+               control->flags &= ~IEEE80211_TXCTL_NO_ACK;
+       tx->fragmented = local->fragmentation_threshold <
+               IEEE80211_MAX_FRAG_THRESHOLD && tx->u.tx.unicast &&
+               skb->len + FCS_LEN > local->fragmentation_threshold &&
+               (!local->ops->set_frag_threshold);
+       if (!tx->sta)
+               control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
+       else if (tx->sta->clear_dst_mask) {
+               control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
+               tx->sta->clear_dst_mask = 0;
+       }
+       control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
+       if (local->sta_antenna_sel != STA_ANTENNA_SEL_AUTO && tx->sta)
+               control->antenna_sel_tx = tx->sta->antenna_sel_tx;
+       hdrlen = ieee80211_get_hdrlen(tx->fc);
+       if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) {
+               u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)];
+               tx->ethertype = (pos[0] << 8) | pos[1];
+       }
+       control->flags |= IEEE80211_TXCTL_FIRST_FRAGMENT;
+
+}
+
+static int inline is_ieee80211_device(struct net_device *dev,
+                                     struct net_device *master)
+{
+       return (wdev_priv(dev->ieee80211_ptr) ==
+               wdev_priv(master->ieee80211_ptr));
+}
+
+/* Device in tx->dev has a reference added; use dev_put(tx->dev) when
+ * finished with it. */
+static int inline ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
+                                      struct sk_buff *skb,
+                                      struct net_device *mdev,
+                                      struct ieee80211_tx_control *control)
+{
+       struct ieee80211_tx_packet_data *pkt_data;
+       struct net_device *dev;
+
+       pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
+       dev = dev_get_by_index(pkt_data->ifindex);
+       if (unlikely(dev && !is_ieee80211_device(dev, mdev))) {
+               dev_put(dev);
+               dev = NULL;
+       }
+       if (unlikely(!dev))
+               return -ENODEV;
+       __ieee80211_tx_prepare(tx, skb, dev, control);
+       return 0;
+}
+
+static inline int __ieee80211_queue_stopped(const struct ieee80211_local *local,
+                                           int queue)
+{
+       return test_bit(IEEE80211_LINK_STATE_XOFF, &local->state[queue]);
+}
+
+static inline int __ieee80211_queue_pending(const struct ieee80211_local *local,
+                                           int queue)
+{
+       return test_bit(IEEE80211_LINK_STATE_PENDING, &local->state[queue]);
+}
+
+#define IEEE80211_TX_OK                0
+#define IEEE80211_TX_AGAIN     1
+#define IEEE80211_TX_FRAG_AGAIN        2
+
+static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
+                         struct ieee80211_txrx_data *tx)
+{
+       struct ieee80211_tx_control *control = tx->u.tx.control;
+       int ret, i;
+
+       if (!ieee80211_qdisc_installed(local->mdev) &&
+           __ieee80211_queue_stopped(local, 0)) {
+               netif_stop_queue(local->mdev);
+               return IEEE80211_TX_AGAIN;
+       }
+       if (skb) {
+               ieee80211_dump_frame(local->mdev->name, "TX to low-level driver", skb);
+               ret = local->ops->tx(local_to_hw(local), skb, control);
+               if (ret)
+                       return IEEE80211_TX_AGAIN;
+               local->mdev->trans_start = jiffies;
+               ieee80211_led_tx(local, 1);
+       }
+       if (tx->u.tx.extra_frag) {
+               control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS |
+                                   IEEE80211_TXCTL_USE_CTS_PROTECT |
+                                   IEEE80211_TXCTL_CLEAR_DST_MASK |
+                                   IEEE80211_TXCTL_FIRST_FRAGMENT);
+               for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+                       if (!tx->u.tx.extra_frag[i])
+                               continue;
+                       if (__ieee80211_queue_stopped(local, control->queue))
+                               return IEEE80211_TX_FRAG_AGAIN;
+                       if (i == tx->u.tx.num_extra_frag) {
+                               control->tx_rate = tx->u.tx.last_frag_hwrate;
+                               control->rate = tx->u.tx.last_frag_rate;
+                               if (tx->u.tx.probe_last_frag)
+                                       control->flags |=
+                                               IEEE80211_TXCTL_RATE_CTRL_PROBE;
+                               else
+                                       control->flags &=
+                                               ~IEEE80211_TXCTL_RATE_CTRL_PROBE;
+                       }
+
+                       ieee80211_dump_frame(local->mdev->name,
+                                            "TX to low-level driver",
+                                            tx->u.tx.extra_frag[i]);
+                       ret = local->ops->tx(local_to_hw(local),
+                                           tx->u.tx.extra_frag[i],
+                                           control);
+                       if (ret)
+                               return IEEE80211_TX_FRAG_AGAIN;
+                       local->mdev->trans_start = jiffies;
+                       ieee80211_led_tx(local, 1);
+                       tx->u.tx.extra_frag[i] = NULL;
+               }
+               kfree(tx->u.tx.extra_frag);
+               tx->u.tx.extra_frag = NULL;
+       }
+       return IEEE80211_TX_OK;
+}
+
+static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
+                       struct ieee80211_tx_control *control, int mgmt)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct sta_info *sta;
+       ieee80211_tx_handler *handler;
+       struct ieee80211_txrx_data tx;
+       ieee80211_txrx_result res = TXRX_DROP;
+       int ret, i;
+
+       WARN_ON(__ieee80211_queue_pending(local, control->queue));
+
+       if (unlikely(skb->len < 10)) {
+               dev_kfree_skb(skb);
+               return 0;
+       }
+
+       __ieee80211_tx_prepare(&tx, skb, dev, control);
+       sta = tx.sta;
+       tx.u.tx.mgmt_interface = mgmt;
+       tx.u.tx.mode = local->hw.conf.mode;
+
+       for (handler = local->tx_handlers; *handler != NULL; handler++) {
+               res = (*handler)(&tx);
+               if (res != TXRX_CONTINUE)
+                       break;
+       }
+
+       skb = tx.skb; /* handlers are allowed to change skb */
+
+       if (sta)
+               sta_info_put(sta);
+
+       if (unlikely(res == TXRX_DROP)) {
+               I802_DEBUG_INC(local->tx_handlers_drop);
+               goto drop;
+       }
+
+       if (unlikely(res == TXRX_QUEUED)) {
+               I802_DEBUG_INC(local->tx_handlers_queued);
+               return 0;
+       }
+
+       if (tx.u.tx.extra_frag) {
+               for (i = 0; i < tx.u.tx.num_extra_frag; i++) {
+                       int next_len, dur;
+                       struct ieee80211_hdr *hdr =
+                               (struct ieee80211_hdr *)
+                               tx.u.tx.extra_frag[i]->data;
+
+                       if (i + 1 < tx.u.tx.num_extra_frag) {
+                               next_len = tx.u.tx.extra_frag[i + 1]->len;
+                       } else {
+                               next_len = 0;
+                               tx.u.tx.rate = tx.u.tx.last_frag_rate;
+                               tx.u.tx.last_frag_hwrate = tx.u.tx.rate->val;
+                       }
+                       dur = ieee80211_duration(&tx, 0, next_len);
+                       hdr->duration_id = cpu_to_le16(dur);
+               }
+       }
+
+retry:
+       ret = __ieee80211_tx(local, skb, &tx);
+       if (ret) {
+               struct ieee80211_tx_stored_packet *store =
+                       &local->pending_packet[control->queue];
+
+               if (ret == IEEE80211_TX_FRAG_AGAIN)
+                       skb = NULL;
+               set_bit(IEEE80211_LINK_STATE_PENDING,
+                       &local->state[control->queue]);
+               smp_mb();
+               /* When the driver gets out of buffers during sending of
+                * fragments and calls ieee80211_stop_queue, there is
+                * a small window between IEEE80211_LINK_STATE_XOFF and
+                * IEEE80211_LINK_STATE_PENDING flags are set. If a buffer
+                * gets available in that window (i.e. driver calls
+                * ieee80211_wake_queue), we would end up with ieee80211_tx
+                * called with IEEE80211_LINK_STATE_PENDING. Prevent this by
+                * continuing transmitting here when that situation is
+                * possible to have happened. */
+               if (!__ieee80211_queue_stopped(local, control->queue)) {
+                       clear_bit(IEEE80211_LINK_STATE_PENDING,
+                                 &local->state[control->queue]);
+                       goto retry;
+               }
+               memcpy(&store->control, control,
+                      sizeof(struct ieee80211_tx_control));
+               store->skb = skb;
+               store->extra_frag = tx.u.tx.extra_frag;
+               store->num_extra_frag = tx.u.tx.num_extra_frag;
+               store->last_frag_hwrate = tx.u.tx.last_frag_hwrate;
+               store->last_frag_rate = tx.u.tx.last_frag_rate;
+               store->last_frag_rate_ctrl_probe = tx.u.tx.probe_last_frag;
+       }
+       return 0;
+
+ drop:
+       if (skb)
+               dev_kfree_skb(skb);
+       for (i = 0; i < tx.u.tx.num_extra_frag; i++)
+               if (tx.u.tx.extra_frag[i])
+                       dev_kfree_skb(tx.u.tx.extra_frag[i]);
+       kfree(tx.u.tx.extra_frag);
+       return 0;
+}
+
+static void ieee80211_tx_pending(unsigned long data)
+{
+       struct ieee80211_local *local = (struct ieee80211_local *)data;
+       struct net_device *dev = local->mdev;
+       struct ieee80211_tx_stored_packet *store;
+       struct ieee80211_txrx_data tx;
+       int i, ret, reschedule = 0;
+
+       netif_tx_lock_bh(dev);
+       for (i = 0; i < local->hw.queues; i++) {
+               if (__ieee80211_queue_stopped(local, i))
+                       continue;
+               if (!__ieee80211_queue_pending(local, i)) {
+                       reschedule = 1;
+                       continue;
+               }
+               store = &local->pending_packet[i];
+               tx.u.tx.control = &store->control;
+               tx.u.tx.extra_frag = store->extra_frag;
+               tx.u.tx.num_extra_frag = store->num_extra_frag;
+               tx.u.tx.last_frag_hwrate = store->last_frag_hwrate;
+               tx.u.tx.last_frag_rate = store->last_frag_rate;
+               tx.u.tx.probe_last_frag = store->last_frag_rate_ctrl_probe;
+               ret = __ieee80211_tx(local, store->skb, &tx);
+               if (ret) {
+                       if (ret == IEEE80211_TX_FRAG_AGAIN)
+                               store->skb = NULL;
+               } else {
+                       clear_bit(IEEE80211_LINK_STATE_PENDING,
+                                 &local->state[i]);
+                       reschedule = 1;
+               }
+       }
+       netif_tx_unlock_bh(dev);
+       if (reschedule) {
+               if (!ieee80211_qdisc_installed(dev)) {
+                       if (!__ieee80211_queue_stopped(local, 0))
+                               netif_wake_queue(dev);
+               } else
+                       netif_schedule(dev);
+       }
+}
+
+static void ieee80211_clear_tx_pending(struct ieee80211_local *local)
+{
+       int i, j;
+       struct ieee80211_tx_stored_packet *store;
+
+       for (i = 0; i < local->hw.queues; i++) {
+               if (!__ieee80211_queue_pending(local, i))
+                       continue;
+               store = &local->pending_packet[i];
+               kfree_skb(store->skb);
+               for (j = 0; j < store->num_extra_frag; j++)
+                       kfree_skb(store->extra_frag[j]);
+               kfree(store->extra_frag);
+               clear_bit(IEEE80211_LINK_STATE_PENDING, &local->state[i]);
+       }
+}
+
+static int ieee80211_master_start_xmit(struct sk_buff *skb,
+                                      struct net_device *dev)
+{
+       struct ieee80211_tx_control control;
+       struct ieee80211_tx_packet_data *pkt_data;
+       struct net_device *odev = NULL;
+       struct ieee80211_sub_if_data *osdata;
+       int headroom;
+       int ret;
+
+       /*
+        * copy control out of the skb so other people can use skb->cb
+        */
+       pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
+       memset(&control, 0, sizeof(struct ieee80211_tx_control));
+
+       if (pkt_data->ifindex)
+               odev = dev_get_by_index(pkt_data->ifindex);
+       if (unlikely(odev && !is_ieee80211_device(odev, dev))) {
+               dev_put(odev);
+               odev = NULL;
+       }
+       if (unlikely(!odev)) {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+               printk(KERN_DEBUG "%s: Discarded packet with nonexistent "
+                      "originating device\n", dev->name);
+#endif
+               dev_kfree_skb(skb);
+               return 0;
+       }
+       osdata = IEEE80211_DEV_TO_SUB_IF(odev);
+
+       headroom = osdata->local->hw.extra_tx_headroom +
+               IEEE80211_ENCRYPT_HEADROOM;
+       if (skb_headroom(skb) < headroom) {
+               if (pskb_expand_head(skb, headroom, 0, GFP_ATOMIC)) {
+                       dev_kfree_skb(skb);
+                       return 0;
+               }
+       }
+
+       control.ifindex = odev->ifindex;
+       control.type = osdata->type;
+       if (pkt_data->req_tx_status)
+               control.flags |= IEEE80211_TXCTL_REQ_TX_STATUS;
+       if (pkt_data->do_not_encrypt)
+               control.flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
+       if (pkt_data->requeue)
+               control.flags |= IEEE80211_TXCTL_REQUEUE;
+       control.queue = pkt_data->queue;
+
+       ret = ieee80211_tx(odev, skb, &control,
+                          control.type == IEEE80211_IF_TYPE_MGMT);
+       dev_put(odev);
+
+       return ret;
+}
+
+
+/**
+ * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type
+ * subinterfaces (wlan#, WDS, and VLAN interfaces)
+ * @skb: packet to be sent
+ * @dev: incoming interface
+ *
+ * Returns: 0 on success (and frees skb in this case) or 1 on failure (skb will
+ * not be freed, and caller is responsible for either retrying later or freeing
+ * skb).
+ *
+ * This function takes in an Ethernet header and encapsulates it with suitable
+ * IEEE 802.11 header based on which interface the packet is coming in. The
+ * encapsulated packet will then be passed to master interface, wlan#.11, for
+ * transmission (through low-level driver).
+ */
+static int ieee80211_subif_start_xmit(struct sk_buff *skb,
+                                     struct net_device *dev)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_tx_packet_data *pkt_data;
+       struct ieee80211_sub_if_data *sdata;
+       int ret = 1, head_need;
+       u16 ethertype, hdrlen, fc;
+       struct ieee80211_hdr hdr;
+       const u8 *encaps_data;
+       int encaps_len, skip_header_bytes;
+       int nh_pos, h_pos, no_encrypt = 0;
+       struct sta_info *sta;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       if (unlikely(skb->len < ETH_HLEN)) {
+               printk(KERN_DEBUG "%s: short skb (len=%d)\n",
+                      dev->name, skb->len);
+               ret = 0;
+               goto fail;
+       }
+
+       nh_pos = skb_network_header(skb) - skb->data;
+       h_pos = skb_transport_header(skb) - skb->data;
+
+       /* convert Ethernet header to proper 802.11 header (based on
+        * operation mode) */
+       ethertype = (skb->data[12] << 8) | skb->data[13];
+       /* TODO: handling for 802.1x authorized/unauthorized port */
+       fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
+
+       if (likely(sdata->type == IEEE80211_IF_TYPE_AP ||
+                  sdata->type == IEEE80211_IF_TYPE_VLAN)) {
+               fc |= IEEE80211_FCTL_FROMDS;
+               /* DA BSSID SA */
+               memcpy(hdr.addr1, skb->data, ETH_ALEN);
+               memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
+               memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
+               hdrlen = 24;
+       } else if (sdata->type == IEEE80211_IF_TYPE_WDS) {
+               fc |= IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS;
+               /* RA TA DA SA */
+               memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN);
+               memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
+               memcpy(hdr.addr3, skb->data, ETH_ALEN);
+               memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
+               hdrlen = 30;
+       } else if (sdata->type == IEEE80211_IF_TYPE_STA) {
+               fc |= IEEE80211_FCTL_TODS;
+               /* BSSID SA DA */
+               memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN);
+               memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
+               memcpy(hdr.addr3, skb->data, ETH_ALEN);
+               hdrlen = 24;
+       } else if (sdata->type == IEEE80211_IF_TYPE_IBSS) {
+               /* DA SA BSSID */
+               memcpy(hdr.addr1, skb->data, ETH_ALEN);
+               memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
+               memcpy(hdr.addr3, sdata->u.sta.bssid, ETH_ALEN);
+               hdrlen = 24;
+       } else {
+               ret = 0;
+               goto fail;
+       }
+
+       /* receiver is QoS enabled, use a QoS type frame */
+       sta = sta_info_get(local, hdr.addr1);
+       if (sta) {
+               if (sta->flags & WLAN_STA_WME) {
+                       fc |= IEEE80211_STYPE_QOS_DATA;
+                       hdrlen += 2;
+               }
+               sta_info_put(sta);
+       }
+
+       hdr.frame_control = cpu_to_le16(fc);
+       hdr.duration_id = 0;
+       hdr.seq_ctrl = 0;
+
+       skip_header_bytes = ETH_HLEN;
+       if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) {
+               encaps_data = bridge_tunnel_header;
+               encaps_len = sizeof(bridge_tunnel_header);
+               skip_header_bytes -= 2;
+       } else if (ethertype >= 0x600) {
+               encaps_data = rfc1042_header;
+               encaps_len = sizeof(rfc1042_header);
+               skip_header_bytes -= 2;
+       } else {
+               encaps_data = NULL;
+               encaps_len = 0;
+       }
+
+       skb_pull(skb, skip_header_bytes);
+       nh_pos -= skip_header_bytes;
+       h_pos -= skip_header_bytes;
+
+       /* TODO: implement support for fragments so that there is no need to
+        * reallocate and copy payload; it might be enough to support one
+        * extra fragment that would be copied in the beginning of the frame
+        * data.. anyway, it would be nice to include this into skb structure
+        * somehow
+        *
+        * There are few options for this:
+        * use skb->cb as an extra space for 802.11 header
+        * allocate new buffer if not enough headroom
+        * make sure that there is enough headroom in every skb by increasing
+        * build in headroom in __dev_alloc_skb() (linux/skbuff.h) and
+        * alloc_skb() (net/core/skbuff.c)
+        */
+       head_need = hdrlen + encaps_len + local->hw.extra_tx_headroom;
+       head_need -= skb_headroom(skb);
+
+       /* We are going to modify skb data, so make a copy of it if happens to
+        * be cloned. This could happen, e.g., with Linux bridge code passing
+        * us broadcast frames. */
+
+       if (head_need > 0 || skb_cloned(skb)) {
+#if 0
+               printk(KERN_DEBUG "%s: need to reallocate buffer for %d bytes "
+                      "of headroom\n", dev->name, head_need);
+#endif
+
+               if (skb_cloned(skb))
+                       I802_DEBUG_INC(local->tx_expand_skb_head_cloned);
+               else
+                       I802_DEBUG_INC(local->tx_expand_skb_head);
+               /* Since we have to reallocate the buffer, make sure that there
+                * is enough room for possible WEP IV/ICV and TKIP (8 bytes
+                * before payload and 12 after). */
+               if (pskb_expand_head(skb, (head_need > 0 ? head_need + 8 : 8),
+                                    12, GFP_ATOMIC)) {
+                       printk(KERN_DEBUG "%s: failed to reallocate TX buffer"
+                              "\n", dev->name);
+                       goto fail;
+               }
+       }
+
+       if (encaps_data) {
+               memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len);
+               nh_pos += encaps_len;
+               h_pos += encaps_len;
+       }
+       memcpy(skb_push(skb, hdrlen), &hdr, hdrlen);
+       nh_pos += hdrlen;
+       h_pos += hdrlen;
+
+       pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
+       memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
+       pkt_data->ifindex = sdata->dev->ifindex;
+       pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT);
+       pkt_data->do_not_encrypt = no_encrypt;
+
+       skb->dev = local->mdev;
+       sdata->stats.tx_packets++;
+       sdata->stats.tx_bytes += skb->len;
+
+       /* Update skb pointers to various headers since this modified frame
+        * is going to go through Linux networking code that may potentially
+        * need things like pointer to IP header. */
+       skb_set_mac_header(skb, 0);
+       skb_set_network_header(skb, nh_pos);
+       skb_set_transport_header(skb, h_pos);
+
+       dev->trans_start = jiffies;
+       dev_queue_xmit(skb);
+
+       return 0;
+
+ fail:
+       if (!ret)
+               dev_kfree_skb(skb);
+
+       return ret;
+}
+
+
+/*
+ * This is the transmit routine for the 802.11 type interfaces
+ * called by upper layers of the linux networking
+ * stack when it has a frame to transmit
+ */
+static int
+ieee80211_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_tx_packet_data *pkt_data;
+       struct ieee80211_hdr *hdr;
+       u16 fc;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+       if (skb->len < 10) {
+               dev_kfree_skb(skb);
+               return 0;
+       }
+
+       if (skb_headroom(skb) < sdata->local->hw.extra_tx_headroom) {
+               if (pskb_expand_head(skb,
+                   sdata->local->hw.extra_tx_headroom, 0, GFP_ATOMIC)) {
+                       dev_kfree_skb(skb);
+                       return 0;
+               }
+       }
+
+       hdr = (struct ieee80211_hdr *) skb->data;
+       fc = le16_to_cpu(hdr->frame_control);
+
+       pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
+       memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
+       pkt_data->ifindex = sdata->dev->ifindex;
+       pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT);
+
+       skb->priority = 20; /* use hardcoded priority for mgmt TX queue */
+       skb->dev = sdata->local->mdev;
+
+       /*
+        * We're using the protocol field of the the frame control header
+        * to request TX callback for hostapd. BIT(1) is checked.
+        */
+       if ((fc & BIT(1)) == BIT(1)) {
+               pkt_data->req_tx_status = 1;
+               fc &= ~BIT(1);
+               hdr->frame_control = cpu_to_le16(fc);
+       }
+
+       pkt_data->do_not_encrypt = !(fc & IEEE80211_FCTL_PROTECTED);
+
+       sdata->stats.tx_packets++;
+       sdata->stats.tx_bytes += skb->len;
+
+       dev_queue_xmit(skb);
+
+       return 0;
+}
+
+
+static void ieee80211_beacon_add_tim(struct ieee80211_local *local,
+                                    struct ieee80211_if_ap *bss,
+                                    struct sk_buff *skb)
+{
+       u8 *pos, *tim;
+       int aid0 = 0;
+       int i, have_bits = 0, n1, n2;
+
+       /* Generate bitmap for TIM only if there are any STAs in power save
+        * mode. */
+       spin_lock_bh(&local->sta_lock);
+       if (atomic_read(&bss->num_sta_ps) > 0)
+               /* in the hope that this is faster than
+                * checking byte-for-byte */
+               have_bits = !bitmap_empty((unsigned long*)bss->tim,
+                                         IEEE80211_MAX_AID+1);
+
+       if (bss->dtim_count == 0)
+               bss->dtim_count = bss->dtim_period - 1;
+       else
+               bss->dtim_count--;
+
+       tim = pos = (u8 *) skb_put(skb, 6);
+       *pos++ = WLAN_EID_TIM;
+       *pos++ = 4;
+       *pos++ = bss->dtim_count;
+       *pos++ = bss->dtim_period;
+
+       if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf))
+               aid0 = 1;
+
+       if (have_bits) {
+               /* Find largest even number N1 so that bits numbered 1 through
+                * (N1 x 8) - 1 in the bitmap are 0 and number N2 so that bits
+                * (N2 + 1) x 8 through 2007 are 0. */
+               n1 = 0;
+               for (i = 0; i < IEEE80211_MAX_TIM_LEN; i++) {
+                       if (bss->tim[i]) {
+                               n1 = i & 0xfe;
+                               break;
+                       }
+               }
+               n2 = n1;
+               for (i = IEEE80211_MAX_TIM_LEN - 1; i >= n1; i--) {
+                       if (bss->tim[i]) {
+                               n2 = i;
+                               break;
+                       }
+               }
+
+               /* Bitmap control */
+               *pos++ = n1 | aid0;
+               /* Part Virt Bitmap */
+               memcpy(pos, bss->tim + n1, n2 - n1 + 1);
+
+               tim[1] = n2 - n1 + 4;
+               skb_put(skb, n2 - n1);
+       } else {
+               *pos++ = aid0; /* Bitmap control */
+               *pos++ = 0; /* Part Virt Bitmap */
+       }
+       spin_unlock_bh(&local->sta_lock);
+}
+
+
+struct sk_buff * ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id,
+                                     struct ieee80211_tx_control *control)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+       struct sk_buff *skb;
+       struct net_device *bdev;
+       struct ieee80211_sub_if_data *sdata = NULL;
+       struct ieee80211_if_ap *ap = NULL;
+       struct ieee80211_rate *rate;
+       struct rate_control_extra extra;
+       u8 *b_head, *b_tail;
+       int bh_len, bt_len;
+
+       bdev = dev_get_by_index(if_id);
+       if (bdev) {
+               sdata = IEEE80211_DEV_TO_SUB_IF(bdev);
+               ap = &sdata->u.ap;
+               dev_put(bdev);
+       }
+
+       if (!ap || sdata->type != IEEE80211_IF_TYPE_AP ||
+           !ap->beacon_head) {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+               if (net_ratelimit())
+                       printk(KERN_DEBUG "no beacon data avail for idx=%d "
+                              "(%s)\n", if_id, bdev ? bdev->name : "N/A");
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+               return NULL;
+       }
+
+       /* Assume we are generating the normal beacon locally */
+       b_head = ap->beacon_head;
+       b_tail = ap->beacon_tail;
+       bh_len = ap->beacon_head_len;
+       bt_len = ap->beacon_tail_len;
+
+       skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+               bh_len + bt_len + 256 /* maximum TIM len */);
+       if (!skb)
+               return NULL;
+
+       skb_reserve(skb, local->hw.extra_tx_headroom);
+       memcpy(skb_put(skb, bh_len), b_head, bh_len);
+
+       ieee80211_include_sequence(sdata, (struct ieee80211_hdr *)skb->data);
+
+       ieee80211_beacon_add_tim(local, ap, skb);
+
+       if (b_tail) {
+               memcpy(skb_put(skb, bt_len), b_tail, bt_len);
+       }
+
+       if (control) {
+               memset(&extra, 0, sizeof(extra));
+               extra.mode = local->oper_hw_mode;
+
+               rate = rate_control_get_rate(local, local->mdev, skb, &extra);
+               if (!rate) {
+                       if (net_ratelimit()) {
+                               printk(KERN_DEBUG "%s: ieee80211_beacon_get: no rate "
+                                      "found\n", local->mdev->name);
+                       }
+                       dev_kfree_skb(skb);
+                       return NULL;
+               }
+
+               control->tx_rate = (local->short_preamble &&
+                                   (rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
+                       rate->val2 : rate->val;
+               control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
+               control->power_level = local->hw.conf.power_level;
+               control->flags |= IEEE80211_TXCTL_NO_ACK;
+               control->retry_limit = 1;
+               control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
+       }
+
+       ap->num_beacons++;
+       return skb;
+}
+EXPORT_SYMBOL(ieee80211_beacon_get);
+
+__le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
+                             size_t frame_len,
+                             const struct ieee80211_tx_control *frame_txctl)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+       struct ieee80211_rate *rate;
+       int short_preamble = local->short_preamble;
+       int erp;
+       u16 dur;
+
+       rate = frame_txctl->rts_rate;
+       erp = !!(rate->flags & IEEE80211_RATE_ERP);
+
+       /* CTS duration */
+       dur = ieee80211_frame_duration(local, 10, rate->rate,
+                                      erp, short_preamble);
+       /* Data frame duration */
+       dur += ieee80211_frame_duration(local, frame_len, rate->rate,
+                                       erp, short_preamble);
+       /* ACK duration */
+       dur += ieee80211_frame_duration(local, 10, rate->rate,
+                                       erp, short_preamble);
+
+       return cpu_to_le16(dur);
+}
+EXPORT_SYMBOL(ieee80211_rts_duration);
+
+
+__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
+                                   size_t frame_len,
+                                   const struct ieee80211_tx_control *frame_txctl)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+       struct ieee80211_rate *rate;
+       int short_preamble = local->short_preamble;
+       int erp;
+       u16 dur;
+
+       rate = frame_txctl->rts_rate;
+       erp = !!(rate->flags & IEEE80211_RATE_ERP);
+
+       /* Data frame duration */
+       dur = ieee80211_frame_duration(local, frame_len, rate->rate,
+                                      erp, short_preamble);
+       if (!(frame_txctl->flags & IEEE80211_TXCTL_NO_ACK)) {
+               /* ACK duration */
+               dur += ieee80211_frame_duration(local, 10, rate->rate,
+                                               erp, short_preamble);
+       }
+
+       return cpu_to_le16(dur);
+}
+EXPORT_SYMBOL(ieee80211_ctstoself_duration);
+
+void ieee80211_rts_get(struct ieee80211_hw *hw,
+                      const void *frame, size_t frame_len,
+                      const struct ieee80211_tx_control *frame_txctl,
+                      struct ieee80211_rts *rts)
+{
+       const struct ieee80211_hdr *hdr = frame;
+       u16 fctl;
+
+       fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS;
+       rts->frame_control = cpu_to_le16(fctl);
+       rts->duration = ieee80211_rts_duration(hw, frame_len, frame_txctl);
+       memcpy(rts->ra, hdr->addr1, sizeof(rts->ra));
+       memcpy(rts->ta, hdr->addr2, sizeof(rts->ta));
+}
+EXPORT_SYMBOL(ieee80211_rts_get);
+
+void ieee80211_ctstoself_get(struct ieee80211_hw *hw,
+                            const void *frame, size_t frame_len,
+                            const struct ieee80211_tx_control *frame_txctl,
+                            struct ieee80211_cts *cts)
+{
+       const struct ieee80211_hdr *hdr = frame;
+       u16 fctl;
+
+       fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS;
+       cts->frame_control = cpu_to_le16(fctl);
+       cts->duration = ieee80211_ctstoself_duration(hw, frame_len, frame_txctl);
+       memcpy(cts->ra, hdr->addr1, sizeof(cts->ra));
+}
+EXPORT_SYMBOL(ieee80211_ctstoself_get);
+
+struct sk_buff *
+ieee80211_get_buffered_bc(struct ieee80211_hw *hw, int if_id,
+                         struct ieee80211_tx_control *control)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+       struct sk_buff *skb;
+       struct sta_info *sta;
+       ieee80211_tx_handler *handler;
+       struct ieee80211_txrx_data tx;
+       ieee80211_txrx_result res = TXRX_DROP;
+       struct net_device *bdev;
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_if_ap *bss = NULL;
+
+       bdev = dev_get_by_index(if_id);
+       if (bdev) {
+               sdata = IEEE80211_DEV_TO_SUB_IF(bdev);
+               bss = &sdata->u.ap;
+               dev_put(bdev);
+       }
+       if (!bss || sdata->type != IEEE80211_IF_TYPE_AP || !bss->beacon_head)
+               return NULL;
+
+       if (bss->dtim_count != 0)
+               return NULL; /* send buffered bc/mc only after DTIM beacon */
+       memset(control, 0, sizeof(*control));
+       while (1) {
+               skb = skb_dequeue(&bss->ps_bc_buf);
+               if (!skb)
+                       return NULL;
+               local->total_ps_buffered--;
+
+               if (!skb_queue_empty(&bss->ps_bc_buf) && skb->len >= 2) {
+                       struct ieee80211_hdr *hdr =
+                               (struct ieee80211_hdr *) skb->data;
+                       /* more buffered multicast/broadcast frames ==> set
+                        * MoreData flag in IEEE 802.11 header to inform PS
+                        * STAs */
+                       hdr->frame_control |=
+                               cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+               }
+
+               if (ieee80211_tx_prepare(&tx, skb, local->mdev, control) == 0)
+                       break;
+               dev_kfree_skb_any(skb);
+       }
+       sta = tx.sta;
+       tx.u.tx.ps_buffered = 1;
+
+       for (handler = local->tx_handlers; *handler != NULL; handler++) {
+               res = (*handler)(&tx);
+               if (res == TXRX_DROP || res == TXRX_QUEUED)
+                       break;
+       }
+       dev_put(tx.dev);
+       skb = tx.skb; /* handlers are allowed to change skb */
+
+       if (res == TXRX_DROP) {
+               I802_DEBUG_INC(local->tx_handlers_drop);
+               dev_kfree_skb(skb);
+               skb = NULL;
+       } else if (res == TXRX_QUEUED) {
+               I802_DEBUG_INC(local->tx_handlers_queued);
+               skb = NULL;
+       }
+
+       if (sta)
+               sta_info_put(sta);
+
+       return skb;
+}
+EXPORT_SYMBOL(ieee80211_get_buffered_bc);
+
+static int __ieee80211_if_config(struct net_device *dev,
+                                struct sk_buff *beacon,
+                                struct ieee80211_tx_control *control)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_if_conf conf;
+       static u8 scan_bssid[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+       if (!local->ops->config_interface || !netif_running(dev))
+               return 0;
+
+       memset(&conf, 0, sizeof(conf));
+       conf.type = sdata->type;
+       if (sdata->type == IEEE80211_IF_TYPE_STA ||
+           sdata->type == IEEE80211_IF_TYPE_IBSS) {
+               if (local->sta_scanning &&
+                   local->scan_dev == dev)
+                       conf.bssid = scan_bssid;
+               else
+                       conf.bssid = sdata->u.sta.bssid;
+               conf.ssid = sdata->u.sta.ssid;
+               conf.ssid_len = sdata->u.sta.ssid_len;
+               conf.generic_elem = sdata->u.sta.extra_ie;
+               conf.generic_elem_len = sdata->u.sta.extra_ie_len;
+       } else if (sdata->type == IEEE80211_IF_TYPE_AP) {
+               conf.ssid = sdata->u.ap.ssid;
+               conf.ssid_len = sdata->u.ap.ssid_len;
+               conf.generic_elem = sdata->u.ap.generic_elem;
+               conf.generic_elem_len = sdata->u.ap.generic_elem_len;
+               conf.beacon = beacon;
+               conf.beacon_control = control;
+       }
+       return local->ops->config_interface(local_to_hw(local),
+                                          dev->ifindex, &conf);
+}
+
+int ieee80211_if_config(struct net_device *dev)
+{
+       return __ieee80211_if_config(dev, NULL, NULL);
+}
+
+int ieee80211_if_config_beacon(struct net_device *dev)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_tx_control control;
+       struct sk_buff *skb;
+
+       if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE))
+               return 0;
+       skb = ieee80211_beacon_get(local_to_hw(local), dev->ifindex, &control);
+       if (!skb)
+               return -ENOMEM;
+       return __ieee80211_if_config(dev, skb, &control);
+}
+
+int ieee80211_hw_config(struct ieee80211_local *local)
+{
+       struct ieee80211_hw_mode *mode;
+       struct ieee80211_channel *chan;
+       int ret = 0;
+
+       if (local->sta_scanning) {
+               chan = local->scan_channel;
+               mode = local->scan_hw_mode;
+       } else {
+               chan = local->oper_channel;
+               mode = local->oper_hw_mode;
+       }
+
+       local->hw.conf.channel = chan->chan;
+       local->hw.conf.channel_val = chan->val;
+       local->hw.conf.power_level = chan->power_level;
+       local->hw.conf.freq = chan->freq;
+       local->hw.conf.phymode = mode->mode;
+       local->hw.conf.antenna_max = chan->antenna_max;
+       local->hw.conf.chan = chan;
+       local->hw.conf.mode = mode;
+
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+       printk(KERN_DEBUG "HW CONFIG: channel=%d freq=%d "
+              "phymode=%d\n", local->hw.conf.channel, local->hw.conf.freq,
+              local->hw.conf.phymode);
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+
+       if (local->ops->config)
+               ret = local->ops->config(local_to_hw(local), &local->hw.conf);
+
+       return ret;
+}
+
+
+static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
+{
+       /* FIX: what would be proper limits for MTU?
+        * This interface uses 802.3 frames. */
+       if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6) {
+               printk(KERN_WARNING "%s: invalid MTU %d\n",
+                      dev->name, new_mtu);
+               return -EINVAL;
+       }
+
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+       printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu);
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+       dev->mtu = new_mtu;
+       return 0;
+}
+
+
+static int ieee80211_change_mtu_apdev(struct net_device *dev, int new_mtu)
+{
+       /* FIX: what would be proper limits for MTU?
+        * This interface uses 802.11 frames. */
+       if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN) {
+               printk(KERN_WARNING "%s: invalid MTU %d\n",
+                      dev->name, new_mtu);
+               return -EINVAL;
+       }
+
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+       printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu);
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+       dev->mtu = new_mtu;
+       return 0;
+}
+
+enum netif_tx_lock_class {
+       TX_LOCK_NORMAL,
+       TX_LOCK_MASTER,
+};
+
+static inline void netif_tx_lock_nested(struct net_device *dev, int subclass)
+{
+       spin_lock_nested(&dev->_xmit_lock, subclass);
+       dev->xmit_lock_owner = smp_processor_id();
+}
+
+static void ieee80211_set_multicast_list(struct net_device *dev)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       unsigned short flags;
+
+       netif_tx_lock_nested(local->mdev, TX_LOCK_MASTER);
+       if (((dev->flags & IFF_ALLMULTI) != 0) ^ (sdata->allmulti != 0)) {
+               if (sdata->allmulti) {
+                       sdata->allmulti = 0;
+                       local->iff_allmultis--;
+               } else {
+                       sdata->allmulti = 1;
+                       local->iff_allmultis++;
+               }
+       }
+       if (((dev->flags & IFF_PROMISC) != 0) ^ (sdata->promisc != 0)) {
+               if (sdata->promisc) {
+                       sdata->promisc = 0;
+                       local->iff_promiscs--;
+               } else {
+                       sdata->promisc = 1;
+                       local->iff_promiscs++;
+               }
+       }
+       if (dev->mc_count != sdata->mc_count) {
+               local->mc_count = local->mc_count - sdata->mc_count +
+                                 dev->mc_count;
+               sdata->mc_count = dev->mc_count;
+       }
+       if (local->ops->set_multicast_list) {
+               flags = local->mdev->flags;
+               if (local->iff_allmultis)
+                       flags |= IFF_ALLMULTI;
+               if (local->iff_promiscs)
+                       flags |= IFF_PROMISC;
+               read_lock(&local->sub_if_lock);
+               local->ops->set_multicast_list(local_to_hw(local), flags,
+                                             local->mc_count);
+               read_unlock(&local->sub_if_lock);
+       }
+       netif_tx_unlock(local->mdev);
+}
+
+struct dev_mc_list *ieee80211_get_mc_list_item(struct ieee80211_hw *hw,
+                                              struct dev_mc_list *prev,
+                                              void **ptr)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+       struct ieee80211_sub_if_data *sdata = *ptr;
+       struct dev_mc_list *mc;
+
+       if (!prev) {
+               WARN_ON(sdata);
+               sdata = NULL;
+       }
+       if (!prev || !prev->next) {
+               if (sdata)
+                       sdata = list_entry(sdata->list.next,
+                                          struct ieee80211_sub_if_data, list);
+               else
+                       sdata = list_entry(local->sub_if_list.next,
+                                          struct ieee80211_sub_if_data, list);
+               if (&sdata->list != &local->sub_if_list)
+                       mc = sdata->dev->mc_list;
+               else
+                       mc = NULL;
+       } else
+               mc = prev->next;
+
+       *ptr = sdata;
+       return mc;
+}
+EXPORT_SYMBOL(ieee80211_get_mc_list_item);
+
+static struct net_device_stats *ieee80211_get_stats(struct net_device *dev)
+{
+       struct ieee80211_sub_if_data *sdata;
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       return &(sdata->stats);
+}
+
+static void ieee80211_if_shutdown(struct net_device *dev)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+       ASSERT_RTNL();
+       switch (sdata->type) {
+       case IEEE80211_IF_TYPE_STA:
+       case IEEE80211_IF_TYPE_IBSS:
+               sdata->u.sta.state = IEEE80211_DISABLED;
+               del_timer_sync(&sdata->u.sta.timer);
+               skb_queue_purge(&sdata->u.sta.skb_queue);
+               if (!local->ops->hw_scan &&
+                   local->scan_dev == sdata->dev) {
+                       local->sta_scanning = 0;
+                       cancel_delayed_work(&local->scan_work);
+               }
+               flush_workqueue(local->hw.workqueue);
+               break;
+       }
+}
+
+static inline int identical_mac_addr_allowed(int type1, int type2)
+{
+       return (type1 == IEEE80211_IF_TYPE_MNTR ||
+               type2 == IEEE80211_IF_TYPE_MNTR ||
+               (type1 == IEEE80211_IF_TYPE_AP &&
+                type2 == IEEE80211_IF_TYPE_WDS) ||
+               (type1 == IEEE80211_IF_TYPE_WDS &&
+                (type2 == IEEE80211_IF_TYPE_WDS ||
+                 type2 == IEEE80211_IF_TYPE_AP)) ||
+               (type1 == IEEE80211_IF_TYPE_AP &&
+                type2 == IEEE80211_IF_TYPE_VLAN) ||
+               (type1 == IEEE80211_IF_TYPE_VLAN &&
+                (type2 == IEEE80211_IF_TYPE_AP ||
+                 type2 == IEEE80211_IF_TYPE_VLAN)));
+}
+
+static int ieee80211_master_open(struct net_device *dev)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata;
+       int res = -EOPNOTSUPP;
+
+       read_lock(&local->sub_if_lock);
+       list_for_each_entry(sdata, &local->sub_if_list, list) {
+               if (sdata->dev != dev && netif_running(sdata->dev)) {
+                       res = 0;
+                       break;
+               }
+       }
+       read_unlock(&local->sub_if_lock);
+       return res;
+}
+
+static int ieee80211_master_stop(struct net_device *dev)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata;
+
+       read_lock(&local->sub_if_lock);
+       list_for_each_entry(sdata, &local->sub_if_list, list)
+               if (sdata->dev != dev && netif_running(sdata->dev))
+                       dev_close(sdata->dev);
+       read_unlock(&local->sub_if_lock);
+
+       return 0;
+}
+
+static int ieee80211_mgmt_open(struct net_device *dev)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+       if (!netif_running(local->mdev))
+               return -EOPNOTSUPP;
+       return 0;
+}
+
+static int ieee80211_mgmt_stop(struct net_device *dev)
+{
+       return 0;
+}
+
+/* Check if running monitor interfaces should go to a "soft monitor" mode
+ * and switch them if necessary. */
+static inline void ieee80211_start_soft_monitor(struct ieee80211_local *local)
+{
+       struct ieee80211_if_init_conf conf;
+
+       if (local->open_count && local->open_count == local->monitors &&
+           !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) &&
+           local->ops->remove_interface) {
+               conf.if_id = -1;
+               conf.type = IEEE80211_IF_TYPE_MNTR;
+               conf.mac_addr = NULL;
+               local->ops->remove_interface(local_to_hw(local), &conf);
+       }
+}
+
+/* Check if running monitor interfaces should go to a "hard monitor" mode
+ * and switch them if necessary. */
+static void ieee80211_start_hard_monitor(struct ieee80211_local *local)
+{
+       struct ieee80211_if_init_conf conf;
+
+       if (local->open_count && local->open_count == local->monitors &&
+           !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) &&
+           local->ops->add_interface) {
+               conf.if_id = -1;
+               conf.type = IEEE80211_IF_TYPE_MNTR;
+               conf.mac_addr = NULL;
+               local->ops->add_interface(local_to_hw(local), &conf);
+       }
+}
+
+static int ieee80211_open(struct net_device *dev)
+{
+       struct ieee80211_sub_if_data *sdata, *nsdata;
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_if_init_conf conf;
+       int res;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       read_lock(&local->sub_if_lock);
+       list_for_each_entry(nsdata, &local->sub_if_list, list) {
+               struct net_device *ndev = nsdata->dev;
+
+               if (ndev != dev && ndev != local->mdev && netif_running(ndev) &&
+                   compare_ether_addr(dev->dev_addr, ndev->dev_addr) == 0 &&
+                   !identical_mac_addr_allowed(sdata->type, nsdata->type)) {
+                       read_unlock(&local->sub_if_lock);
+                       return -ENOTUNIQ;
+               }
+       }
+       read_unlock(&local->sub_if_lock);
+
+       if (sdata->type == IEEE80211_IF_TYPE_WDS &&
+           is_zero_ether_addr(sdata->u.wds.remote_addr))
+               return -ENOLINK;
+
+       if (sdata->type == IEEE80211_IF_TYPE_MNTR && local->open_count &&
+           !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER)) {
+               /* run the interface in a "soft monitor" mode */
+               local->monitors++;
+               local->open_count++;
+               local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
+               return 0;
+       }
+       ieee80211_start_soft_monitor(local);
+
+       if (local->ops->add_interface) {
+               conf.if_id = dev->ifindex;
+               conf.type = sdata->type;
+               conf.mac_addr = dev->dev_addr;
+               res = local->ops->add_interface(local_to_hw(local), &conf);
+               if (res) {
+                       if (sdata->type == IEEE80211_IF_TYPE_MNTR)
+                               ieee80211_start_hard_monitor(local);
+                       return res;
+               }
+       } else {
+               if (sdata->type != IEEE80211_IF_TYPE_STA)
+                       return -EOPNOTSUPP;
+               if (local->open_count > 0)
+                       return -ENOBUFS;
+       }
+
+       if (local->open_count == 0) {
+               res = 0;
+               tasklet_enable(&local->tx_pending_tasklet);
+               tasklet_enable(&local->tasklet);
+               if (local->ops->open)
+                       res = local->ops->open(local_to_hw(local));
+               if (res == 0) {
+                       res = dev_open(local->mdev);
+                       if (res) {
+                               if (local->ops->stop)
+                                       local->ops->stop(local_to_hw(local));
+                       } else {
+                               res = ieee80211_hw_config(local);
+                               if (res && local->ops->stop)
+                                       local->ops->stop(local_to_hw(local));
+                               else if (!res && local->apdev)
+                                       dev_open(local->apdev);
+                       }
+               }
+               if (res) {
+                       if (local->ops->remove_interface)
+                               local->ops->remove_interface(local_to_hw(local),
+                                                           &conf);
+                       return res;
+               }
+       }
+       local->open_count++;
+
+       if (sdata->type == IEEE80211_IF_TYPE_MNTR) {
+               local->monitors++;
+               local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
+       } else
+               ieee80211_if_config(dev);
+
+       if (sdata->type == IEEE80211_IF_TYPE_STA &&
+           !local->user_space_mlme)
+               netif_carrier_off(dev);
+
+       netif_start_queue(dev);
+       return 0;
+}
+
+
+static int ieee80211_stop(struct net_device *dev)
+{
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+       if (sdata->type == IEEE80211_IF_TYPE_MNTR &&
+           local->open_count > 1 &&
+           !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER)) {
+               /* remove "soft monitor" interface */
+               local->open_count--;
+               local->monitors--;
+               if (!local->monitors)
+                       local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
+               return 0;
+       }
+
+       netif_stop_queue(dev);
+       ieee80211_if_shutdown(dev);
+
+       if (sdata->type == IEEE80211_IF_TYPE_MNTR) {
+               local->monitors--;
+               if (!local->monitors)
+                       local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
+       }
+
+       local->open_count--;
+       if (local->open_count == 0) {
+               if (netif_running(local->mdev))
+                       dev_close(local->mdev);
+               if (local->apdev)
+                       dev_close(local->apdev);
+               if (local->ops->stop)
+                       local->ops->stop(local_to_hw(local));
+               tasklet_disable(&local->tx_pending_tasklet);
+               tasklet_disable(&local->tasklet);
+       }
+       if (local->ops->remove_interface) {
+               struct ieee80211_if_init_conf conf;
+
+               conf.if_id = dev->ifindex;
+               conf.type = sdata->type;
+               conf.mac_addr = dev->dev_addr;
+               local->ops->remove_interface(local_to_hw(local), &conf);
+       }
+
+       ieee80211_start_hard_monitor(local);
+
+       return 0;
+}
+
+
+static int header_parse_80211(struct sk_buff *skb, unsigned char *haddr)
+{
+       memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */
+       return ETH_ALEN;
+}
+
+static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
+{
+       return compare_ether_addr(raddr, addr) == 0 ||
+              is_broadcast_ether_addr(raddr);
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
+{
+       struct net_device *dev = rx->dev;
+       struct ieee80211_local *local = rx->local;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+       u16 fc, hdrlen, ethertype;
+       u8 *payload;
+       u8 dst[ETH_ALEN];
+       u8 src[ETH_ALEN];
+       struct sk_buff *skb = rx->skb, *skb2;
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+       fc = rx->fc;
+       if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA))
+               return TXRX_CONTINUE;
+
+       if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
+               return TXRX_DROP;
+
+       hdrlen = ieee80211_get_hdrlen(fc);
+
+       /* convert IEEE 802.11 header + possible LLC headers into Ethernet
+        * header
+        * IEEE 802.11 address fields:
+        * ToDS FromDS Addr1 Addr2 Addr3 Addr4
+        *   0     0   DA    SA    BSSID n/a
+        *   0     1   DA    BSSID SA    n/a
+        *   1     0   BSSID SA    DA    n/a
+        *   1     1   RA    TA    DA    SA
+        */
+
+       switch (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
+       case IEEE80211_FCTL_TODS:
+               /* BSSID SA DA */
+               memcpy(dst, hdr->addr3, ETH_ALEN);
+               memcpy(src, hdr->addr2, ETH_ALEN);
+
+               if (unlikely(sdata->type != IEEE80211_IF_TYPE_AP &&
+                            sdata->type != IEEE80211_IF_TYPE_VLAN)) {
+                       printk(KERN_DEBUG "%s: dropped ToDS frame (BSSID="
+                              MAC_FMT " SA=" MAC_FMT " DA=" MAC_FMT ")\n",
+                              dev->name, MAC_ARG(hdr->addr1),
+                              MAC_ARG(hdr->addr2), MAC_ARG(hdr->addr3));
+                       return TXRX_DROP;
+               }
+               break;
+       case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
+               /* RA TA DA SA */
+               memcpy(dst, hdr->addr3, ETH_ALEN);
+               memcpy(src, hdr->addr4, ETH_ALEN);
+
+               if (unlikely(sdata->type != IEEE80211_IF_TYPE_WDS)) {
+                       printk(KERN_DEBUG "%s: dropped FromDS&ToDS frame (RA="
+                              MAC_FMT " TA=" MAC_FMT " DA=" MAC_FMT " SA="
+                              MAC_FMT ")\n",
+                              rx->dev->name, MAC_ARG(hdr->addr1),
+                              MAC_ARG(hdr->addr2), MAC_ARG(hdr->addr3),
+                              MAC_ARG(hdr->addr4));
+                       return TXRX_DROP;
+               }
+               break;
+       case IEEE80211_FCTL_FROMDS:
+               /* DA BSSID SA */
+               memcpy(dst, hdr->addr1, ETH_ALEN);
+               memcpy(src, hdr->addr3, ETH_ALEN);
+
+               if (sdata->type != IEEE80211_IF_TYPE_STA) {
+                       return TXRX_DROP;
+               }
+               break;
+       case 0:
+               /* DA SA BSSID */
+               memcpy(dst, hdr->addr1, ETH_ALEN);
+               memcpy(src, hdr->addr2, ETH_ALEN);
+
+               if (sdata->type != IEEE80211_IF_TYPE_IBSS) {
+                       if (net_ratelimit()) {
+                               printk(KERN_DEBUG "%s: dropped IBSS frame (DA="
+                                      MAC_FMT " SA=" MAC_FMT " BSSID=" MAC_FMT
+                                      ")\n",
+                                      dev->name, MAC_ARG(hdr->addr1),
+                                      MAC_ARG(hdr->addr2),
+                                      MAC_ARG(hdr->addr3));
+                       }
+                       return TXRX_DROP;
+               }
+               break;
+       }
+
+       payload = skb->data + hdrlen;
+
+       if (unlikely(skb->len - hdrlen < 8)) {
+               if (net_ratelimit()) {
+                       printk(KERN_DEBUG "%s: RX too short data frame "
+                              "payload\n", dev->name);
+               }
+               return TXRX_DROP;
+       }
+
+       ethertype = (payload[6] << 8) | payload[7];
+
+       if (likely((compare_ether_addr(payload, rfc1042_header) == 0 &&
+                   ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
+                  compare_ether_addr(payload, bridge_tunnel_header) == 0)) {
+               /* remove RFC1042 or Bridge-Tunnel encapsulation and
+                * replace EtherType */
+               skb_pull(skb, hdrlen + 6);
+               memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
+               memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
+       } else {
+               struct ethhdr *ehdr;
+               __be16 len;
+               skb_pull(skb, hdrlen);
+               len = htons(skb->len);
+               ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr));
+               memcpy(ehdr->h_dest, dst, ETH_ALEN);
+               memcpy(ehdr->h_source, src, ETH_ALEN);
+               ehdr->h_proto = len;
+       }
+       skb->dev = dev;
+
+       skb2 = NULL;
+
+       sdata->stats.rx_packets++;
+       sdata->stats.rx_bytes += skb->len;
+
+       if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP
+           || sdata->type == IEEE80211_IF_TYPE_VLAN) && rx->u.rx.ra_match) {
+               if (is_multicast_ether_addr(skb->data)) {
+                       /* send multicast frames both to higher layers in
+                        * local net stack and back to the wireless media */
+                       skb2 = skb_copy(skb, GFP_ATOMIC);
+                       if (!skb2)
+                               printk(KERN_DEBUG "%s: failed to clone "
+                                      "multicast frame\n", dev->name);
+               } else {
+                       struct sta_info *dsta;
+                       dsta = sta_info_get(local, skb->data);
+                       if (dsta && !dsta->dev) {
+                               printk(KERN_DEBUG "Station with null dev "
+                                      "structure!\n");
+                       } else if (dsta && dsta->dev == dev) {
+                               /* Destination station is associated to this
+                                * AP, so send the frame directly to it and
+                                * do not pass the frame to local net stack.
+                                */
+                               skb2 = skb;
+                               skb = NULL;
+                       }
+                       if (dsta)
+                               sta_info_put(dsta);
+               }
+       }
+
+       if (skb) {
+               /* deliver to local stack */
+               skb->protocol = eth_type_trans(skb, dev);
+               memset(skb->cb, 0, sizeof(skb->cb));
+               netif_rx(skb);
+       }
+
+       if (skb2) {
+               /* send to wireless media */
+               skb2->protocol = __constant_htons(ETH_P_802_3);
+               skb_set_network_header(skb2, 0);
+               skb_set_mac_header(skb2, 0);
+               dev_queue_xmit(skb2);
+       }
+
+       return TXRX_QUEUED;
+}
+
+
+static struct ieee80211_rate *
+ieee80211_get_rate(struct ieee80211_local *local, int phymode, int hw_rate)
+{
+       struct ieee80211_hw_mode *mode;
+       int r;
+
+       list_for_each_entry(mode, &local->modes_list, list) {
+               if (mode->mode != phymode)
+                       continue;
+               for (r = 0; r < mode->num_rates; r++) {
+                       struct ieee80211_rate *rate = &mode->rates[r];
+                       if (rate->val == hw_rate ||
+                           (rate->flags & IEEE80211_RATE_PREAMBLE2 &&
+                            rate->val2 == hw_rate))
+                               return rate;
+               }
+       }
+
+       return NULL;
+}
+
+static void
+ieee80211_fill_frame_info(struct ieee80211_local *local,
+                         struct ieee80211_frame_info *fi,
+                         struct ieee80211_rx_status *status)
+{
+       if (status) {
+               struct timespec ts;
+               struct ieee80211_rate *rate;
+
+               jiffies_to_timespec(jiffies, &ts);
+               fi->hosttime = cpu_to_be64((u64) ts.tv_sec * 1000000 +
+                                          ts.tv_nsec / 1000);
+               fi->mactime = cpu_to_be64(status->mactime);
+               switch (status->phymode) {
+               case MODE_IEEE80211A:
+                       fi->phytype = htonl(ieee80211_phytype_ofdm_dot11_a);
+                       break;
+               case MODE_IEEE80211B:
+                       fi->phytype = htonl(ieee80211_phytype_dsss_dot11_b);
+                       break;
+               case MODE_IEEE80211G:
+                       fi->phytype = htonl(ieee80211_phytype_pbcc_dot11_g);
+                       break;
+               case MODE_ATHEROS_TURBO:
+                       fi->phytype =
+                               htonl(ieee80211_phytype_dsss_dot11_turbo);
+                       break;
+               default:
+                       fi->phytype = htonl(0xAAAAAAAA);
+                       break;
+               }
+               fi->channel = htonl(status->channel);
+               rate = ieee80211_get_rate(local, status->phymode,
+                                         status->rate);
+               if (rate) {
+                       fi->datarate = htonl(rate->rate);
+                       if (rate->flags & IEEE80211_RATE_PREAMBLE2) {
+                               if (status->rate == rate->val)
+                                       fi->preamble = htonl(2); /* long */
+                               else if (status->rate == rate->val2)
+                                       fi->preamble = htonl(1); /* short */
+                       } else
+                               fi->preamble = htonl(0);
+               } else {
+                       fi->datarate = htonl(0);
+                       fi->preamble = htonl(0);
+               }
+
+               fi->antenna = htonl(status->antenna);
+               fi->priority = htonl(0xffffffff); /* no clue */
+               fi->ssi_type = htonl(ieee80211_ssi_raw);
+               fi->ssi_signal = htonl(status->ssi);
+               fi->ssi_noise = 0x00000000;
+               fi->encoding = 0;
+       } else {
+               /* clear everything because we really don't know.
+                * the msg_type field isn't present on monitor frames
+                * so we don't know whether it will be present or not,
+                * but it's ok to not clear it since it'll be assigned
+                * anyway */
+               memset(fi, 0, sizeof(*fi) - sizeof(fi->msg_type));
+
+               fi->ssi_type = htonl(ieee80211_ssi_none);
+       }
+       fi->version = htonl(IEEE80211_FI_VERSION);
+       fi->length = cpu_to_be32(sizeof(*fi) - sizeof(fi->msg_type));
+}
+
+/* this routine is actually not just for this, but also
+ * for pushing fake 'management' frames into userspace.
+ * it shall be replaced by a netlink-based system. */
+void
+ieee80211_rx_mgmt(struct ieee80211_local *local, struct sk_buff *skb,
+                 struct ieee80211_rx_status *status, u32 msg_type)
+{
+       struct ieee80211_frame_info *fi;
+       const size_t hlen = sizeof(struct ieee80211_frame_info);
+       struct ieee80211_sub_if_data *sdata;
+
+       skb->dev = local->apdev;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(local->apdev);
+
+       if (skb_headroom(skb) < hlen) {
+               I802_DEBUG_INC(local->rx_expand_skb_head);
+               if (pskb_expand_head(skb, hlen, 0, GFP_ATOMIC)) {
+                       dev_kfree_skb(skb);
+                       return;
+               }
+       }
+
+       fi = (struct ieee80211_frame_info *) skb_push(skb, hlen);
+
+       ieee80211_fill_frame_info(local, fi, status);
+       fi->msg_type = htonl(msg_type);
+
+       sdata->stats.rx_packets++;
+       sdata->stats.rx_bytes += skb->len;
+
+       skb_set_mac_header(skb, 0);
+       skb->ip_summed = CHECKSUM_UNNECESSARY;
+       skb->pkt_type = PACKET_OTHERHOST;
+       skb->protocol = htons(ETH_P_802_2);
+       memset(skb->cb, 0, sizeof(skb->cb));
+       netif_rx(skb);
+}
+
+static void
+ieee80211_rx_monitor(struct net_device *dev, struct sk_buff *skb,
+                    struct ieee80211_rx_status *status)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_rate *rate;
+       struct ieee80211_rtap_hdr {
+               struct ieee80211_radiotap_header hdr;
+               u8 flags;
+               u8 rate;
+               __le16 chan_freq;
+               __le16 chan_flags;
+               u8 antsignal;
+       } __attribute__ ((packed)) *rthdr;
+
+       skb->dev = dev;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+       if (status->flag & RX_FLAG_RADIOTAP)
+               goto out;
+
+       if (skb_headroom(skb) < sizeof(*rthdr)) {
+               I802_DEBUG_INC(local->rx_expand_skb_head);
+               if (pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC)) {
+                       dev_kfree_skb(skb);
+                       return;
+               }
+       }
+
+       rthdr = (struct ieee80211_rtap_hdr *) skb_push(skb, sizeof(*rthdr));
+       memset(rthdr, 0, sizeof(*rthdr));
+       rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
+       rthdr->hdr.it_present =
+               cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
+                           (1 << IEEE80211_RADIOTAP_RATE) |
+                           (1 << IEEE80211_RADIOTAP_CHANNEL) |
+                           (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL));
+       rthdr->flags = local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS ?
+                      IEEE80211_RADIOTAP_F_FCS : 0;
+       rate = ieee80211_get_rate(local, status->phymode, status->rate);
+       if (rate)
+               rthdr->rate = rate->rate / 5;
+       rthdr->chan_freq = cpu_to_le16(status->freq);
+       rthdr->chan_flags =
+               status->phymode == MODE_IEEE80211A ?
+               cpu_to_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ) :
+               cpu_to_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ);
+       rthdr->antsignal = status->ssi;
+
+ out:
+       sdata->stats.rx_packets++;
+       sdata->stats.rx_bytes += skb->len;
+
+       skb_set_mac_header(skb, 0);
+       skb->ip_summed = CHECKSUM_UNNECESSARY;
+       skb->pkt_type = PACKET_OTHERHOST;
+       skb->protocol = htons(ETH_P_802_2);
+       memset(skb->cb, 0, sizeof(skb->cb));
+       netif_rx(skb);
+}
+
+int ieee80211_radar_status(struct ieee80211_hw *hw, int channel,
+                          int radar, int radar_type)
+{
+       struct sk_buff *skb;
+       struct ieee80211_radar_info *msg;
+       struct ieee80211_local *local = hw_to_local(hw);
+
+       if (!local->apdev)
+               return 0;
+
+       skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) +
+                           sizeof(struct ieee80211_radar_info));
+
+       if (!skb)
+               return -ENOMEM;
+       skb_reserve(skb, sizeof(struct ieee80211_frame_info));
+
+       msg = (struct ieee80211_radar_info *)
+               skb_put(skb, sizeof(struct ieee80211_radar_info));
+       msg->channel = channel;
+       msg->radar = radar;
+       msg->radar_type = radar_type;
+
+       ieee80211_rx_mgmt(local, skb, NULL, ieee80211_msg_radar);
+       return 0;
+}
+EXPORT_SYMBOL(ieee80211_radar_status);
+
+int ieee80211_set_aid_for_sta(struct ieee80211_hw *hw, u8 *peer_address,
+                             u16 aid)
+{
+       struct sk_buff *skb;
+       struct ieee80211_msg_set_aid_for_sta *msg;
+       struct ieee80211_local *local = hw_to_local(hw);
+
+       /* unlikely because if this event only happens for APs,
+        * which require an open ap device. */
+       if (unlikely(!local->apdev))
+               return 0;
+
+       skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) +
+                           sizeof(struct ieee80211_msg_set_aid_for_sta));
+
+       if (!skb)
+               return -ENOMEM;
+       skb_reserve(skb, sizeof(struct ieee80211_frame_info));
+
+       msg = (struct ieee80211_msg_set_aid_for_sta *)
+               skb_put(skb, sizeof(struct ieee80211_msg_set_aid_for_sta));
+       memcpy(msg->sta_address, peer_address, ETH_ALEN);
+       msg->aid = aid;
+
+       ieee80211_rx_mgmt(local, skb, NULL, ieee80211_msg_set_aid_for_sta);
+       return 0;
+}
+EXPORT_SYMBOL(ieee80211_set_aid_for_sta);
+
+static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta)
+{
+       struct ieee80211_sub_if_data *sdata;
+       sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+
+       if (sdata->bss)
+               atomic_inc(&sdata->bss->num_sta_ps);
+       sta->flags |= WLAN_STA_PS;
+       sta->pspoll = 0;
+#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+       printk(KERN_DEBUG "%s: STA " MAC_FMT " aid %d enters power "
+              "save mode\n", dev->name, MAC_ARG(sta->addr), sta->aid);
+#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+}
+
+
+static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct sk_buff *skb;
+       int sent = 0;
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_tx_packet_data *pkt_data;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+       if (sdata->bss)
+               atomic_dec(&sdata->bss->num_sta_ps);
+       sta->flags &= ~(WLAN_STA_PS | WLAN_STA_TIM);
+       sta->pspoll = 0;
+       if (!skb_queue_empty(&sta->ps_tx_buf)) {
+               if (local->ops->set_tim)
+                       local->ops->set_tim(local_to_hw(local), sta->aid, 0);
+               if (sdata->bss)
+                       bss_tim_clear(local, sdata->bss, sta->aid);
+       }
+#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+       printk(KERN_DEBUG "%s: STA " MAC_FMT " aid %d exits power "
+              "save mode\n", dev->name, MAC_ARG(sta->addr), sta->aid);
+#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+       /* Send all buffered frames to the station */
+       while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
+               pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
+               sent++;
+               pkt_data->requeue = 1;
+               dev_queue_xmit(skb);
+       }
+       while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
+               pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
+               local->total_ps_buffered--;
+               sent++;
+#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+               printk(KERN_DEBUG "%s: STA " MAC_FMT " aid %d send PS frame "
+                      "since STA not sleeping anymore\n", dev->name,
+                      MAC_ARG(sta->addr), sta->aid);
+#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+               pkt_data->requeue = 1;
+               dev_queue_xmit(skb);
+       }
+
+       return sent;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx)
+{
+       struct sk_buff *skb;
+       int no_pending_pkts;
+
+       if (likely(!rx->sta ||
+                  (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL ||
+                  (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PSPOLL ||
+                  !rx->u.rx.ra_match))
+               return TXRX_CONTINUE;
+
+       skb = skb_dequeue(&rx->sta->tx_filtered);
+       if (!skb) {
+               skb = skb_dequeue(&rx->sta->ps_tx_buf);
+               if (skb)
+                       rx->local->total_ps_buffered--;
+       }
+       no_pending_pkts = skb_queue_empty(&rx->sta->tx_filtered) &&
+               skb_queue_empty(&rx->sta->ps_tx_buf);
+
+       if (skb) {
+               struct ieee80211_hdr *hdr =
+                       (struct ieee80211_hdr *) skb->data;
+
+               /* tell TX path to send one frame even though the STA may
+                * still remain is PS mode after this frame exchange */
+               rx->sta->pspoll = 1;
+
+#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+               printk(KERN_DEBUG "STA " MAC_FMT " aid %d: PS Poll (entries "
+                      "after %d)\n",
+                      MAC_ARG(rx->sta->addr), rx->sta->aid,
+                      skb_queue_len(&rx->sta->ps_tx_buf));
+#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+
+               /* Use MoreData flag to indicate whether there are more
+                * buffered frames for this STA */
+               if (no_pending_pkts) {
+                       hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA);
+                       rx->sta->flags &= ~WLAN_STA_TIM;
+               } else
+                       hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+
+               dev_queue_xmit(skb);
+
+               if (no_pending_pkts) {
+                       if (rx->local->ops->set_tim)
+                               rx->local->ops->set_tim(local_to_hw(rx->local),
+                                                      rx->sta->aid, 0);
+                       if (rx->sdata->bss)
+                               bss_tim_clear(rx->local, rx->sdata->bss, rx->sta->aid);
+               }
+#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+       } else if (!rx->u.rx.sent_ps_buffered) {
+               printk(KERN_DEBUG "%s: STA " MAC_FMT " sent PS Poll even "
+                      "though there is no buffered frames for it\n",
+                      rx->dev->name, MAC_ARG(rx->sta->addr));
+#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+
+       }
+
+       /* Free PS Poll skb here instead of returning TXRX_DROP that would
+        * count as an dropped frame. */
+       dev_kfree_skb(rx->skb);
+
+       return TXRX_QUEUED;
+}
+
+
+static inline struct ieee80211_fragment_entry *
+ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
+                        unsigned int frag, unsigned int seq, int rx_queue,
+                        struct sk_buff **skb)
+{
+       struct ieee80211_fragment_entry *entry;
+       int idx;
+
+       idx = sdata->fragment_next;
+       entry = &sdata->fragments[sdata->fragment_next++];
+       if (sdata->fragment_next >= IEEE80211_FRAGMENT_MAX)
+               sdata->fragment_next = 0;
+
+       if (!skb_queue_empty(&entry->skb_list)) {
+#ifdef CONFIG_MAC80211_DEBUG
+               struct ieee80211_hdr *hdr =
+                       (struct ieee80211_hdr *) entry->skb_list.next->data;
+               printk(KERN_DEBUG "%s: RX reassembly removed oldest "
+                      "fragment entry (idx=%d age=%lu seq=%d last_frag=%d "
+                      "addr1=" MAC_FMT " addr2=" MAC_FMT "\n",
+                      sdata->dev->name, idx,
+                      jiffies - entry->first_frag_time, entry->seq,
+                      entry->last_frag, MAC_ARG(hdr->addr1),
+                      MAC_ARG(hdr->addr2));
+#endif /* CONFIG_MAC80211_DEBUG */
+               __skb_queue_purge(&entry->skb_list);
+       }
+
+       __skb_queue_tail(&entry->skb_list, *skb); /* no need for locking */
+       *skb = NULL;
+       entry->first_frag_time = jiffies;
+       entry->seq = seq;
+       entry->rx_queue = rx_queue;
+       entry->last_frag = frag;
+       entry->ccmp = 0;
+       entry->extra_len = 0;
+
+       return entry;
+}
+
+
+static inline struct ieee80211_fragment_entry *
+ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
+                         u16 fc, unsigned int frag, unsigned int seq,
+                         int rx_queue, struct ieee80211_hdr *hdr)
+{
+       struct ieee80211_fragment_entry *entry;
+       int i, idx;
+
+       idx = sdata->fragment_next;
+       for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
+               struct ieee80211_hdr *f_hdr;
+               u16 f_fc;
+
+               idx--;
+               if (idx < 0)
+                       idx = IEEE80211_FRAGMENT_MAX - 1;
+
+               entry = &sdata->fragments[idx];
+               if (skb_queue_empty(&entry->skb_list) || entry->seq != seq ||
+                   entry->rx_queue != rx_queue ||
+                   entry->last_frag + 1 != frag)
+                       continue;
+
+               f_hdr = (struct ieee80211_hdr *) entry->skb_list.next->data;
+               f_fc = le16_to_cpu(f_hdr->frame_control);
+
+               if ((fc & IEEE80211_FCTL_FTYPE) != (f_fc & IEEE80211_FCTL_FTYPE) ||
+                   compare_ether_addr(hdr->addr1, f_hdr->addr1) != 0 ||
+                   compare_ether_addr(hdr->addr2, f_hdr->addr2) != 0)
+                       continue;
+
+               if (entry->first_frag_time + 2 * HZ < jiffies) {
+                       __skb_queue_purge(&entry->skb_list);
+                       continue;
+               }
+               return entry;
+       }
+
+       return NULL;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
+{
+       struct ieee80211_hdr *hdr;
+       u16 sc;
+       unsigned int frag, seq;
+       struct ieee80211_fragment_entry *entry;
+       struct sk_buff *skb;
+
+       hdr = (struct ieee80211_hdr *) rx->skb->data;
+       sc = le16_to_cpu(hdr->seq_ctrl);
+       frag = sc & IEEE80211_SCTL_FRAG;
+
+       if (likely((!(rx->fc & IEEE80211_FCTL_MOREFRAGS) && frag == 0) ||
+                  (rx->skb)->len < 24 ||
+                  is_multicast_ether_addr(hdr->addr1))) {
+               /* not fragmented */
+               goto out;
+       }
+       I802_DEBUG_INC(rx->local->rx_handlers_fragments);
+
+       seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
+
+       if (frag == 0) {
+               /* This is the first fragment of a new frame. */
+               entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
+                                                rx->u.rx.queue, &(rx->skb));
+               if (rx->key && rx->key->alg == ALG_CCMP &&
+                   (rx->fc & IEEE80211_FCTL_PROTECTED)) {
+                       /* Store CCMP PN so that we can verify that the next
+                        * fragment has a sequential PN value. */
+                       entry->ccmp = 1;
+                       memcpy(entry->last_pn,
+                              rx->key->u.ccmp.rx_pn[rx->u.rx.queue],
+                              CCMP_PN_LEN);
+               }
+               return TXRX_QUEUED;
+       }
+
+       /* This is a fragment for a frame that should already be pending in
+        * fragment cache. Add this fragment to the end of the pending entry.
+        */
+       entry = ieee80211_reassemble_find(rx->sdata, rx->fc, frag, seq,
+                                         rx->u.rx.queue, hdr);
+       if (!entry) {
+               I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
+               return TXRX_DROP;
+       }
+
+       /* Verify that MPDUs within one MSDU have sequential PN values.
+        * (IEEE 802.11i, 8.3.3.4.5) */
+       if (entry->ccmp) {
+               int i;
+               u8 pn[CCMP_PN_LEN], *rpn;
+               if (!rx->key || rx->key->alg != ALG_CCMP)
+                       return TXRX_DROP;
+               memcpy(pn, entry->last_pn, CCMP_PN_LEN);
+               for (i = CCMP_PN_LEN - 1; i >= 0; i--) {
+                       pn[i]++;
+                       if (pn[i])
+                               break;
+               }
+               rpn = rx->key->u.ccmp.rx_pn[rx->u.rx.queue];
+               if (memcmp(pn, rpn, CCMP_PN_LEN) != 0) {
+                       printk(KERN_DEBUG "%s: defrag: CCMP PN not sequential"
+                              " A2=" MAC_FMT " PN=%02x%02x%02x%02x%02x%02x "
+                              "(expected %02x%02x%02x%02x%02x%02x)\n",
+                              rx->dev->name, MAC_ARG(hdr->addr2),
+                              rpn[0], rpn[1], rpn[2], rpn[3], rpn[4], rpn[5],
+                              pn[0], pn[1], pn[2], pn[3], pn[4], pn[5]);
+                       return TXRX_DROP;
+               }
+               memcpy(entry->last_pn, pn, CCMP_PN_LEN);
+       }
+
+       skb_pull(rx->skb, ieee80211_get_hdrlen(rx->fc));
+       __skb_queue_tail(&entry->skb_list, rx->skb);
+       entry->last_frag = frag;
+       entry->extra_len += rx->skb->len;
+       if (rx->fc & IEEE80211_FCTL_MOREFRAGS) {
+               rx->skb = NULL;
+               return TXRX_QUEUED;
+       }
+
+       rx->skb = __skb_dequeue(&entry->skb_list);
+       if (skb_tailroom(rx->skb) < entry->extra_len) {
+               I802_DEBUG_INC(rx->local->rx_expand_skb_head2);
+               if (unlikely(pskb_expand_head(rx->skb, 0, entry->extra_len,
+                                             GFP_ATOMIC))) {
+                       I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
+                       __skb_queue_purge(&entry->skb_list);
+                       return TXRX_DROP;
+               }
+       }
+       while ((skb = __skb_dequeue(&entry->skb_list)))
+               memcpy(skb_put(rx->skb, skb->len), skb->data, skb->len);
+
+       /* Complete frame has been reassembled - process it now */
+       rx->fragmented = 1;
+
+ out:
+       if (rx->sta)
+               rx->sta->rx_packets++;
+       if (is_multicast_ether_addr(hdr->addr1))
+               rx->local->dot11MulticastReceivedFrameCount++;
+       else
+               ieee80211_led_rx(rx->local);
+       return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_monitor(struct ieee80211_txrx_data *rx)
+{
+       if (rx->sdata->type == IEEE80211_IF_TYPE_MNTR) {
+               ieee80211_rx_monitor(rx->dev, rx->skb, rx->u.rx.status);
+               return TXRX_QUEUED;
+       }
+
+       if (rx->u.rx.status->flag & RX_FLAG_RADIOTAP)
+               skb_pull(rx->skb, ieee80211_get_radiotap_len(rx->skb));
+
+       return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_check(struct ieee80211_txrx_data *rx)
+{
+       struct ieee80211_hdr *hdr;
+       int always_sta_key;
+       hdr = (struct ieee80211_hdr *) rx->skb->data;
+
+       /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */
+       if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) {
+               if (unlikely(rx->fc & IEEE80211_FCTL_RETRY &&
+                            rx->sta->last_seq_ctrl[rx->u.rx.queue] ==
+                            hdr->seq_ctrl)) {
+                       if (rx->u.rx.ra_match) {
+                               rx->local->dot11FrameDuplicateCount++;
+                               rx->sta->num_duplicates++;
+                       }
+                       return TXRX_DROP;
+               } else
+                       rx->sta->last_seq_ctrl[rx->u.rx.queue] = hdr->seq_ctrl;
+       }
+
+       if ((rx->local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) &&
+           rx->skb->len > FCS_LEN)
+               skb_trim(rx->skb, rx->skb->len - FCS_LEN);
+
+       if (unlikely(rx->skb->len < 16)) {
+               I802_DEBUG_INC(rx->local->rx_handlers_drop_short);
+               return TXRX_DROP;
+       }
+
+       if (!rx->u.rx.ra_match)
+               rx->skb->pkt_type = PACKET_OTHERHOST;
+       else if (compare_ether_addr(rx->dev->dev_addr, hdr->addr1) == 0)
+               rx->skb->pkt_type = PACKET_HOST;
+       else if (is_multicast_ether_addr(hdr->addr1)) {
+               if (is_broadcast_ether_addr(hdr->addr1))
+                       rx->skb->pkt_type = PACKET_BROADCAST;
+               else
+                       rx->skb->pkt_type = PACKET_MULTICAST;
+       } else
+               rx->skb->pkt_type = PACKET_OTHERHOST;
+
+       /* Drop disallowed frame classes based on STA auth/assoc state;
+        * IEEE 802.11, Chap 5.5.
+        *
+        * 80211.o does filtering only based on association state, i.e., it
+        * drops Class 3 frames from not associated stations. hostapd sends
+        * deauth/disassoc frames when needed. In addition, hostapd is
+        * responsible for filtering on both auth and assoc states.
+        */
+       if (unlikely(((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA ||
+                     ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL &&
+                      (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)) &&
+                    rx->sdata->type != IEEE80211_IF_TYPE_IBSS &&
+                    (!rx->sta || !(rx->sta->flags & WLAN_STA_ASSOC)))) {
+               if ((!(rx->fc & IEEE80211_FCTL_FROMDS) &&
+                    !(rx->fc & IEEE80211_FCTL_TODS) &&
+                    (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
+                   || !rx->u.rx.ra_match) {
+                       /* Drop IBSS frames and frames for other hosts
+                        * silently. */
+                       return TXRX_DROP;
+               }
+
+               if (!rx->local->apdev)
+                       return TXRX_DROP;
+
+               ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status,
+                                 ieee80211_msg_sta_not_assoc);
+               return TXRX_QUEUED;
+       }
+
+       if (rx->sdata->type == IEEE80211_IF_TYPE_STA)
+               always_sta_key = 0;
+       else
+               always_sta_key = 1;
+
+       if (rx->sta && rx->sta->key && always_sta_key) {
+               rx->key = rx->sta->key;
+       } else {
+               if (rx->sta && rx->sta->key)
+                       rx->key = rx->sta->key;
+               else
+                       rx->key = rx->sdata->default_key;
+
+               if ((rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) &&
+                   rx->fc & IEEE80211_FCTL_PROTECTED) {
+                       int keyidx = ieee80211_wep_get_keyidx(rx->skb);
+
+                       if (keyidx >= 0 && keyidx < NUM_DEFAULT_KEYS &&
+                           (!rx->sta || !rx->sta->key || keyidx > 0))
+                               rx->key = rx->sdata->keys[keyidx];
+
+                       if (!rx->key) {
+                               if (!rx->u.rx.ra_match)
+                                       return TXRX_DROP;
+                               printk(KERN_DEBUG "%s: RX WEP frame with "
+                                      "unknown keyidx %d (A1=" MAC_FMT " A2="
+                                      MAC_FMT " A3=" MAC_FMT ")\n",
+                                      rx->dev->name, keyidx,
+                                      MAC_ARG(hdr->addr1),
+                                      MAC_ARG(hdr->addr2),
+                                      MAC_ARG(hdr->addr3));
+                               if (!rx->local->apdev)
+                                       return TXRX_DROP;
+                               ieee80211_rx_mgmt(
+                                       rx->local, rx->skb, rx->u.rx.status,
+                                       ieee80211_msg_wep_frame_unknown_key);
+                               return TXRX_QUEUED;
+                       }
+               }
+       }
+
+       if (rx->fc & IEEE80211_FCTL_PROTECTED && rx->key && rx->u.rx.ra_match) {
+               rx->key->tx_rx_count++;
+               if (unlikely(rx->local->key_tx_rx_threshold &&
+                            rx->key->tx_rx_count >
+                            rx->local->key_tx_rx_threshold)) {
+                       ieee80211_key_threshold_notify(rx->dev, rx->key,
+                                                      rx->sta);
+               }
+       }
+
+       return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_sta_process(struct ieee80211_txrx_data *rx)
+{
+       struct sta_info *sta = rx->sta;
+       struct net_device *dev = rx->dev;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+
+       if (!sta)
+               return TXRX_CONTINUE;
+
+       /* Update last_rx only for IBSS packets which are for the current
+        * BSSID to avoid keeping the current IBSS network alive in cases where
+        * other STAs are using different BSSID. */
+       if (rx->sdata->type == IEEE80211_IF_TYPE_IBSS) {
+               u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len);
+               if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0)
+                       sta->last_rx = jiffies;
+       } else
+       if (!is_multicast_ether_addr(hdr->addr1) ||
+           rx->sdata->type == IEEE80211_IF_TYPE_STA) {
+               /* Update last_rx only for unicast frames in order to prevent
+                * the Probe Request frames (the only broadcast frames from a
+                * STA in infrastructure mode) from keeping a connection alive.
+                */
+               sta->last_rx = jiffies;
+       }
+
+       if (!rx->u.rx.ra_match)
+               return TXRX_CONTINUE;
+
+       sta->rx_fragments++;
+       sta->rx_bytes += rx->skb->len;
+       sta->last_rssi = (sta->last_rssi * 15 +
+                         rx->u.rx.status->ssi) / 16;
+       sta->last_signal = (sta->last_signal * 15 +
+                           rx->u.rx.status->signal) / 16;
+       sta->last_noise = (sta->last_noise * 15 +
+                          rx->u.rx.status->noise) / 16;
+
+       if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) {
+               /* Change STA power saving mode only in the end of a frame
+                * exchange sequence */
+               if ((sta->flags & WLAN_STA_PS) && !(rx->fc & IEEE80211_FCTL_PM))
+                       rx->u.rx.sent_ps_buffered += ap_sta_ps_end(dev, sta);
+               else if (!(sta->flags & WLAN_STA_PS) &&
+                        (rx->fc & IEEE80211_FCTL_PM))
+                       ap_sta_ps_start(dev, sta);
+       }
+
+       /* Drop data::nullfunc frames silently, since they are used only to
+        * control station power saving mode. */
+       if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
+           (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_NULLFUNC) {
+               I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc);
+               /* Update counter and free packet here to avoid counting this
+                * as a dropped packed. */
+               sta->rx_packets++;
+               dev_kfree_skb(rx->skb);
+               return TXRX_QUEUED;
+       }
+
+       return TXRX_CONTINUE;
+} /* ieee80211_rx_h_sta_process */
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_wep_weak_iv_detection(struct ieee80211_txrx_data *rx)
+{
+       if (!rx->sta || !(rx->fc & IEEE80211_FCTL_PROTECTED) ||
+           (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
+           !rx->key || rx->key->alg != ALG_WEP || !rx->u.rx.ra_match)
+               return TXRX_CONTINUE;
+
+       /* Check for weak IVs, if hwaccel did not remove IV from the frame */
+       if ((rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) ||
+           rx->key->force_sw_encrypt) {
+               u8 *iv = ieee80211_wep_is_weak_iv(rx->skb, rx->key);
+               if (iv) {
+                       rx->sta->wep_weak_iv_count++;
+               }
+       }
+
+       return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_wep_decrypt(struct ieee80211_txrx_data *rx)
+{
+       /* If the device handles decryption totally, skip this test */
+       if (rx->local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP)
+               return TXRX_CONTINUE;
+
+       if ((rx->key && rx->key->alg != ALG_WEP) ||
+           !(rx->fc & IEEE80211_FCTL_PROTECTED) ||
+           ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA &&
+            ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
+             (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH)))
+               return TXRX_CONTINUE;
+
+       if (!rx->key) {
+               printk(KERN_DEBUG "%s: RX WEP frame, but no key set\n",
+                      rx->dev->name);
+               return TXRX_DROP;
+       }
+
+       if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED) ||
+           rx->key->force_sw_encrypt) {
+               if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) {
+                       printk(KERN_DEBUG "%s: RX WEP frame, decrypt "
+                              "failed\n", rx->dev->name);
+                       return TXRX_DROP;
+               }
+       } else if (rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) {
+               ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key);
+               /* remove ICV */
+               skb_trim(rx->skb, rx->skb->len - 4);
+       }
+
+       return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_802_1x_pae(struct ieee80211_txrx_data *rx)
+{
+       if (rx->sdata->eapol && ieee80211_is_eapol(rx->skb) &&
+           rx->sdata->type != IEEE80211_IF_TYPE_STA && rx->u.rx.ra_match) {
+               /* Pass both encrypted and unencrypted EAPOL frames to user
+                * space for processing. */
+               if (!rx->local->apdev)
+                       return TXRX_DROP;
+               ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status,
+                                 ieee80211_msg_normal);
+               return TXRX_QUEUED;
+       }
+
+       if (unlikely(rx->sdata->ieee802_1x &&
+                    (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
+                    (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC &&
+                    (!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED)) &&
+                    !ieee80211_is_eapol(rx->skb))) {
+#ifdef CONFIG_MAC80211_DEBUG
+               struct ieee80211_hdr *hdr =
+                       (struct ieee80211_hdr *) rx->skb->data;
+               printk(KERN_DEBUG "%s: dropped frame from " MAC_FMT
+                      " (unauthorized port)\n", rx->dev->name,
+                      MAC_ARG(hdr->addr2));
+#endif /* CONFIG_MAC80211_DEBUG */
+               return TXRX_DROP;
+       }
+
+       return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_drop_unencrypted(struct ieee80211_txrx_data *rx)
+{
+       /*  If the device handles decryption totally, skip this test */
+       if (rx->local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP)
+               return TXRX_CONTINUE;
+
+       /* Drop unencrypted frames if key is set. */
+       if (unlikely(!(rx->fc & IEEE80211_FCTL_PROTECTED) &&
+                    (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
+                    (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC &&
+                    (rx->key || rx->sdata->drop_unencrypted) &&
+                    (rx->sdata->eapol == 0 ||
+                     !ieee80211_is_eapol(rx->skb)))) {
+               printk(KERN_DEBUG "%s: RX non-WEP frame, but expected "
+                      "encryption\n", rx->dev->name);
+               return TXRX_DROP;
+       }
+       return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_mgmt(struct ieee80211_txrx_data *rx)
+{
+       struct ieee80211_sub_if_data *sdata;
+
+       if (!rx->u.rx.ra_match)
+               return TXRX_DROP;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
+       if ((sdata->type == IEEE80211_IF_TYPE_STA ||
+            sdata->type == IEEE80211_IF_TYPE_IBSS) &&
+           !rx->local->user_space_mlme) {
+               ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status);
+       } else {
+               /* Management frames are sent to hostapd for processing */
+               if (!rx->local->apdev)
+                       return TXRX_DROP;
+               ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status,
+                                 ieee80211_msg_normal);
+       }
+       return TXRX_QUEUED;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_passive_scan(struct ieee80211_txrx_data *rx)
+{
+       struct ieee80211_local *local = rx->local;
+       struct sk_buff *skb = rx->skb;
+
+       if (unlikely(local->sta_scanning != 0)) {
+               ieee80211_sta_rx_scan(rx->dev, skb, rx->u.rx.status);
+               return TXRX_QUEUED;
+       }
+
+       if (unlikely(rx->u.rx.in_scan)) {
+               /* scanning finished during invoking of handlers */
+               I802_DEBUG_INC(local->rx_handlers_drop_passive_scan);
+               return TXRX_DROP;
+       }
+
+       return TXRX_CONTINUE;
+}
+
+
+static void ieee80211_rx_michael_mic_report(struct net_device *dev,
+                                           struct ieee80211_hdr *hdr,
+                                           struct sta_info *sta,
+                                           struct ieee80211_txrx_data *rx)
+{
+       int keyidx, hdrlen;
+
+       hdrlen = ieee80211_get_hdrlen_from_skb(rx->skb);
+       if (rx->skb->len >= hdrlen + 4)
+               keyidx = rx->skb->data[hdrlen + 3] >> 6;
+       else
+               keyidx = -1;
+
+       /* TODO: verify that this is not triggered by fragmented
+        * frames (hw does not verify MIC for them). */
+       printk(KERN_DEBUG "%s: TKIP hwaccel reported Michael MIC "
+              "failure from " MAC_FMT " to " MAC_FMT " keyidx=%d\n",
+              dev->name, MAC_ARG(hdr->addr2), MAC_ARG(hdr->addr1), keyidx);
+
+       if (!sta) {
+               /* Some hardware versions seem to generate incorrect
+                * Michael MIC reports; ignore them to avoid triggering
+                * countermeasures. */
+               printk(KERN_DEBUG "%s: ignored spurious Michael MIC "
+                      "error for unknown address " MAC_FMT "\n",
+                      dev->name, MAC_ARG(hdr->addr2));
+               goto ignore;
+       }
+
+       if (!(rx->fc & IEEE80211_FCTL_PROTECTED)) {
+               printk(KERN_DEBUG "%s: ignored spurious Michael MIC "
+                      "error for a frame with no ISWEP flag (src "
+                      MAC_FMT ")\n", dev->name, MAC_ARG(hdr->addr2));
+               goto ignore;
+       }
+
+       if ((rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) &&
+           rx->sdata->type == IEEE80211_IF_TYPE_AP) {
+               keyidx = ieee80211_wep_get_keyidx(rx->skb);
+               /* AP with Pairwise keys support should never receive Michael
+                * MIC errors for non-zero keyidx because these are reserved
+                * for group keys and only the AP is sending real multicast
+                * frames in BSS. */
+               if (keyidx) {
+                       printk(KERN_DEBUG "%s: ignored Michael MIC error for "
+                              "a frame with non-zero keyidx (%d) (src " MAC_FMT
+                              ")\n", dev->name, keyidx, MAC_ARG(hdr->addr2));
+                       goto ignore;
+               }
+       }
+
+       if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA &&
+           ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
+            (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH)) {
+               printk(KERN_DEBUG "%s: ignored spurious Michael MIC "
+                      "error for a frame that cannot be encrypted "
+                      "(fc=0x%04x) (src " MAC_FMT ")\n",
+                      dev->name, rx->fc, MAC_ARG(hdr->addr2));
+               goto ignore;
+       }
+
+       do {
+               union iwreq_data wrqu;
+               char *buf = kmalloc(128, GFP_ATOMIC);
+               if (!buf)
+                       break;
+
+               /* TODO: needed parameters: count, key type, TSC */
+               sprintf(buf, "MLME-MICHAELMICFAILURE.indication("
+                       "keyid=%d %scast addr=" MAC_FMT ")",
+                       keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
+                       MAC_ARG(hdr->addr2));
+               memset(&wrqu, 0, sizeof(wrqu));
+               wrqu.data.length = strlen(buf);
+               wireless_send_event(rx->dev, IWEVCUSTOM, &wrqu, buf);
+               kfree(buf);
+       } while (0);
+
+       /* TODO: consider verifying the MIC error report with software
+        * implementation if we get too many spurious reports from the
+        * hardware. */
+       if (!rx->local->apdev)
+               goto ignore;
+       ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status,
+                         ieee80211_msg_michael_mic_failure);
+       return;
+
+ ignore:
+       dev_kfree_skb(rx->skb);
+       rx->skb = NULL;
+}
+
+static inline ieee80211_txrx_result __ieee80211_invoke_rx_handlers(
+                               struct ieee80211_local *local,
+                               ieee80211_rx_handler *handlers,
+                               struct ieee80211_txrx_data *rx,
+                               struct sta_info *sta)
+{
+       ieee80211_rx_handler *handler;
+       ieee80211_txrx_result res = TXRX_DROP;
+
+       for (handler = handlers; *handler != NULL; handler++) {
+               res = (*handler)(rx);
+               if (res != TXRX_CONTINUE) {
+                       if (res == TXRX_DROP) {
+                               I802_DEBUG_INC(local->rx_handlers_drop);
+                               if (sta)
+                                       sta->rx_dropped++;
+                       }
+                       if (res == TXRX_QUEUED)
+                               I802_DEBUG_INC(local->rx_handlers_queued);
+                       break;
+               }
+       }
+
+       if (res == TXRX_DROP) {
+               dev_kfree_skb(rx->skb);
+       }
+       return res;
+}
+
+static inline void ieee80211_invoke_rx_handlers(struct ieee80211_local *local,
+                                               ieee80211_rx_handler *handlers,
+                                               struct ieee80211_txrx_data *rx,
+                                               struct sta_info *sta)
+{
+       if (__ieee80211_invoke_rx_handlers(local, handlers, rx, sta) ==
+           TXRX_CONTINUE)
+               dev_kfree_skb(rx->skb);
+}
+
+/*
+ * This is the receive path handler. It is called by a low level driver when an
+ * 802.11 MPDU is received from the hardware.
+ */
+void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
+                   struct ieee80211_rx_status *status)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+       struct ieee80211_sub_if_data *sdata;
+       struct sta_info *sta;
+       struct ieee80211_hdr *hdr;
+       struct ieee80211_txrx_data rx;
+       u16 type;
+       int multicast;
+       int radiotap_len = 0;
+
+       if (status->flag & RX_FLAG_RADIOTAP) {
+               radiotap_len = ieee80211_get_radiotap_len(skb);
+               skb_pull(skb, radiotap_len);
+       }
+
+       hdr = (struct ieee80211_hdr *) skb->data;
+       memset(&rx, 0, sizeof(rx));
+       rx.skb = skb;
+       rx.local = local;
+
+       rx.u.rx.status = status;
+       rx.fc = skb->len >= 2 ? le16_to_cpu(hdr->frame_control) : 0;
+       type = rx.fc & IEEE80211_FCTL_FTYPE;
+       if (type == IEEE80211_FTYPE_DATA || type == IEEE80211_FTYPE_MGMT)
+               local->dot11ReceivedFragmentCount++;
+       multicast = is_multicast_ether_addr(hdr->addr1);
+
+       if (skb->len >= 16)
+               sta = rx.sta = sta_info_get(local, hdr->addr2);
+       else
+               sta = rx.sta = NULL;
+
+       if (sta) {
+               rx.dev = sta->dev;
+               rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
+       }
+
+       if ((status->flag & RX_FLAG_MMIC_ERROR)) {
+               ieee80211_rx_michael_mic_report(local->mdev, hdr, sta, &rx);
+               goto end;
+       }
+
+       if (unlikely(local->sta_scanning))
+               rx.u.rx.in_scan = 1;
+
+       if (__ieee80211_invoke_rx_handlers(local, local->rx_pre_handlers, &rx,
+                                          sta) != TXRX_CONTINUE)
+               goto end;
+       skb = rx.skb;
+
+       skb_push(skb, radiotap_len);
+       if (sta && !sta->assoc_ap && !(sta->flags & WLAN_STA_WDS) &&
+           !local->iff_promiscs && !multicast) {
+               rx.u.rx.ra_match = 1;
+               ieee80211_invoke_rx_handlers(local, local->rx_handlers, &rx,
+                                            sta);
+       } else {
+               struct ieee80211_sub_if_data *prev = NULL;
+               struct sk_buff *skb_new;
+               u8 *bssid = ieee80211_get_bssid(hdr, skb->len - radiotap_len);
+
+               read_lock(&local->sub_if_lock);
+               list_for_each_entry(sdata, &local->sub_if_list, list) {
+                       rx.u.rx.ra_match = 1;
+                       switch (sdata->type) {
+                       case IEEE80211_IF_TYPE_STA:
+                               if (!bssid)
+                                       continue;
+                               if (!ieee80211_bssid_match(bssid,
+                                                       sdata->u.sta.bssid)) {
+                                       if (!rx.u.rx.in_scan)
+                                               continue;
+                                       rx.u.rx.ra_match = 0;
+                               } else if (!multicast &&
+                                          compare_ether_addr(sdata->dev->dev_addr,
+                                                             hdr->addr1) != 0) {
+                                       if (!sdata->promisc)
+                                               continue;
+                                       rx.u.rx.ra_match = 0;
+                               }
+                               break;
+                       case IEEE80211_IF_TYPE_IBSS:
+                               if (!bssid)
+                                       continue;
+                               if (!ieee80211_bssid_match(bssid,
+                                                       sdata->u.sta.bssid)) {
+                                       if (!rx.u.rx.in_scan)
+                                               continue;
+                                       rx.u.rx.ra_match = 0;
+                               } else if (!multicast &&
+                                          compare_ether_addr(sdata->dev->dev_addr,
+                                                             hdr->addr1) != 0) {
+                                       if (!sdata->promisc)
+                                               continue;
+                                       rx.u.rx.ra_match = 0;
+                               } else if (!sta)
+                                       sta = rx.sta =
+                                               ieee80211_ibss_add_sta(sdata->dev,
+                                                                      skb, bssid,
+                                                                      hdr->addr2);
+                               break;
+                       case IEEE80211_IF_TYPE_AP:
+                               if (!bssid) {
+                                       if (compare_ether_addr(sdata->dev->dev_addr,
+                                                              hdr->addr1) != 0)
+                                               continue;
+                               } else if (!ieee80211_bssid_match(bssid,
+                                                       sdata->dev->dev_addr)) {
+                                       if (!rx.u.rx.in_scan)
+                                               continue;
+                                       rx.u.rx.ra_match = 0;
+                               }
+                               if (sdata->dev == local->mdev &&
+                                   !rx.u.rx.in_scan)
+                                       /* do not receive anything via
+                                        * master device when not scanning */
+                                       continue;
+                               break;
+                       case IEEE80211_IF_TYPE_WDS:
+                               if (bssid ||
+                                   (rx.fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)
+                                       continue;
+                               if (compare_ether_addr(sdata->u.wds.remote_addr,
+                                                      hdr->addr2) != 0)
+                                       continue;
+                               break;
+                       }
+
+                       if (prev) {
+                               skb_new = skb_copy(skb, GFP_ATOMIC);
+                               if (!skb_new) {
+                                       if (net_ratelimit())
+                                               printk(KERN_DEBUG "%s: failed to copy "
+                                                      "multicast frame for %s",
+                                                      local->mdev->name, prev->dev->name);
+                                       continue;
+                               }
+                               rx.skb = skb_new;
+                               rx.dev = prev->dev;
+                               rx.sdata = prev;
+                               ieee80211_invoke_rx_handlers(local,
+                                                            local->rx_handlers,
+                                                            &rx, sta);
+                       }
+                       prev = sdata;
+               }
+               if (prev) {
+                       rx.skb = skb;
+                       rx.dev = prev->dev;
+                       rx.sdata = prev;
+                       ieee80211_invoke_rx_handlers(local, local->rx_handlers,
+                                                    &rx, sta);
+               } else
+                       dev_kfree_skb(skb);
+               read_unlock(&local->sub_if_lock);
+       }
+
+  end:
+       if (sta)
+               sta_info_put(sta);
+}
+EXPORT_SYMBOL(__ieee80211_rx);
+
+static ieee80211_txrx_result
+ieee80211_tx_h_load_stats(struct ieee80211_txrx_data *tx)
+{
+       struct ieee80211_local *local = tx->local;
+       struct ieee80211_hw_mode *mode = tx->u.tx.mode;
+       struct sk_buff *skb = tx->skb;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       u32 load = 0, hdrtime;
+
+       /* TODO: this could be part of tx_status handling, so that the number
+        * of retries would be known; TX rate should in that case be stored
+        * somewhere with the packet */
+
+       /* Estimate total channel use caused by this frame */
+
+       /* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values,
+        * 1 usec = 1/8 * (1080 / 10) = 13.5 */
+
+       if (mode->mode == MODE_IEEE80211A ||
+           mode->mode == MODE_ATHEROS_TURBO ||
+           mode->mode == MODE_ATHEROS_TURBOG ||
+           (mode->mode == MODE_IEEE80211G &&
+            tx->u.tx.rate->flags & IEEE80211_RATE_ERP))
+               hdrtime = CHAN_UTIL_HDR_SHORT;
+       else
+               hdrtime = CHAN_UTIL_HDR_LONG;
+
+       load = hdrtime;
+       if (!is_multicast_ether_addr(hdr->addr1))
+               load += hdrtime;
+
+       if (tx->u.tx.control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
+               load += 2 * hdrtime;
+       else if (tx->u.tx.control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
+               load += hdrtime;
+
+       load += skb->len * tx->u.tx.rate->rate_inv;
+
+       if (tx->u.tx.extra_frag) {
+               int i;
+               for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+                       load += 2 * hdrtime;
+                       load += tx->u.tx.extra_frag[i]->len *
+                               tx->u.tx.rate->rate;
+               }
+       }
+
+       /* Divide channel_use by 8 to avoid wrapping around the counter */
+       load >>= CHAN_UTIL_SHIFT;
+       local->channel_use_raw += load;
+       if (tx->sta)
+               tx->sta->channel_use_raw += load;
+       tx->sdata->channel_use_raw += load;
+
+       return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result
+ieee80211_rx_h_load_stats(struct ieee80211_txrx_data *rx)
+{
+       struct ieee80211_local *local = rx->local;
+       struct sk_buff *skb = rx->skb;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       u32 load = 0, hdrtime;
+       struct ieee80211_rate *rate;
+       struct ieee80211_hw_mode *mode = local->hw.conf.mode;
+       int i;
+
+       /* Estimate total channel use caused by this frame */
+
+       if (unlikely(mode->num_rates < 0))
+               return TXRX_CONTINUE;
+
+       rate = &mode->rates[0];
+       for (i = 0; i < mode->num_rates; i++) {
+               if (mode->rates[i].val == rx->u.rx.status->rate) {
+                       rate = &mode->rates[i];
+                       break;
+               }
+       }
+
+       /* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values,
+        * 1 usec = 1/8 * (1080 / 10) = 13.5 */
+
+       if (mode->mode == MODE_IEEE80211A ||
+           mode->mode == MODE_ATHEROS_TURBO ||
+           mode->mode == MODE_ATHEROS_TURBOG ||
+           (mode->mode == MODE_IEEE80211G &&
+            rate->flags & IEEE80211_RATE_ERP))
+               hdrtime = CHAN_UTIL_HDR_SHORT;
+       else
+               hdrtime = CHAN_UTIL_HDR_LONG;
+
+       load = hdrtime;
+       if (!is_multicast_ether_addr(hdr->addr1))
+               load += hdrtime;
+
+       load += skb->len * rate->rate_inv;
+
+       /* Divide channel_use by 8 to avoid wrapping around the counter */
+       load >>= CHAN_UTIL_SHIFT;
+       local->channel_use_raw += load;
+       if (rx->sta)
+               rx->sta->channel_use_raw += load;
+       rx->u.rx.load = load;
+
+       return TXRX_CONTINUE;
+}
+
+static ieee80211_txrx_result
+ieee80211_rx_h_if_stats(struct ieee80211_txrx_data *rx)
+{
+       rx->sdata->channel_use_raw += rx->u.rx.load;
+       return TXRX_CONTINUE;
+}
+
+static void ieee80211_stat_refresh(unsigned long data)
+{
+       struct ieee80211_local *local = (struct ieee80211_local *) data;
+       struct sta_info *sta;
+       struct ieee80211_sub_if_data *sdata;
+
+       if (!local->stat_time)
+               return;
+
+       /* go through all stations */
+       spin_lock_bh(&local->sta_lock);
+       list_for_each_entry(sta, &local->sta_list, list) {
+               sta->channel_use = (sta->channel_use_raw / local->stat_time) /
+                       CHAN_UTIL_PER_10MS;
+               sta->channel_use_raw = 0;
+       }
+       spin_unlock_bh(&local->sta_lock);
+
+       /* go through all subinterfaces */
+       read_lock(&local->sub_if_lock);
+       list_for_each_entry(sdata, &local->sub_if_list, list) {
+               sdata->channel_use = (sdata->channel_use_raw /
+                                     local->stat_time) / CHAN_UTIL_PER_10MS;
+               sdata->channel_use_raw = 0;
+       }
+       read_unlock(&local->sub_if_lock);
+
+       /* hardware interface */
+       local->channel_use = (local->channel_use_raw /
+                             local->stat_time) / CHAN_UTIL_PER_10MS;
+       local->channel_use_raw = 0;
+
+       local->stat_timer.expires = jiffies + HZ * local->stat_time / 100;
+       add_timer(&local->stat_timer);
+}
+
+
+/* This is a version of the rx handler that can be called from hard irq
+ * context. Post the skb on the queue and schedule the tasklet */
+void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb,
+                         struct ieee80211_rx_status *status)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+
+       BUILD_BUG_ON(sizeof(struct ieee80211_rx_status) > sizeof(skb->cb));
+
+       skb->dev = local->mdev;
+       /* copy status into skb->cb for use by tasklet */
+       memcpy(skb->cb, status, sizeof(*status));
+       skb->pkt_type = IEEE80211_RX_MSG;
+       skb_queue_tail(&local->skb_queue, skb);
+       tasklet_schedule(&local->tasklet);
+}
+EXPORT_SYMBOL(ieee80211_rx_irqsafe);
+
+void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
+                                struct sk_buff *skb,
+                                struct ieee80211_tx_status *status)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+       struct ieee80211_tx_status *saved;
+       int tmp;
+
+       skb->dev = local->mdev;
+       saved = kmalloc(sizeof(struct ieee80211_tx_status), GFP_ATOMIC);
+       if (unlikely(!saved)) {
+               if (net_ratelimit())
+                       printk(KERN_WARNING "%s: Not enough memory, "
+                              "dropping tx status", skb->dev->name);
+               /* should be dev_kfree_skb_irq, but due to this function being
+                * named _irqsafe instead of just _irq we can't be sure that
+                * people won't call it from non-irq contexts */
+               dev_kfree_skb_any(skb);
+               return;
+       }
+       memcpy(saved, status, sizeof(struct ieee80211_tx_status));
+       /* copy pointer to saved status into skb->cb for use by tasklet */
+       memcpy(skb->cb, &saved, sizeof(saved));
+
+       skb->pkt_type = IEEE80211_TX_STATUS_MSG;
+       skb_queue_tail(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS ?
+                      &local->skb_queue : &local->skb_queue_unreliable, skb);
+       tmp = skb_queue_len(&local->skb_queue) +
+               skb_queue_len(&local->skb_queue_unreliable);
+       while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT &&
+              (skb = skb_dequeue(&local->skb_queue_unreliable))) {
+               memcpy(&saved, skb->cb, sizeof(saved));
+               kfree(saved);
+               dev_kfree_skb_irq(skb);
+               tmp--;
+               I802_DEBUG_INC(local->tx_status_drop);
+       }
+       tasklet_schedule(&local->tasklet);
+}
+EXPORT_SYMBOL(ieee80211_tx_status_irqsafe);
+
+static void ieee80211_tasklet_handler(unsigned long data)
+{
+       struct ieee80211_local *local = (struct ieee80211_local *) data;
+       struct sk_buff *skb;
+       struct ieee80211_rx_status rx_status;
+       struct ieee80211_tx_status *tx_status;
+
+       while ((skb = skb_dequeue(&local->skb_queue)) ||
+              (skb = skb_dequeue(&local->skb_queue_unreliable))) {
+               switch (skb->pkt_type) {
+               case IEEE80211_RX_MSG:
+                       /* status is in skb->cb */
+                       memcpy(&rx_status, skb->cb, sizeof(rx_status));
+                       /* Clear skb->type in order to not confuse kernel
+                        * netstack. */
+                       skb->pkt_type = 0;
+                       __ieee80211_rx(local_to_hw(local), skb, &rx_status);
+                       break;
+               case IEEE80211_TX_STATUS_MSG:
+                       /* get pointer to saved status out of skb->cb */
+                       memcpy(&tx_status, skb->cb, sizeof(tx_status));
+                       skb->pkt_type = 0;
+                       ieee80211_tx_status(local_to_hw(local),
+                                           skb, tx_status);
+                       kfree(tx_status);
+                       break;
+               default: /* should never get here! */
+                       printk(KERN_ERR "%s: Unknown message type (%d)\n",
+                              local->mdev->name, skb->pkt_type);
+                       dev_kfree_skb(skb);
+                       break;
+               }
+       }
+}
+
+
+/* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to
+ * make a prepared TX frame (one that has been given to hw) to look like brand
+ * new IEEE 802.11 frame that is ready to go through TX processing again.
+ * Also, tx_packet_data in cb is restored from tx_control. */
+static void ieee80211_remove_tx_extra(struct ieee80211_local *local,
+                                     struct ieee80211_key *key,
+                                     struct sk_buff *skb,
+                                     struct ieee80211_tx_control *control)
+{
+       int hdrlen, iv_len, mic_len;
+       struct ieee80211_tx_packet_data *pkt_data;
+
+       pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
+       pkt_data->ifindex = control->ifindex;
+       pkt_data->mgmt_iface = (control->type == IEEE80211_IF_TYPE_MGMT);
+       pkt_data->req_tx_status = !!(control->flags & IEEE80211_TXCTL_REQ_TX_STATUS);
+       pkt_data->do_not_encrypt = !!(control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT);
+       pkt_data->requeue = !!(control->flags & IEEE80211_TXCTL_REQUEUE);
+       pkt_data->queue = control->queue;
+
+       hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+
+       if (!key)
+               goto no_key;
+
+       switch (key->alg) {
+       case ALG_WEP:
+               iv_len = WEP_IV_LEN;
+               mic_len = WEP_ICV_LEN;
+               break;
+       case ALG_TKIP:
+               iv_len = TKIP_IV_LEN;
+               mic_len = TKIP_ICV_LEN;
+               break;
+       case ALG_CCMP:
+               iv_len = CCMP_HDR_LEN;
+               mic_len = CCMP_MIC_LEN;
+               break;
+       default:
+               goto no_key;
+       }
+
+       if (skb->len >= mic_len && key->force_sw_encrypt)
+               skb_trim(skb, skb->len - mic_len);
+       if (skb->len >= iv_len && skb->len > hdrlen) {
+               memmove(skb->data + iv_len, skb->data, hdrlen);
+               skb_pull(skb, iv_len);
+       }
+
+no_key:
+       {
+               struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+               u16 fc = le16_to_cpu(hdr->frame_control);
+               if ((fc & 0x8C) == 0x88) /* QoS Control Field */ {
+                       fc &= ~IEEE80211_STYPE_QOS_DATA;
+                       hdr->frame_control = cpu_to_le16(fc);
+                       memmove(skb->data + 2, skb->data, hdrlen - 2);
+                       skb_pull(skb, 2);
+               }
+       }
+}
+
+
+void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
+                        struct ieee80211_tx_status *status)
+{
+       struct sk_buff *skb2;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       struct ieee80211_local *local = hw_to_local(hw);
+       u16 frag, type;
+       u32 msg_type;
+
+       if (!status) {
+               printk(KERN_ERR
+                      "%s: ieee80211_tx_status called with NULL status\n",
+                      local->mdev->name);
+               dev_kfree_skb(skb);
+               return;
+       }
+
+       if (status->excessive_retries) {
+               struct sta_info *sta;
+               sta = sta_info_get(local, hdr->addr1);
+               if (sta) {
+                       if (sta->flags & WLAN_STA_PS) {
+                               /* The STA is in power save mode, so assume
+                                * that this TX packet failed because of that.
+                                */
+                               status->excessive_retries = 0;
+                               status->flags |= IEEE80211_TX_STATUS_TX_FILTERED;
+                       }
+                       sta_info_put(sta);
+               }
+       }
+
+       if (status->flags & IEEE80211_TX_STATUS_TX_FILTERED) {
+               struct sta_info *sta;
+               sta = sta_info_get(local, hdr->addr1);
+               if (sta) {
+                       sta->tx_filtered_count++;
+
+                       /* Clear the TX filter mask for this STA when sending
+                        * the next packet. If the STA went to power save mode,
+                        * this will happen when it is waking up for the next
+                        * time. */
+                       sta->clear_dst_mask = 1;
+
+                       /* TODO: Is the WLAN_STA_PS flag always set here or is
+                        * the race between RX and TX status causing some
+                        * packets to be filtered out before 80211.o gets an
+                        * update for PS status? This seems to be the case, so
+                        * no changes are likely to be needed. */
+                       if (sta->flags & WLAN_STA_PS &&
+                           skb_queue_len(&sta->tx_filtered) <
+                           STA_MAX_TX_BUFFER) {
+                               ieee80211_remove_tx_extra(local, sta->key,
+                                                         skb,
+                                                         &status->control);
+                               skb_queue_tail(&sta->tx_filtered, skb);
+                       } else if (!(sta->flags & WLAN_STA_PS) &&
+                                  !(status->control.flags & IEEE80211_TXCTL_REQUEUE)) {
+                               /* Software retry the packet once */
+                               status->control.flags |= IEEE80211_TXCTL_REQUEUE;
+                               ieee80211_remove_tx_extra(local, sta->key,
+                                                         skb,
+                                                         &status->control);
+                               dev_queue_xmit(skb);
+                       } else {
+                               if (net_ratelimit()) {
+                                       printk(KERN_DEBUG "%s: dropped TX "
+                                              "filtered frame queue_len=%d "
+                                              "PS=%d @%lu\n",
+                                              local->mdev->name,
+                                              skb_queue_len(
+                                                      &sta->tx_filtered),
+                                              !!(sta->flags & WLAN_STA_PS),
+                                              jiffies);
+                               }
+                               dev_kfree_skb(skb);
+                       }
+                       sta_info_put(sta);
+                       return;
+               }
+       } else {
+               /* FIXME: STUPID to call this with both local and local->mdev */
+               rate_control_tx_status(local, local->mdev, skb, status);
+       }
+
+       ieee80211_led_tx(local, 0);
+
+       /* SNMP counters
+        * Fragments are passed to low-level drivers as separate skbs, so these
+        * are actually fragments, not frames. Update frame counters only for
+        * the first fragment of the frame. */
+
+       frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
+       type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE;
+
+       if (status->flags & IEEE80211_TX_STATUS_ACK) {
+               if (frag == 0) {
+                       local->dot11TransmittedFrameCount++;
+                       if (is_multicast_ether_addr(hdr->addr1))
+                               local->dot11MulticastTransmittedFrameCount++;
+                       if (status->retry_count > 0)
+                               local->dot11RetryCount++;
+                       if (status->retry_count > 1)
+                               local->dot11MultipleRetryCount++;
+               }
+
+               /* This counter shall be incremented for an acknowledged MPDU
+                * with an individual address in the address 1 field or an MPDU
+                * with a multicast address in the address 1 field of type Data
+                * or Management. */
+               if (!is_multicast_ether_addr(hdr->addr1) ||
+                   type == IEEE80211_FTYPE_DATA ||
+                   type == IEEE80211_FTYPE_MGMT)
+                       local->dot11TransmittedFragmentCount++;
+       } else {
+               if (frag == 0)
+                       local->dot11FailedCount++;
+       }
+
+       if (!(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS)
+           || unlikely(!local->apdev)) {
+               dev_kfree_skb(skb);
+               return;
+       }
+
+       msg_type = (status->flags & IEEE80211_TX_STATUS_ACK) ?
+               ieee80211_msg_tx_callback_ack : ieee80211_msg_tx_callback_fail;
+
+       /* skb was the original skb used for TX. Clone it and give the clone
+        * to netif_rx(). Free original skb. */
+       skb2 = skb_copy(skb, GFP_ATOMIC);
+       if (!skb2) {
+               dev_kfree_skb(skb);
+               return;
+       }
+       dev_kfree_skb(skb);
+       skb = skb2;
+
+       /* Send frame to hostapd */
+       ieee80211_rx_mgmt(local, skb, NULL, msg_type);
+}
+EXPORT_SYMBOL(ieee80211_tx_status);
+
+/* TODO: implement register/unregister functions for adding TX/RX handlers
+ * into ordered list */
+
+/* rx_pre handlers don't have dev and sdata fields available in
+ * ieee80211_txrx_data */
+static ieee80211_rx_handler ieee80211_rx_pre_handlers[] =
+{
+       ieee80211_rx_h_parse_qos,
+       ieee80211_rx_h_load_stats,
+       NULL
+};
+
+static ieee80211_rx_handler ieee80211_rx_handlers[] =
+{
+       ieee80211_rx_h_if_stats,
+       ieee80211_rx_h_monitor,
+       ieee80211_rx_h_passive_scan,
+       ieee80211_rx_h_check,
+       ieee80211_rx_h_sta_process,
+       ieee80211_rx_h_ccmp_decrypt,
+       ieee80211_rx_h_tkip_decrypt,
+       ieee80211_rx_h_wep_weak_iv_detection,
+       ieee80211_rx_h_wep_decrypt,
+       ieee80211_rx_h_defragment,
+       ieee80211_rx_h_ps_poll,
+       ieee80211_rx_h_michael_mic_verify,
+       /* this must be after decryption - so header is counted in MPDU mic
+        * must be before pae and data, so QOS_DATA format frames
+        * are not passed to user space by these functions
+        */
+       ieee80211_rx_h_remove_qos_control,
+       ieee80211_rx_h_802_1x_pae,
+       ieee80211_rx_h_drop_unencrypted,
+       ieee80211_rx_h_data,
+       ieee80211_rx_h_mgmt,
+       NULL
+};
+
+static ieee80211_tx_handler ieee80211_tx_handlers[] =
+{
+       ieee80211_tx_h_check_assoc,
+       ieee80211_tx_h_sequence,
+       ieee80211_tx_h_ps_buf,
+       ieee80211_tx_h_select_key,
+       ieee80211_tx_h_michael_mic_add,
+       ieee80211_tx_h_fragment,
+       ieee80211_tx_h_tkip_encrypt,
+       ieee80211_tx_h_ccmp_encrypt,
+       ieee80211_tx_h_wep_encrypt,
+       ieee80211_tx_h_rate_ctrl,
+       ieee80211_tx_h_misc,
+       ieee80211_tx_h_load_stats,
+       NULL
+};
+
+
+int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct sta_info *sta;
+
+       if (compare_ether_addr(remote_addr, sdata->u.wds.remote_addr) == 0)
+               return 0;
+
+       /* Create STA entry for the new peer */
+       sta = sta_info_add(local, dev, remote_addr, GFP_KERNEL);
+       if (!sta)
+               return -ENOMEM;
+       sta_info_put(sta);
+
+       /* Remove STA entry for the old peer */
+       sta = sta_info_get(local, sdata->u.wds.remote_addr);
+       if (sta) {
+               sta_info_put(sta);
+               sta_info_free(sta, 0);
+       } else {
+               printk(KERN_DEBUG "%s: could not find STA entry for WDS link "
+                      "peer " MAC_FMT "\n",
+                      dev->name, MAC_ARG(sdata->u.wds.remote_addr));
+       }
+
+       /* Update WDS link data */
+       memcpy(&sdata->u.wds.remote_addr, remote_addr, ETH_ALEN);
+
+       return 0;
+}
+
+/* Must not be called for mdev and apdev */
+void ieee80211_if_setup(struct net_device *dev)
+{
+       ether_setup(dev);
+       dev->hard_start_xmit = ieee80211_subif_start_xmit;
+       dev->wireless_handlers = &ieee80211_iw_handler_def;
+       dev->set_multicast_list = ieee80211_set_multicast_list;
+       dev->change_mtu = ieee80211_change_mtu;
+       dev->get_stats = ieee80211_get_stats;
+       dev->open = ieee80211_open;
+       dev->stop = ieee80211_stop;
+       dev->uninit = ieee80211_if_reinit;
+       dev->destructor = ieee80211_if_free;
+}
+
+void ieee80211_if_mgmt_setup(struct net_device *dev)
+{
+       ether_setup(dev);
+       dev->hard_start_xmit = ieee80211_mgmt_start_xmit;
+       dev->change_mtu = ieee80211_change_mtu_apdev;
+       dev->get_stats = ieee80211_get_stats;
+       dev->open = ieee80211_mgmt_open;
+       dev->stop = ieee80211_mgmt_stop;
+       dev->type = ARPHRD_IEEE80211_PRISM;
+       dev->hard_header_parse = header_parse_80211;
+       dev->uninit = ieee80211_if_reinit;
+       dev->destructor = ieee80211_if_free;
+}
+
+int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
+                                const char *name)
+{
+       struct rate_control_ref *ref, *old;
+
+       ASSERT_RTNL();
+       if (local->open_count || netif_running(local->mdev) ||
+           (local->apdev && netif_running(local->apdev)))
+               return -EBUSY;
+
+       ref = rate_control_alloc(name, local);
+       if (!ref) {
+               printk(KERN_WARNING "%s: Failed to select rate control "
+                      "algorithm\n", local->mdev->name);
+               return -ENOENT;
+       }
+
+       old = local->rate_ctrl;
+       local->rate_ctrl = ref;
+       if (old) {
+               rate_control_put(old);
+               sta_info_flush(local, NULL);
+       }
+
+       printk(KERN_DEBUG "%s: Selected rate control "
+              "algorithm '%s'\n", local->mdev->name,
+              ref->ops->name);
+
+
+       return 0;
+}
+
+static void rate_control_deinitialize(struct ieee80211_local *local)
+{
+       struct rate_control_ref *ref;
+
+       ref = local->rate_ctrl;
+       local->rate_ctrl = NULL;
+       rate_control_put(ref);
+}
+
+struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
+                                       const struct ieee80211_ops *ops)
+{
+       struct net_device *mdev;
+       struct ieee80211_local *local;
+       struct ieee80211_sub_if_data *sdata;
+       int priv_size;
+       struct wiphy *wiphy;
+
+       /* Ensure 32-byte alignment of our private data and hw private data.
+        * We use the wiphy priv data for both our ieee80211_local and for
+        * the driver's private data
+        *
+        * In memory it'll be like this:
+        *
+        * +-------------------------+
+        * | struct wiphy           |
+        * +-------------------------+
+        * | struct ieee80211_local  |
+        * +-------------------------+
+        * | driver's private data   |
+        * +-------------------------+
+        *
+        */
+       priv_size = ((sizeof(struct ieee80211_local) +
+                     NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST) +
+                   priv_data_len;
+
+       wiphy = wiphy_new(&mac80211_config_ops, priv_size);
+
+       if (!wiphy)
+               return NULL;
+
+       wiphy->privid = mac80211_wiphy_privid;
+
+       local = wiphy_priv(wiphy);
+       local->hw.wiphy = wiphy;
+
+       local->hw.priv = (char *)local +
+                        ((sizeof(struct ieee80211_local) +
+                          NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
+
+       local->ops = ops;
+
+       /* for now, mdev needs sub_if_data :/ */
+       mdev = alloc_netdev(sizeof(struct ieee80211_sub_if_data),
+                           "wmaster%d", ether_setup);
+       if (!mdev) {
+               wiphy_free(wiphy);
+               return NULL;
+       }
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(mdev);
+       mdev->ieee80211_ptr = &sdata->wdev;
+       sdata->wdev.wiphy = wiphy;
+
+       local->hw.queues = 1; /* default */
+
+       local->mdev = mdev;
+       local->rx_pre_handlers = ieee80211_rx_pre_handlers;
+       local->rx_handlers = ieee80211_rx_handlers;
+       local->tx_handlers = ieee80211_tx_handlers;
+
+       local->bridge_packets = 1;
+
+       local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
+       local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
+       local->short_retry_limit = 7;
+       local->long_retry_limit = 4;
+       local->hw.conf.radio_enabled = 1;
+       local->rate_ctrl_num_up = RATE_CONTROL_NUM_UP;
+       local->rate_ctrl_num_down = RATE_CONTROL_NUM_DOWN;
+
+       local->enabled_modes = (unsigned int) -1;
+
+       INIT_LIST_HEAD(&local->modes_list);
+
+       rwlock_init(&local->sub_if_lock);
+       INIT_LIST_HEAD(&local->sub_if_list);
+
+       INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work);
+       init_timer(&local->stat_timer);
+       local->stat_timer.function = ieee80211_stat_refresh;
+       local->stat_timer.data = (unsigned long) local;
+       ieee80211_rx_bss_list_init(mdev);
+
+       sta_info_init(local);
+
+       mdev->hard_start_xmit = ieee80211_master_start_xmit;
+       mdev->open = ieee80211_master_open;
+       mdev->stop = ieee80211_master_stop;
+       mdev->type = ARPHRD_IEEE80211;
+       mdev->hard_header_parse = header_parse_80211;
+
+       sdata->type = IEEE80211_IF_TYPE_AP;
+       sdata->dev = mdev;
+       sdata->local = local;
+       sdata->u.ap.force_unicast_rateidx = -1;
+       sdata->u.ap.max_ratectrl_rateidx = -1;
+       ieee80211_if_sdata_init(sdata);
+       list_add_tail(&sdata->list, &local->sub_if_list);
+
+       tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
+                    (unsigned long)local);
+       tasklet_disable(&local->tx_pending_tasklet);
+
+       tasklet_init(&local->tasklet,
+                    ieee80211_tasklet_handler,
+                    (unsigned long) local);
+       tasklet_disable(&local->tasklet);
+
+       skb_queue_head_init(&local->skb_queue);
+       skb_queue_head_init(&local->skb_queue_unreliable);
+
+       return local_to_hw(local);
+}
+EXPORT_SYMBOL(ieee80211_alloc_hw);
+
+int ieee80211_register_hw(struct ieee80211_hw *hw)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+       const char *name;
+       int result;
+
+       result = wiphy_register(local->hw.wiphy);
+       if (result < 0)
+               return result;
+
+       name = wiphy_dev(local->hw.wiphy)->driver->name;
+       local->hw.workqueue = create_singlethread_workqueue(name);
+       if (!local->hw.workqueue) {
+               result = -ENOMEM;
+               goto fail_workqueue;
+       }
+
+       debugfs_hw_add(local);
+
+       local->hw.conf.beacon_int = 1000;
+
+       local->wstats_flags |= local->hw.max_rssi ?
+                              IW_QUAL_LEVEL_UPDATED : IW_QUAL_LEVEL_INVALID;
+       local->wstats_flags |= local->hw.max_signal ?
+                              IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID;
+       local->wstats_flags |= local->hw.max_noise ?
+                              IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID;
+       if (local->hw.max_rssi < 0 || local->hw.max_noise < 0)
+               local->wstats_flags |= IW_QUAL_DBM;
+
+       result = sta_info_start(local);
+       if (result < 0)
+               goto fail_sta_info;
+
+       rtnl_lock();
+       result = dev_alloc_name(local->mdev, local->mdev->name);
+       if (result < 0)
+               goto fail_dev;
+
+       memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
+       SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy));
+
+       result = register_netdevice(local->mdev);
+       if (result < 0)
+               goto fail_dev;
+
+       ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
+
+       result = ieee80211_init_rate_ctrl_alg(local, NULL);
+       if (result < 0) {
+               printk(KERN_DEBUG "%s: Failed to initialize rate control "
+                      "algorithm\n", local->mdev->name);
+               goto fail_rate;
+       }
+
+       result = ieee80211_wep_init(local);
+
+       if (result < 0) {
+               printk(KERN_DEBUG "%s: Failed to initialize wep\n",
+                      local->mdev->name);
+               goto fail_wep;
+       }
+
+       ieee80211_install_qdisc(local->mdev);
+
+       /* add one default STA interface */
+       result = ieee80211_if_add(local->mdev, "wlan%d", NULL,
+                                 IEEE80211_IF_TYPE_STA);
+       if (result)
+               printk(KERN_WARNING "%s: Failed to add default virtual iface\n",
+                      local->mdev->name);
+
+       local->reg_state = IEEE80211_DEV_REGISTERED;
+       rtnl_unlock();
+
+       ieee80211_led_init(local);
+
+       return 0;
+
+fail_wep:
+       rate_control_deinitialize(local);
+fail_rate:
+       ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
+       unregister_netdevice(local->mdev);
+fail_dev:
+       rtnl_unlock();
+       sta_info_stop(local);
+fail_sta_info:
+       debugfs_hw_del(local);
+       destroy_workqueue(local->hw.workqueue);
+fail_workqueue:
+       wiphy_unregister(local->hw.wiphy);
+       return result;
+}
+EXPORT_SYMBOL(ieee80211_register_hw);
+
+int ieee80211_register_hwmode(struct ieee80211_hw *hw,
+                             struct ieee80211_hw_mode *mode)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+       struct ieee80211_rate *rate;
+       int i;
+
+       INIT_LIST_HEAD(&mode->list);
+       list_add_tail(&mode->list, &local->modes_list);
+
+       local->hw_modes |= (1 << mode->mode);
+       for (i = 0; i < mode->num_rates; i++) {
+               rate = &(mode->rates[i]);
+               rate->rate_inv = CHAN_UTIL_RATE_LCM / rate->rate;
+       }
+       ieee80211_prepare_rates(local, mode);
+
+       if (!local->oper_hw_mode) {
+               /* Default to this mode */
+               local->hw.conf.phymode = mode->mode;
+               local->oper_hw_mode = local->scan_hw_mode = mode;
+               local->oper_channel = local->scan_channel = &mode->channels[0];
+               local->hw.conf.mode = local->oper_hw_mode;
+               local->hw.conf.chan = local->oper_channel;
+       }
+
+       if (!(hw->flags & IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED))
+               ieee80211_init_client(local->mdev);
+
+       return 0;
+}
+EXPORT_SYMBOL(ieee80211_register_hwmode);
+
+void ieee80211_unregister_hw(struct ieee80211_hw *hw)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+       struct ieee80211_sub_if_data *sdata, *tmp;
+       struct list_head tmp_list;
+       int i;
+
+       tasklet_kill(&local->tx_pending_tasklet);
+       tasklet_kill(&local->tasklet);
+
+       rtnl_lock();
+
+       BUG_ON(local->reg_state != IEEE80211_DEV_REGISTERED);
+
+       local->reg_state = IEEE80211_DEV_UNREGISTERED;
+       if (local->apdev)
+               ieee80211_if_del_mgmt(local);
+
+       write_lock_bh(&local->sub_if_lock);
+       list_replace_init(&local->sub_if_list, &tmp_list);
+       write_unlock_bh(&local->sub_if_lock);
+
+       list_for_each_entry_safe(sdata, tmp, &tmp_list, list)
+               __ieee80211_if_del(local, sdata);
+
+       rtnl_unlock();
+
+       if (local->stat_time)
+               del_timer_sync(&local->stat_timer);
+
+       ieee80211_rx_bss_list_deinit(local->mdev);
+       ieee80211_clear_tx_pending(local);
+       sta_info_stop(local);
+       rate_control_deinitialize(local);
+       debugfs_hw_del(local);
+
+       for (i = 0; i < NUM_IEEE80211_MODES; i++) {
+               kfree(local->supp_rates[i]);
+               kfree(local->basic_rates[i]);
+       }
+
+       if (skb_queue_len(&local->skb_queue)
+                       || skb_queue_len(&local->skb_queue_unreliable))
+               printk(KERN_WARNING "%s: skb_queue not empty\n",
+                      local->mdev->name);
+       skb_queue_purge(&local->skb_queue);
+       skb_queue_purge(&local->skb_queue_unreliable);
+
+       destroy_workqueue(local->hw.workqueue);
+       wiphy_unregister(local->hw.wiphy);
+       ieee80211_wep_free(local);
+       ieee80211_led_exit(local);
+}
+EXPORT_SYMBOL(ieee80211_unregister_hw);
+
+void ieee80211_free_hw(struct ieee80211_hw *hw)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+
+       ieee80211_if_free(local->mdev);
+       wiphy_free(local->hw.wiphy);
+}
+EXPORT_SYMBOL(ieee80211_free_hw);
+
+void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+
+       if (test_and_clear_bit(IEEE80211_LINK_STATE_XOFF,
+                              &local->state[queue])) {
+               if (test_bit(IEEE80211_LINK_STATE_PENDING,
+                            &local->state[queue]))
+                       tasklet_schedule(&local->tx_pending_tasklet);
+               else
+                       if (!ieee80211_qdisc_installed(local->mdev)) {
+                               if (queue == 0)
+                                       netif_wake_queue(local->mdev);
+                       } else
+                               __netif_schedule(local->mdev);
+       }
+}
+EXPORT_SYMBOL(ieee80211_wake_queue);
+
+void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+
+       if (!ieee80211_qdisc_installed(local->mdev) && queue == 0)
+               netif_stop_queue(local->mdev);
+       set_bit(IEEE80211_LINK_STATE_XOFF, &local->state[queue]);
+}
+EXPORT_SYMBOL(ieee80211_stop_queue);
+
+void ieee80211_start_queues(struct ieee80211_hw *hw)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+       int i;
+
+       for (i = 0; i < local->hw.queues; i++)
+               clear_bit(IEEE80211_LINK_STATE_XOFF, &local->state[i]);
+       if (!ieee80211_qdisc_installed(local->mdev))
+               netif_start_queue(local->mdev);
+}
+EXPORT_SYMBOL(ieee80211_start_queues);
+
+void ieee80211_stop_queues(struct ieee80211_hw *hw)
+{
+       int i;
+
+       for (i = 0; i < hw->queues; i++)
+               ieee80211_stop_queue(hw, i);
+}
+EXPORT_SYMBOL(ieee80211_stop_queues);
+
+void ieee80211_wake_queues(struct ieee80211_hw *hw)
+{
+       int i;
+
+       for (i = 0; i < hw->queues; i++)
+               ieee80211_wake_queue(hw, i);
+}
+EXPORT_SYMBOL(ieee80211_wake_queues);
+
+struct net_device_stats *ieee80211_dev_stats(struct net_device *dev)
+{
+       struct ieee80211_sub_if_data *sdata;
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       return &sdata->stats;
+}
+
+static int __init ieee80211_init(void)
+{
+       struct sk_buff *skb;
+       int ret;
+
+       BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb));
+
+       ret = ieee80211_wme_register();
+       if (ret) {
+               printk(KERN_DEBUG "ieee80211_init: failed to "
+                      "initialize WME (err=%d)\n", ret);
+               return ret;
+       }
+
+       ieee80211_debugfs_netdev_init();
+
+       return 0;
+}
+
+
+static void __exit ieee80211_exit(void)
+{
+       ieee80211_wme_unregister();
+       ieee80211_debugfs_netdev_exit();
+}
+
+
+module_init(ieee80211_init);
+module_exit(ieee80211_exit);
+
+MODULE_DESCRIPTION("IEEE 802.11 subsystem");
+MODULE_LICENSE("GPL");
diff --git a/net/mac80211/ieee80211_cfg.c b/net/mac80211/ieee80211_cfg.c
new file mode 100644 (file)
index 0000000..509096e
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * mac80211 configuration hooks for cfg80211
+ *
+ * Copyright 2006      Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This file is GPLv2 as found in COPYING.
+ */
+
+#include <linux/nl80211.h>
+#include <linux/rtnetlink.h>
+#include <net/cfg80211.h>
+#include "ieee80211_i.h"
+#include "ieee80211_cfg.h"
+
+static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
+                              unsigned int type)
+{
+       struct ieee80211_local *local = wiphy_priv(wiphy);
+       int itype;
+
+       if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
+               return -ENODEV;
+
+       switch (type) {
+       case NL80211_IFTYPE_UNSPECIFIED:
+               itype = IEEE80211_IF_TYPE_STA;
+               break;
+       case NL80211_IFTYPE_ADHOC:
+               itype = IEEE80211_IF_TYPE_IBSS;
+               break;
+       case NL80211_IFTYPE_STATION:
+               itype = IEEE80211_IF_TYPE_STA;
+               break;
+       case NL80211_IFTYPE_MONITOR:
+               itype = IEEE80211_IF_TYPE_MNTR;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return ieee80211_if_add(local->mdev, name, NULL, itype);
+}
+
+static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
+{
+       struct ieee80211_local *local = wiphy_priv(wiphy);
+       struct net_device *dev;
+       char *name;
+
+       if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
+               return -ENODEV;
+
+       dev = dev_get_by_index(ifindex);
+       if (!dev)
+               return 0;
+
+       name = dev->name;
+       dev_put(dev);
+
+       return ieee80211_if_remove(local->mdev, name, -1);
+}
+
+struct cfg80211_ops mac80211_config_ops = {
+       .add_virtual_intf = ieee80211_add_iface,
+       .del_virtual_intf = ieee80211_del_iface,
+};
diff --git a/net/mac80211/ieee80211_cfg.h b/net/mac80211/ieee80211_cfg.h
new file mode 100644 (file)
index 0000000..85ed2c9
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * mac80211 configuration hooks for cfg80211
+ */
+#ifndef __IEEE80211_CFG_H
+#define __IEEE80211_CFG_H
+
+extern struct cfg80211_ops mac80211_config_ops;
+
+#endif /* __IEEE80211_CFG_H */
diff --git a/net/mac80211/ieee80211_common.h b/net/mac80211/ieee80211_common.h
new file mode 100644 (file)
index 0000000..b9a73e7
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * IEEE 802.11 driver (80211.o) -- hostapd interface
+ * Copyright 2002-2004, Instant802 Networks, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef IEEE80211_COMMON_H
+#define IEEE80211_COMMON_H
+
+#include <linux/types.h>
+
+/*
+ * This is common header information with user space. It is used on all
+ * frames sent to wlan#ap interface.
+ */
+
+#define IEEE80211_FI_VERSION 0x80211001
+
+struct ieee80211_frame_info {
+       __be32 version;
+       __be32 length;
+       __be64 mactime;
+       __be64 hosttime;
+       __be32 phytype;
+       __be32 channel;
+       __be32 datarate;
+       __be32 antenna;
+       __be32 priority;
+       __be32 ssi_type;
+       __be32 ssi_signal;
+       __be32 ssi_noise;
+       __be32 preamble;
+       __be32 encoding;
+
+       /* Note: this structure is otherwise identical to capture format used
+        * in linux-wlan-ng, but this additional field is used to provide meta
+        * data about the frame to hostapd. This was the easiest method for
+        * providing this information, but this might change in the future. */
+       __be32 msg_type;
+} __attribute__ ((packed));
+
+
+enum ieee80211_msg_type {
+       ieee80211_msg_normal = 0,
+       ieee80211_msg_tx_callback_ack = 1,
+       ieee80211_msg_tx_callback_fail = 2,
+       ieee80211_msg_passive_scan = 3,
+       ieee80211_msg_wep_frame_unknown_key = 4,
+       ieee80211_msg_michael_mic_failure = 5,
+       /* hole at 6, was monitor but never sent to userspace */
+       ieee80211_msg_sta_not_assoc = 7,
+       ieee80211_msg_set_aid_for_sta = 8 /* used by Intersil MVC driver */,
+       ieee80211_msg_key_threshold_notification = 9,
+       ieee80211_msg_radar = 11,
+};
+
+struct ieee80211_msg_set_aid_for_sta {
+       char    sta_address[ETH_ALEN];
+       u16     aid;
+};
+
+struct ieee80211_msg_key_notification {
+       int tx_rx_count;
+       char ifname[IFNAMSIZ];
+       u8 addr[ETH_ALEN]; /* ff:ff:ff:ff:ff:ff for broadcast keys */
+};
+
+
+enum ieee80211_phytype {
+       ieee80211_phytype_fhss_dot11_97  = 1,
+       ieee80211_phytype_dsss_dot11_97  = 2,
+       ieee80211_phytype_irbaseband     = 3,
+       ieee80211_phytype_dsss_dot11_b   = 4,
+       ieee80211_phytype_pbcc_dot11_b   = 5,
+       ieee80211_phytype_ofdm_dot11_g   = 6,
+       ieee80211_phytype_pbcc_dot11_g   = 7,
+       ieee80211_phytype_ofdm_dot11_a   = 8,
+       ieee80211_phytype_dsss_dot11_turbog = 255,
+       ieee80211_phytype_dsss_dot11_turbo = 256,
+};
+
+enum ieee80211_ssi_type {
+       ieee80211_ssi_none = 0,
+       ieee80211_ssi_norm = 1, /* normalized, 0-1000 */
+       ieee80211_ssi_dbm = 2,
+       ieee80211_ssi_raw = 3, /* raw SSI */
+};
+
+struct ieee80211_radar_info {
+               int channel;
+               int radar;
+               int radar_type;
+};
+
+#endif /* IEEE80211_COMMON_H */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
new file mode 100644 (file)
index 0000000..af4d14d
--- /dev/null
@@ -0,0 +1,798 @@
+/*
+ * Copyright 2002-2005, Instant802 Networks, Inc.
+ * Copyright 2005, Devicescape Software, Inc.
+ * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef IEEE80211_I_H
+#define IEEE80211_I_H
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/if_ether.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/workqueue.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <net/wireless.h>
+#include "ieee80211_key.h"
+#include "sta_info.h"
+
+/* ieee80211.o internal definitions, etc. These are not included into
+ * low-level drivers. */
+
+#ifndef ETH_P_PAE
+#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
+#endif /* ETH_P_PAE */
+
+#define WLAN_FC_DATA_PRESENT(fc) (((fc) & 0x4c) == 0x08)
+
+struct ieee80211_local;
+
+#define BIT(x) (1 << (x))
+
+#define IEEE80211_ALIGN32_PAD(a) ((4 - ((a) & 3)) & 3)
+
+/* Maximum number of broadcast/multicast frames to buffer when some of the
+ * associated stations are using power saving. */
+#define AP_MAX_BC_BUFFER 128
+
+/* Maximum number of frames buffered to all STAs, including multicast frames.
+ * Note: increasing this limit increases the potential memory requirement. Each
+ * frame can be up to about 2 kB long. */
+#define TOTAL_MAX_TX_BUFFER 512
+
+/* Required encryption head and tailroom */
+#define IEEE80211_ENCRYPT_HEADROOM 8
+#define IEEE80211_ENCRYPT_TAILROOM 12
+
+/* IEEE 802.11 (Ch. 9.5 Defragmentation) requires support for concurrent
+ * reception of at least three fragmented frames. This limit can be increased
+ * by changing this define, at the cost of slower frame reassembly and
+ * increased memory use (about 2 kB of RAM per entry). */
+#define IEEE80211_FRAGMENT_MAX 4
+
+struct ieee80211_fragment_entry {
+       unsigned long first_frag_time;
+       unsigned int seq;
+       unsigned int rx_queue;
+       unsigned int last_frag;
+       unsigned int extra_len;
+       struct sk_buff_head skb_list;
+       int ccmp; /* Whether fragments were encrypted with CCMP */
+       u8 last_pn[6]; /* PN of the last fragment if CCMP was used */
+};
+
+
+struct ieee80211_sta_bss {
+       struct list_head list;
+       struct ieee80211_sta_bss *hnext;
+       atomic_t users;
+
+       u8 bssid[ETH_ALEN];
+       u8 ssid[IEEE80211_MAX_SSID_LEN];
+       size_t ssid_len;
+       u16 capability; /* host byte order */
+       int hw_mode;
+       int channel;
+       int freq;
+       int rssi, signal, noise;
+       u8 *wpa_ie;
+       size_t wpa_ie_len;
+       u8 *rsn_ie;
+       size_t rsn_ie_len;
+       u8 *wmm_ie;
+       size_t wmm_ie_len;
+#define IEEE80211_MAX_SUPP_RATES 32
+       u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
+       size_t supp_rates_len;
+       int beacon_int;
+       u64 timestamp;
+
+       int probe_resp;
+       unsigned long last_update;
+
+};
+
+
+typedef enum {
+       TXRX_CONTINUE, TXRX_DROP, TXRX_QUEUED
+} ieee80211_txrx_result;
+
+struct ieee80211_txrx_data {
+       struct sk_buff *skb;
+       struct net_device *dev;
+       struct ieee80211_local *local;
+       struct ieee80211_sub_if_data *sdata;
+       struct sta_info *sta;
+       u16 fc, ethertype;
+       struct ieee80211_key *key;
+       unsigned int fragmented:1; /* whether the MSDU was fragmented */
+       union {
+               struct {
+                       struct ieee80211_tx_control *control;
+                       unsigned int unicast:1;
+                       unsigned int ps_buffered:1;
+                       unsigned int short_preamble:1;
+                       unsigned int probe_last_frag:1;
+                       struct ieee80211_hw_mode *mode;
+                       struct ieee80211_rate *rate;
+                       /* use this rate (if set) for last fragment; rate can
+                        * be set to lower rate for the first fragments, e.g.,
+                        * when using CTS protection with IEEE 802.11g. */
+                       struct ieee80211_rate *last_frag_rate;
+                       int last_frag_hwrate;
+                       int mgmt_interface;
+
+                       /* Extra fragments (in addition to the first fragment
+                        * in skb) */
+                       int num_extra_frag;
+                       struct sk_buff **extra_frag;
+               } tx;
+               struct {
+                       struct ieee80211_rx_status *status;
+                       int sent_ps_buffered;
+                       int queue;
+                       int load;
+                       unsigned int in_scan:1;
+                       /* frame is destined to interface currently processed
+                        * (including multicast frames) */
+                       unsigned int ra_match:1;
+               } rx;
+       } u;
+};
+
+/* Stored in sk_buff->cb */
+struct ieee80211_tx_packet_data {
+       int ifindex;
+       unsigned long jiffies;
+       unsigned int req_tx_status:1;
+       unsigned int do_not_encrypt:1;
+       unsigned int requeue:1;
+       unsigned int mgmt_iface:1;
+       unsigned int queue:4;
+};
+
+struct ieee80211_tx_stored_packet {
+       struct ieee80211_tx_control control;
+       struct sk_buff *skb;
+       int num_extra_frag;
+       struct sk_buff **extra_frag;
+       int last_frag_rateidx;
+       int last_frag_hwrate;
+       struct ieee80211_rate *last_frag_rate;
+       unsigned int last_frag_rate_ctrl_probe:1;
+};
+
+typedef ieee80211_txrx_result (*ieee80211_tx_handler)
+(struct ieee80211_txrx_data *tx);
+
+typedef ieee80211_txrx_result (*ieee80211_rx_handler)
+(struct ieee80211_txrx_data *rx);
+
+struct ieee80211_if_ap {
+       u8 *beacon_head, *beacon_tail;
+       int beacon_head_len, beacon_tail_len;
+
+       u8 ssid[IEEE80211_MAX_SSID_LEN];
+       size_t ssid_len;
+       u8 *generic_elem;
+       size_t generic_elem_len;
+
+       /* yes, this looks ugly, but guarantees that we can later use
+        * bitmap_empty :)
+        * NB: don't ever use set_bit, use bss_tim_set/bss_tim_clear! */
+       u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)];
+       atomic_t num_sta_ps; /* number of stations in PS mode */
+       struct sk_buff_head ps_bc_buf;
+       int dtim_period, dtim_count;
+       int force_unicast_rateidx; /* forced TX rateidx for unicast frames */
+       int max_ratectrl_rateidx; /* max TX rateidx for rate control */
+       int num_beacons; /* number of TXed beacon frames for this BSS */
+};
+
+struct ieee80211_if_wds {
+       u8 remote_addr[ETH_ALEN];
+       struct sta_info *sta;
+};
+
+struct ieee80211_if_vlan {
+       u8 id;
+};
+
+struct ieee80211_if_sta {
+       enum {
+               IEEE80211_DISABLED, IEEE80211_AUTHENTICATE,
+               IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED,
+               IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED
+       } state;
+       struct timer_list timer;
+       struct work_struct work;
+       u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
+       u8 ssid[IEEE80211_MAX_SSID_LEN];
+       size_t ssid_len;
+       u16 aid;
+       u16 ap_capab, capab;
+       u8 *extra_ie; /* to be added to the end of AssocReq */
+       size_t extra_ie_len;
+
+       /* The last AssocReq/Resp IEs */
+       u8 *assocreq_ies, *assocresp_ies;
+       size_t assocreq_ies_len, assocresp_ies_len;
+
+       int auth_tries, assoc_tries;
+
+       unsigned int ssid_set:1;
+       unsigned int bssid_set:1;
+       unsigned int prev_bssid_set:1;
+       unsigned int authenticated:1;
+       unsigned int associated:1;
+       unsigned int probereq_poll:1;
+       unsigned int use_protection:1;
+       unsigned int create_ibss:1;
+       unsigned int mixed_cell:1;
+       unsigned int wmm_enabled:1;
+       unsigned int auto_ssid_sel:1;
+       unsigned int auto_bssid_sel:1;
+       unsigned int auto_channel_sel:1;
+#define IEEE80211_STA_REQ_SCAN 0
+#define IEEE80211_STA_REQ_AUTH 1
+#define IEEE80211_STA_REQ_RUN  2
+       unsigned long request;
+       struct sk_buff_head skb_queue;
+
+       int key_mgmt;
+       unsigned long last_probe;
+
+#define IEEE80211_AUTH_ALG_OPEN BIT(0)
+#define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1)
+#define IEEE80211_AUTH_ALG_LEAP BIT(2)
+       unsigned int auth_algs; /* bitfield of allowed auth algs */
+       int auth_alg; /* currently used IEEE 802.11 authentication algorithm */
+       int auth_transaction;
+
+       unsigned long ibss_join_req;
+       struct sk_buff *probe_resp; /* ProbeResp template for IBSS */
+       u32 supp_rates_bits;
+
+       int wmm_last_param_set;
+};
+
+
+struct ieee80211_sub_if_data {
+       struct list_head list;
+       unsigned int type;
+
+       struct wireless_dev wdev;
+
+       struct net_device *dev;
+       struct ieee80211_local *local;
+
+       int mc_count;
+       unsigned int allmulti:1;
+       unsigned int promisc:1;
+
+       struct net_device_stats stats;
+       int drop_unencrypted;
+       int eapol; /* 0 = process EAPOL frames as normal data frames,
+                   * 1 = send EAPOL frames through wlan#ap to hostapd
+                   *     (default) */
+       int ieee802_1x; /* IEEE 802.1X PAE - drop packet to/from unauthorized
+                        * port */
+
+       u16 sequence;
+
+       /* Fragment table for host-based reassembly */
+       struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
+       unsigned int fragment_next;
+
+#define NUM_DEFAULT_KEYS 4
+       struct ieee80211_key *keys[NUM_DEFAULT_KEYS];
+       struct ieee80211_key *default_key;
+
+       struct ieee80211_if_ap *bss; /* BSS that this device belongs to */
+
+       union {
+               struct ieee80211_if_ap ap;
+               struct ieee80211_if_wds wds;
+               struct ieee80211_if_vlan vlan;
+               struct ieee80211_if_sta sta;
+       } u;
+       int channel_use;
+       int channel_use_raw;
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+       struct dentry *debugfsdir;
+       union {
+               struct {
+                       struct dentry *channel_use;
+                       struct dentry *drop_unencrypted;
+                       struct dentry *eapol;
+                       struct dentry *ieee8021_x;
+                       struct dentry *state;
+                       struct dentry *bssid;
+                       struct dentry *prev_bssid;
+                       struct dentry *ssid_len;
+                       struct dentry *aid;
+                       struct dentry *ap_capab;
+                       struct dentry *capab;
+                       struct dentry *extra_ie_len;
+                       struct dentry *auth_tries;
+                       struct dentry *assoc_tries;
+                       struct dentry *auth_algs;
+                       struct dentry *auth_alg;
+                       struct dentry *auth_transaction;
+                       struct dentry *flags;
+               } sta;
+               struct {
+                       struct dentry *channel_use;
+                       struct dentry *drop_unencrypted;
+                       struct dentry *eapol;
+                       struct dentry *ieee8021_x;
+                       struct dentry *num_sta_ps;
+                       struct dentry *dtim_period;
+                       struct dentry *dtim_count;
+                       struct dentry *num_beacons;
+                       struct dentry *force_unicast_rateidx;
+                       struct dentry *max_ratectrl_rateidx;
+                       struct dentry *num_buffered_multicast;
+                       struct dentry *beacon_head_len;
+                       struct dentry *beacon_tail_len;
+               } ap;
+               struct {
+                       struct dentry *channel_use;
+                       struct dentry *drop_unencrypted;
+                       struct dentry *eapol;
+                       struct dentry *ieee8021_x;
+                       struct dentry *peer;
+               } wds;
+               struct {
+                       struct dentry *channel_use;
+                       struct dentry *drop_unencrypted;
+                       struct dentry *eapol;
+                       struct dentry *ieee8021_x;
+                       struct dentry *vlan_id;
+               } vlan;
+               struct {
+                       struct dentry *mode;
+               } monitor;
+               struct dentry *default_key;
+       } debugfs;
+#endif
+};
+
+#define IEEE80211_DEV_TO_SUB_IF(dev) netdev_priv(dev)
+
+enum {
+       IEEE80211_RX_MSG        = 1,
+       IEEE80211_TX_STATUS_MSG = 2,
+};
+
+struct ieee80211_local {
+       /* embed the driver visible part.
+        * don't cast (use the static inlines below), but we keep
+        * it first anyway so they become a no-op */
+       struct ieee80211_hw hw;
+
+       const struct ieee80211_ops *ops;
+
+       /* List of registered struct ieee80211_hw_mode */
+       struct list_head modes_list;
+
+       struct net_device *mdev; /* wmaster# - "master" 802.11 device */
+       struct net_device *apdev; /* wlan#ap - management frames (hostapd) */
+       int open_count;
+       int monitors;
+       struct iw_statistics wstats;
+       u8 wstats_flags;
+
+       enum {
+               IEEE80211_DEV_UNINITIALIZED = 0,
+               IEEE80211_DEV_REGISTERED,
+               IEEE80211_DEV_UNREGISTERED,
+       } reg_state;
+
+       /* Tasklet and skb queue to process calls from IRQ mode. All frames
+        * added to skb_queue will be processed, but frames in
+        * skb_queue_unreliable may be dropped if the total length of these
+        * queues increases over the limit. */
+#define IEEE80211_IRQSAFE_QUEUE_LIMIT 128
+       struct tasklet_struct tasklet;
+       struct sk_buff_head skb_queue;
+       struct sk_buff_head skb_queue_unreliable;
+
+       /* Station data structures */
+       spinlock_t sta_lock; /* mutex for STA data structures */
+       int num_sta; /* number of stations in sta_list */
+       struct list_head sta_list;
+       struct list_head deleted_sta_list;
+       struct sta_info *sta_hash[STA_HASH_SIZE];
+       struct timer_list sta_cleanup;
+
+       unsigned long state[NUM_TX_DATA_QUEUES];
+       struct ieee80211_tx_stored_packet pending_packet[NUM_TX_DATA_QUEUES];
+       struct tasklet_struct tx_pending_tasklet;
+
+       int mc_count;   /* total count of multicast entries in all interfaces */
+       int iff_allmultis, iff_promiscs;
+                       /* number of interfaces with corresponding IFF_ flags */
+
+       struct rate_control_ref *rate_ctrl;
+
+       int next_mode; /* MODE_IEEE80211*
+                       * The mode preference for next channel change. This is
+                       * used to select .11g vs. .11b channels (or 4.9 GHz vs.
+                       * .11a) when the channel number is not unique. */
+
+       /* Supported and basic rate filters for different modes. These are
+        * pointers to -1 terminated lists and rates in 100 kbps units. */
+       int *supp_rates[NUM_IEEE80211_MODES];
+       int *basic_rates[NUM_IEEE80211_MODES];
+
+       int rts_threshold;
+       int cts_protect_erp_frames;
+       int fragmentation_threshold;
+       int short_retry_limit; /* dot11ShortRetryLimit */
+       int long_retry_limit; /* dot11LongRetryLimit */
+       int short_preamble; /* use short preamble with IEEE 802.11b */
+
+       struct crypto_blkcipher *wep_tx_tfm;
+       struct crypto_blkcipher *wep_rx_tfm;
+       u32 wep_iv;
+       int key_tx_rx_threshold; /* number of times any key can be used in TX
+                                 * or RX before generating a rekey
+                                 * notification; 0 = notification disabled. */
+
+       int bridge_packets; /* bridge packets between associated stations and
+                            * deliver multicast frames both back to wireless
+                            * media and to the local net stack */
+
+       ieee80211_rx_handler *rx_pre_handlers;
+       ieee80211_rx_handler *rx_handlers;
+       ieee80211_tx_handler *tx_handlers;
+
+       rwlock_t sub_if_lock; /* Protects sub_if_list. Cannot be taken under
+                              * sta_bss_lock or sta_lock. */
+       struct list_head sub_if_list;
+       int sta_scanning;
+       int scan_channel_idx;
+       enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state;
+       unsigned long last_scan_completed;
+       struct delayed_work scan_work;
+       struct net_device *scan_dev;
+       struct ieee80211_channel *oper_channel, *scan_channel;
+       struct ieee80211_hw_mode *oper_hw_mode, *scan_hw_mode;
+       u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
+       size_t scan_ssid_len;
+       struct list_head sta_bss_list;
+       struct ieee80211_sta_bss *sta_bss_hash[STA_HASH_SIZE];
+       spinlock_t sta_bss_lock;
+#define IEEE80211_SCAN_MATCH_SSID BIT(0)
+#define IEEE80211_SCAN_WPA_ONLY BIT(1)
+#define IEEE80211_SCAN_EXTRA_INFO BIT(2)
+       int scan_flags;
+
+       /* SNMP counters */
+       /* dot11CountersTable */
+       u32 dot11TransmittedFragmentCount;
+       u32 dot11MulticastTransmittedFrameCount;
+       u32 dot11FailedCount;
+       u32 dot11RetryCount;
+       u32 dot11MultipleRetryCount;
+       u32 dot11FrameDuplicateCount;
+       u32 dot11ReceivedFragmentCount;
+       u32 dot11MulticastReceivedFrameCount;
+       u32 dot11TransmittedFrameCount;
+       u32 dot11WEPUndecryptableCount;
+
+#ifdef CONFIG_MAC80211_LEDS
+       int tx_led_counter, rx_led_counter;
+       struct led_trigger *tx_led, *rx_led;
+       char tx_led_name[32], rx_led_name[32];
+#endif
+
+       u32 channel_use;
+       u32 channel_use_raw;
+       u32 stat_time;
+       struct timer_list stat_timer;
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+       struct work_struct sta_debugfs_add;
+#endif
+
+       enum {
+               STA_ANTENNA_SEL_AUTO = 0,
+               STA_ANTENNA_SEL_SW_CTRL = 1,
+               STA_ANTENNA_SEL_SW_CTRL_DEBUG = 2
+       } sta_antenna_sel;
+
+       int rate_ctrl_num_up, rate_ctrl_num_down;
+
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+       /* TX/RX handler statistics */
+       unsigned int tx_handlers_drop;
+       unsigned int tx_handlers_queued;
+       unsigned int tx_handlers_drop_unencrypted;
+       unsigned int tx_handlers_drop_fragment;
+       unsigned int tx_handlers_drop_wep;
+       unsigned int tx_handlers_drop_not_assoc;
+       unsigned int tx_handlers_drop_unauth_port;
+       unsigned int rx_handlers_drop;
+       unsigned int rx_handlers_queued;
+       unsigned int rx_handlers_drop_nullfunc;
+       unsigned int rx_handlers_drop_defrag;
+       unsigned int rx_handlers_drop_short;
+       unsigned int rx_handlers_drop_passive_scan;
+       unsigned int tx_expand_skb_head;
+       unsigned int tx_expand_skb_head_cloned;
+       unsigned int rx_expand_skb_head;
+       unsigned int rx_expand_skb_head2;
+       unsigned int rx_handlers_fragments;
+       unsigned int tx_status_drop;
+       unsigned int wme_rx_queue[NUM_RX_DATA_QUEUES];
+       unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES];
+#define I802_DEBUG_INC(c) (c)++
+#else /* CONFIG_MAC80211_DEBUG_COUNTERS */
+#define I802_DEBUG_INC(c) do { } while (0)
+#endif /* CONFIG_MAC80211_DEBUG_COUNTERS */
+
+
+       int default_wep_only; /* only default WEP keys are used with this
+                              * interface; this is used to decide when hwaccel
+                              * can be used with default keys */
+       int total_ps_buffered; /* total number of all buffered unicast and
+                               * multicast packets for power saving stations
+                               */
+       int allow_broadcast_always; /* whether to allow TX of broadcast frames
+                                    * even when there are no associated STAs
+                                    */
+
+       int wifi_wme_noack_test;
+       unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
+
+       unsigned int enabled_modes; /* bitfield of allowed modes;
+                                     * (1 << MODE_*) */
+       unsigned int hw_modes; /* bitfield of supported hardware modes;
+                               * (1 << MODE_*) */
+
+       int user_space_mlme;
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+       struct local_debugfsdentries {
+               struct dentry *channel;
+               struct dentry *frequency;
+               struct dentry *radar_detect;
+               struct dentry *antenna_sel_tx;
+               struct dentry *antenna_sel_rx;
+               struct dentry *bridge_packets;
+               struct dentry *key_tx_rx_threshold;
+               struct dentry *rts_threshold;
+               struct dentry *fragmentation_threshold;
+               struct dentry *short_retry_limit;
+               struct dentry *long_retry_limit;
+               struct dentry *total_ps_buffered;
+               struct dentry *mode;
+               struct dentry *wep_iv;
+               struct dentry *tx_power_reduction;
+               struct dentry *modes;
+               struct dentry *statistics;
+               struct local_debugfsdentries_statsdentries {
+                       struct dentry *transmitted_fragment_count;
+                       struct dentry *multicast_transmitted_frame_count;
+                       struct dentry *failed_count;
+                       struct dentry *retry_count;
+                       struct dentry *multiple_retry_count;
+                       struct dentry *frame_duplicate_count;
+                       struct dentry *received_fragment_count;
+                       struct dentry *multicast_received_frame_count;
+                       struct dentry *transmitted_frame_count;
+                       struct dentry *wep_undecryptable_count;
+                       struct dentry *num_scans;
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+                       struct dentry *tx_handlers_drop;
+                       struct dentry *tx_handlers_queued;
+                       struct dentry *tx_handlers_drop_unencrypted;
+                       struct dentry *tx_handlers_drop_fragment;
+                       struct dentry *tx_handlers_drop_wep;
+                       struct dentry *tx_handlers_drop_not_assoc;
+                       struct dentry *tx_handlers_drop_unauth_port;
+                       struct dentry *rx_handlers_drop;
+                       struct dentry *rx_handlers_queued;
+                       struct dentry *rx_handlers_drop_nullfunc;
+                       struct dentry *rx_handlers_drop_defrag;
+                       struct dentry *rx_handlers_drop_short;
+                       struct dentry *rx_handlers_drop_passive_scan;
+                       struct dentry *tx_expand_skb_head;
+                       struct dentry *tx_expand_skb_head_cloned;
+                       struct dentry *rx_expand_skb_head;
+                       struct dentry *rx_expand_skb_head2;
+                       struct dentry *rx_handlers_fragments;
+                       struct dentry *tx_status_drop;
+                       struct dentry *wme_tx_queue;
+                       struct dentry *wme_rx_queue;
+#endif
+                       struct dentry *dot11ACKFailureCount;
+                       struct dentry *dot11RTSFailureCount;
+                       struct dentry *dot11FCSErrorCount;
+                       struct dentry *dot11RTSSuccessCount;
+               } stats;
+               struct dentry *stations;
+               struct dentry *keys;
+       } debugfs;
+#endif
+};
+
+static inline struct ieee80211_local *hw_to_local(
+       struct ieee80211_hw *hw)
+{
+       return container_of(hw, struct ieee80211_local, hw);
+}
+
+static inline struct ieee80211_hw *local_to_hw(
+       struct ieee80211_local *local)
+{
+       return &local->hw;
+}
+
+enum ieee80211_link_state_t {
+       IEEE80211_LINK_STATE_XOFF = 0,
+       IEEE80211_LINK_STATE_PENDING,
+};
+
+struct sta_attribute {
+       struct attribute attr;
+       ssize_t (*show)(const struct sta_info *, char *buf);
+       ssize_t (*store)(struct sta_info *, const char *buf, size_t count);
+};
+
+static inline void __bss_tim_set(struct ieee80211_if_ap *bss, int aid)
+{
+       /*
+        * This format has ben mandated by the IEEE specifications,
+        * so this line may not be changed to use the __set_bit() format.
+        */
+       bss->tim[(aid)/8] |= 1<<((aid) % 8);
+}
+
+static inline void bss_tim_set(struct ieee80211_local *local,
+                              struct ieee80211_if_ap *bss, int aid)
+{
+       spin_lock_bh(&local->sta_lock);
+       __bss_tim_set(bss, aid);
+       spin_unlock_bh(&local->sta_lock);
+}
+
+static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, int aid)
+{
+       /*
+        * This format has ben mandated by the IEEE specifications,
+        * so this line may not be changed to use the __clear_bit() format.
+        */
+       bss->tim[(aid)/8] &= !(1<<((aid) % 8));
+}
+
+static inline void bss_tim_clear(struct ieee80211_local *local,
+                                struct ieee80211_if_ap *bss, int aid)
+{
+       spin_lock_bh(&local->sta_lock);
+       __bss_tim_clear(bss, aid);
+       spin_unlock_bh(&local->sta_lock);
+}
+
+/**
+ * ieee80211_is_erp_rate - Check if a rate is an ERP rate
+ * @phymode: The PHY-mode for this rate (MODE_IEEE80211...)
+ * @rate: Transmission rate to check, in 100 kbps
+ *
+ * Check if a given rate is an Extended Rate PHY (ERP) rate.
+ */
+static inline int ieee80211_is_erp_rate(int phymode, int rate)
+{
+       if (phymode == MODE_IEEE80211G) {
+               if (rate != 10 && rate != 20 &&
+                   rate != 55 && rate != 110)
+                       return 1;
+       }
+       return 0;
+}
+
+/* ieee80211.c */
+int ieee80211_hw_config(struct ieee80211_local *local);
+int ieee80211_if_config(struct net_device *dev);
+int ieee80211_if_config_beacon(struct net_device *dev);
+struct ieee80211_key_conf *
+ieee80211_key_data2conf(struct ieee80211_local *local,
+                       const struct ieee80211_key *data);
+struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
+                                         int idx, size_t key_len, gfp_t flags);
+void ieee80211_key_free(struct ieee80211_key *key);
+void ieee80211_rx_mgmt(struct ieee80211_local *local, struct sk_buff *skb,
+                      struct ieee80211_rx_status *status, u32 msg_type);
+void ieee80211_prepare_rates(struct ieee80211_local *local,
+                            struct ieee80211_hw_mode *mode);
+void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx);
+int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr);
+void ieee80211_if_setup(struct net_device *dev);
+void ieee80211_if_mgmt_setup(struct net_device *dev);
+int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
+                                const char *name);
+struct net_device_stats *ieee80211_dev_stats(struct net_device *dev);
+
+/* ieee80211_ioctl.c */
+extern const struct iw_handler_def ieee80211_iw_handler_def;
+
+void ieee80211_update_default_wep_only(struct ieee80211_local *local);
+
+
+/* Least common multiple of the used rates (in 100 kbps). This is used to
+ * calculate rate_inv values for each rate so that only integers are needed. */
+#define CHAN_UTIL_RATE_LCM 95040
+/* 1 usec is 1/8 * (95040/10) = 1188 */
+#define CHAN_UTIL_PER_USEC 1188
+/* Amount of bits to shift the result right to scale the total utilization
+ * to values that will not wrap around 32-bit integers. */
+#define CHAN_UTIL_SHIFT 9
+/* Theoretical maximum of channel utilization counter in 10 ms (stat_time=1):
+ * (CHAN_UTIL_PER_USEC * 10000) >> CHAN_UTIL_SHIFT = 23203. So dividing the
+ * raw value with about 23 should give utilization in 10th of a percentage
+ * (1/1000). However, utilization is only estimated and not all intervals
+ * between frames etc. are calculated. 18 seems to give numbers that are closer
+ * to the real maximum. */
+#define CHAN_UTIL_PER_10MS 18
+#define CHAN_UTIL_HDR_LONG (202 * CHAN_UTIL_PER_USEC)
+#define CHAN_UTIL_HDR_SHORT (40 * CHAN_UTIL_PER_USEC)
+
+
+/* ieee80211_ioctl.c */
+int ieee80211_set_compression(struct ieee80211_local *local,
+                             struct net_device *dev, struct sta_info *sta);
+int ieee80211_init_client(struct net_device *dev);
+int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq);
+/* ieee80211_sta.c */
+void ieee80211_sta_timer(unsigned long data);
+void ieee80211_sta_work(struct work_struct *work);
+void ieee80211_sta_scan_work(struct work_struct *work);
+void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
+                          struct ieee80211_rx_status *rx_status);
+int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len);
+int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len);
+int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid);
+int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len);
+void ieee80211_sta_req_auth(struct net_device *dev,
+                           struct ieee80211_if_sta *ifsta);
+int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len);
+void ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb,
+                          struct ieee80211_rx_status *rx_status);
+void ieee80211_rx_bss_list_init(struct net_device *dev);
+void ieee80211_rx_bss_list_deinit(struct net_device *dev);
+int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len);
+struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev,
+                                        struct sk_buff *skb, u8 *bssid,
+                                        u8 *addr);
+int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason);
+int ieee80211_sta_disassociate(struct net_device *dev, u16 reason);
+
+/* ieee80211_iface.c */
+int ieee80211_if_add(struct net_device *dev, const char *name,
+                    struct net_device **new_dev, int type);
+void ieee80211_if_set_type(struct net_device *dev, int type);
+void ieee80211_if_reinit(struct net_device *dev);
+void __ieee80211_if_del(struct ieee80211_local *local,
+                       struct ieee80211_sub_if_data *sdata);
+int ieee80211_if_remove(struct net_device *dev, const char *name, int id);
+void ieee80211_if_free(struct net_device *dev);
+void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata);
+int ieee80211_if_add_mgmt(struct ieee80211_local *local);
+void ieee80211_if_del_mgmt(struct ieee80211_local *local);
+
+/* for wiphy privid */
+extern void *mac80211_wiphy_privid;
+
+#endif /* IEEE80211_I_H */
diff --git a/net/mac80211/ieee80211_iface.c b/net/mac80211/ieee80211_iface.c
new file mode 100644 (file)
index 0000000..cf0f32e
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * Copyright 2002-2005, Instant802 Networks, Inc.
+ * Copyright 2005-2006, Devicescape Software, Inc.
+ * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/if_arp.h>
+#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+#include "sta_info.h"
+#include "debugfs_netdev.h"
+
+void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata)
+{
+       int i;
+
+       /* Default values for sub-interface parameters */
+       sdata->drop_unencrypted = 0;
+       sdata->eapol = 1;
+       for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
+               skb_queue_head_init(&sdata->fragments[i].skb_list);
+}
+
+static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata)
+{
+       int i;
+
+       for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
+               __skb_queue_purge(&sdata->fragments[i].skb_list);
+       }
+}
+
+/* Must be called with rtnl lock held. */
+int ieee80211_if_add(struct net_device *dev, const char *name,
+                    struct net_device **new_dev, int type)
+{
+       struct net_device *ndev;
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata = NULL;
+       int ret;
+
+       ASSERT_RTNL();
+       ndev = alloc_netdev(sizeof(struct ieee80211_sub_if_data),
+                           name, ieee80211_if_setup);
+       if (!ndev)
+               return -ENOMEM;
+
+       ret = dev_alloc_name(ndev, ndev->name);
+       if (ret < 0)
+               goto fail;
+
+       memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
+       ndev->base_addr = dev->base_addr;
+       ndev->irq = dev->irq;
+       ndev->mem_start = dev->mem_start;
+       ndev->mem_end = dev->mem_end;
+       SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
+       ndev->ieee80211_ptr = &sdata->wdev;
+       sdata->wdev.wiphy = local->hw.wiphy;
+       sdata->type = IEEE80211_IF_TYPE_AP;
+       sdata->dev = ndev;
+       sdata->local = local;
+       ieee80211_if_sdata_init(sdata);
+
+       ret = register_netdevice(ndev);
+       if (ret)
+               goto fail;
+
+       ieee80211_debugfs_add_netdev(sdata);
+       ieee80211_if_set_type(ndev, type);
+
+       write_lock_bh(&local->sub_if_lock);
+       if (unlikely(local->reg_state == IEEE80211_DEV_UNREGISTERED)) {
+               write_unlock_bh(&local->sub_if_lock);
+               __ieee80211_if_del(local, sdata);
+               return -ENODEV;
+       }
+       list_add(&sdata->list, &local->sub_if_list);
+       if (new_dev)
+               *new_dev = ndev;
+       write_unlock_bh(&local->sub_if_lock);
+
+       ieee80211_update_default_wep_only(local);
+
+       return 0;
+
+fail:
+       free_netdev(ndev);
+       return ret;
+}
+
+int ieee80211_if_add_mgmt(struct ieee80211_local *local)
+{
+       struct net_device *ndev;
+       struct ieee80211_sub_if_data *nsdata;
+       int ret;
+
+       ASSERT_RTNL();
+
+       ndev = alloc_netdev(sizeof(struct ieee80211_sub_if_data), "wmgmt%d",
+                           ieee80211_if_mgmt_setup);
+       if (!ndev)
+               return -ENOMEM;
+       ret = dev_alloc_name(ndev, ndev->name);
+       if (ret < 0)
+               goto fail;
+
+       memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
+       SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
+
+       nsdata = IEEE80211_DEV_TO_SUB_IF(ndev);
+       ndev->ieee80211_ptr = &nsdata->wdev;
+       nsdata->wdev.wiphy = local->hw.wiphy;
+       nsdata->type = IEEE80211_IF_TYPE_MGMT;
+       nsdata->dev = ndev;
+       nsdata->local = local;
+       ieee80211_if_sdata_init(nsdata);
+
+       ret = register_netdevice(ndev);
+       if (ret)
+               goto fail;
+
+       ieee80211_debugfs_add_netdev(nsdata);
+
+       if (local->open_count > 0)
+               dev_open(ndev);
+       local->apdev = ndev;
+       return 0;
+
+fail:
+       free_netdev(ndev);
+       return ret;
+}
+
+void ieee80211_if_del_mgmt(struct ieee80211_local *local)
+{
+       struct net_device *apdev;
+
+       ASSERT_RTNL();
+       apdev = local->apdev;
+       ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(apdev));
+       local->apdev = NULL;
+       unregister_netdevice(apdev);
+}
+
+void ieee80211_if_set_type(struct net_device *dev, int type)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       int oldtype = sdata->type;
+
+       sdata->type = type;
+       switch (type) {
+       case IEEE80211_IF_TYPE_WDS:
+               sdata->bss = NULL;
+               break;
+       case IEEE80211_IF_TYPE_VLAN:
+               break;
+       case IEEE80211_IF_TYPE_AP:
+               sdata->u.ap.dtim_period = 2;
+               sdata->u.ap.force_unicast_rateidx = -1;
+               sdata->u.ap.max_ratectrl_rateidx = -1;
+               skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
+               sdata->bss = &sdata->u.ap;
+               break;
+       case IEEE80211_IF_TYPE_STA:
+       case IEEE80211_IF_TYPE_IBSS: {
+               struct ieee80211_sub_if_data *msdata;
+               struct ieee80211_if_sta *ifsta;
+
+               ifsta = &sdata->u.sta;
+               INIT_WORK(&ifsta->work, ieee80211_sta_work);
+               setup_timer(&ifsta->timer, ieee80211_sta_timer,
+                           (unsigned long) sdata);
+               skb_queue_head_init(&ifsta->skb_queue);
+
+               ifsta->capab = WLAN_CAPABILITY_ESS;
+               ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN |
+                       IEEE80211_AUTH_ALG_SHARED_KEY;
+               ifsta->create_ibss = 1;
+               ifsta->wmm_enabled = 1;
+               ifsta->auto_channel_sel = 1;
+               ifsta->auto_bssid_sel = 1;
+
+               msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev);
+               sdata->bss = &msdata->u.ap;
+               break;
+       }
+       case IEEE80211_IF_TYPE_MNTR:
+               dev->type = ARPHRD_IEEE80211_RADIOTAP;
+               break;
+       default:
+               printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
+                      dev->name, __FUNCTION__, type);
+       }
+       ieee80211_debugfs_change_if_type(sdata, oldtype);
+       ieee80211_update_default_wep_only(local);
+}
+
+/* Must be called with rtnl lock held. */
+void ieee80211_if_reinit(struct net_device *dev)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct sta_info *sta;
+       int i;
+
+       ASSERT_RTNL();
+       ieee80211_if_sdata_deinit(sdata);
+       for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+               if (!sdata->keys[i])
+                       continue;
+#if 0
+               /* The interface is down at the moment, so there is not
+                * really much point in disabling the keys at this point. */
+               memset(addr, 0xff, ETH_ALEN);
+               if (local->ops->set_key)
+                       local->ops->set_key(local_to_hw(local), DISABLE_KEY, addr,
+                                           local->keys[i], 0);
+#endif
+               ieee80211_key_free(sdata->keys[i]);
+               sdata->keys[i] = NULL;
+       }
+
+       switch (sdata->type) {
+       case IEEE80211_IF_TYPE_AP: {
+               /* Remove all virtual interfaces that use this BSS
+                * as their sdata->bss */
+               struct ieee80211_sub_if_data *tsdata, *n;
+               LIST_HEAD(tmp_list);
+
+               write_lock_bh(&local->sub_if_lock);
+               list_for_each_entry_safe(tsdata, n, &local->sub_if_list, list) {
+                       if (tsdata != sdata && tsdata->bss == &sdata->u.ap) {
+                               printk(KERN_DEBUG "%s: removing virtual "
+                                      "interface %s because its BSS interface"
+                                      " is being removed\n",
+                                      sdata->dev->name, tsdata->dev->name);
+                               list_move_tail(&tsdata->list, &tmp_list);
+                       }
+               }
+               write_unlock_bh(&local->sub_if_lock);
+
+               list_for_each_entry_safe(tsdata, n, &tmp_list, list)
+                       __ieee80211_if_del(local, tsdata);
+
+               kfree(sdata->u.ap.beacon_head);
+               kfree(sdata->u.ap.beacon_tail);
+               kfree(sdata->u.ap.generic_elem);
+
+               if (dev != local->mdev) {
+                       struct sk_buff *skb;
+                       while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
+                               local->total_ps_buffered--;
+                               dev_kfree_skb(skb);
+                       }
+               }
+
+               break;
+       }
+       case IEEE80211_IF_TYPE_WDS:
+               sta = sta_info_get(local, sdata->u.wds.remote_addr);
+               if (sta) {
+                       sta_info_put(sta);
+                       sta_info_free(sta, 0);
+               } else {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+                       printk(KERN_DEBUG "%s: Someone had deleted my STA "
+                              "entry for the WDS link\n", dev->name);
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+               }
+               break;
+       case IEEE80211_IF_TYPE_STA:
+       case IEEE80211_IF_TYPE_IBSS:
+               kfree(sdata->u.sta.extra_ie);
+               sdata->u.sta.extra_ie = NULL;
+               kfree(sdata->u.sta.assocreq_ies);
+               sdata->u.sta.assocreq_ies = NULL;
+               kfree(sdata->u.sta.assocresp_ies);
+               sdata->u.sta.assocresp_ies = NULL;
+               if (sdata->u.sta.probe_resp) {
+                       dev_kfree_skb(sdata->u.sta.probe_resp);
+                       sdata->u.sta.probe_resp = NULL;
+               }
+
+               break;
+       case IEEE80211_IF_TYPE_MNTR:
+               dev->type = ARPHRD_ETHER;
+               break;
+       }
+
+       /* remove all STAs that are bound to this virtual interface */
+       sta_info_flush(local, dev);
+
+       memset(&sdata->u, 0, sizeof(sdata->u));
+       ieee80211_if_sdata_init(sdata);
+}
+
+/* Must be called with rtnl lock held. */
+void __ieee80211_if_del(struct ieee80211_local *local,
+                       struct ieee80211_sub_if_data *sdata)
+{
+       struct net_device *dev = sdata->dev;
+
+       ieee80211_debugfs_remove_netdev(sdata);
+       unregister_netdevice(dev);
+       /* Except master interface, the net_device will be freed by
+        * net_device->destructor (i. e. ieee80211_if_free). */
+}
+
+/* Must be called with rtnl lock held. */
+int ieee80211_if_remove(struct net_device *dev, const char *name, int id)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata, *n;
+
+       ASSERT_RTNL();
+
+       write_lock_bh(&local->sub_if_lock);
+       list_for_each_entry_safe(sdata, n, &local->sub_if_list, list) {
+               if ((sdata->type == id || id == -1) &&
+                   strcmp(name, sdata->dev->name) == 0 &&
+                   sdata->dev != local->mdev) {
+                       list_del(&sdata->list);
+                       write_unlock_bh(&local->sub_if_lock);
+                       __ieee80211_if_del(local, sdata);
+                       ieee80211_update_default_wep_only(local);
+                       return 0;
+               }
+       }
+       write_unlock_bh(&local->sub_if_lock);
+       return -ENODEV;
+}
+
+void ieee80211_if_free(struct net_device *dev)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+       /* local->apdev must be NULL when freeing management interface */
+       BUG_ON(dev == local->apdev);
+       ieee80211_if_sdata_deinit(sdata);
+       free_netdev(dev);
+}
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
new file mode 100644 (file)
index 0000000..352f03b
--- /dev/null
@@ -0,0 +1,1822 @@
+/*
+ * Copyright 2002-2005, Instant802 Networks, Inc.
+ * Copyright 2005-2006, Devicescape Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+#include <asm/uaccess.h>
+
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+#include "hostapd_ioctl.h"
+#include "ieee80211_rate.h"
+#include "wpa.h"
+#include "aes_ccm.h"
+#include "debugfs_key.h"
+
+static int ieee80211_regdom = 0x10; /* FCC */
+module_param(ieee80211_regdom, int, 0444);
+MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain; 64=MKK");
+
+/*
+ * If firmware is upgraded by the vendor, additional channels can be used based
+ * on the new Japanese regulatory rules. This is indicated by setting
+ * ieee80211_japan_5ghz module parameter to one when loading the 80211 kernel
+ * module.
+ */
+static int ieee80211_japan_5ghz /* = 0 */;
+module_param(ieee80211_japan_5ghz, int, 0444);
+MODULE_PARM_DESC(ieee80211_japan_5ghz, "Vendor-updated firmware for 5 GHz");
+
+static void ieee80211_set_hw_encryption(struct net_device *dev,
+                                       struct sta_info *sta, u8 addr[ETH_ALEN],
+                                       struct ieee80211_key *key)
+{
+       struct ieee80211_key_conf *keyconf = NULL;
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+       /* default to sw encryption; this will be cleared by low-level
+        * driver if the hw supports requested encryption */
+       if (key)
+               key->force_sw_encrypt = 1;
+
+       if (key && local->ops->set_key &&
+           (keyconf = ieee80211_key_data2conf(local, key))) {
+               if (local->ops->set_key(local_to_hw(local), SET_KEY, addr,
+                                      keyconf, sta ? sta->aid : 0)) {
+                       key->force_sw_encrypt = 1;
+                       key->hw_key_idx = HW_KEY_IDX_INVALID;
+               } else {
+                       key->force_sw_encrypt =
+                               !!(keyconf->flags & IEEE80211_KEY_FORCE_SW_ENCRYPT);
+                       key->hw_key_idx =
+                               keyconf->hw_key_idx;
+
+               }
+       }
+       kfree(keyconf);
+}
+
+
+static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
+                                   int idx, int alg, int set_tx_key,
+                                   const u8 *_key, size_t key_len)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       int ret = 0;
+       struct sta_info *sta;
+       struct ieee80211_key *key, *old_key;
+       int try_hwaccel = 1;
+       struct ieee80211_key_conf *keyconf;
+       struct ieee80211_sub_if_data *sdata;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+       if (is_broadcast_ether_addr(sta_addr)) {
+               sta = NULL;
+               if (idx >= NUM_DEFAULT_KEYS) {
+                       printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
+                              dev->name, idx);
+                       return -EINVAL;
+               }
+               key = sdata->keys[idx];
+
+               /* TODO: consider adding hwaccel support for these; at least
+                * Atheros key cache should be able to handle this since AP is
+                * only transmitting frames with default keys. */
+               /* FIX: hw key cache can be used when only one virtual
+                * STA is associated with each AP. If more than one STA
+                * is associated to the same AP, software encryption
+                * must be used. This should be done automatically
+                * based on configured station devices. For the time
+                * being, this can be only set at compile time. */
+       } else {
+               set_tx_key = 0;
+               if (idx != 0) {
+                       printk(KERN_DEBUG "%s: set_encrypt - non-zero idx for "
+                              "individual key\n", dev->name);
+                       return -EINVAL;
+               }
+
+               sta = sta_info_get(local, sta_addr);
+               if (!sta) {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+                       printk(KERN_DEBUG "%s: set_encrypt - unknown addr "
+                              MAC_FMT "\n",
+                              dev->name, MAC_ARG(sta_addr));
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+
+                       return -ENOENT;
+               }
+
+               key = sta->key;
+       }
+
+       /* FIX:
+        * Cannot configure default hwaccel keys with WEP algorithm, if
+        * any of the virtual interfaces is using static WEP
+        * configuration because hwaccel would otherwise try to decrypt
+        * these frames.
+        *
+        * For now, just disable WEP hwaccel for broadcast when there is
+        * possibility of conflict with default keys. This can maybe later be
+        * optimized by using non-default keys (at least with Atheros ar521x).
+        */
+       if (!sta && alg == ALG_WEP && !local->default_wep_only &&
+           sdata->type != IEEE80211_IF_TYPE_IBSS &&
+           sdata->type != IEEE80211_IF_TYPE_AP) {
+               try_hwaccel = 0;
+       }
+
+       if (local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP) {
+               /* Software encryption cannot be used with devices that hide
+                * encryption from the host system, so always try to use
+                * hardware acceleration with such devices. */
+               try_hwaccel = 1;
+       }
+
+       if ((local->hw.flags & IEEE80211_HW_NO_TKIP_WMM_HWACCEL) &&
+           alg == ALG_TKIP) {
+               if (sta && (sta->flags & WLAN_STA_WME)) {
+               /* Hardware does not support hwaccel with TKIP when using WMM.
+                */
+                       try_hwaccel = 0;
+               }
+               else if (sdata->type == IEEE80211_IF_TYPE_STA) {
+                       sta = sta_info_get(local, sdata->u.sta.bssid);
+                       if (sta) {
+                               if (sta->flags & WLAN_STA_WME) {
+                                       try_hwaccel = 0;
+                               }
+                               sta_info_put(sta);
+                               sta = NULL;
+                       }
+               }
+       }
+
+       if (alg == ALG_NONE) {
+               keyconf = NULL;
+               if (try_hwaccel && key &&
+                   key->hw_key_idx != HW_KEY_IDX_INVALID &&
+                   local->ops->set_key &&
+                   (keyconf = ieee80211_key_data2conf(local, key)) != NULL &&
+                   local->ops->set_key(local_to_hw(local), DISABLE_KEY,
+                                      sta_addr, keyconf, sta ? sta->aid : 0)) {
+                       printk(KERN_DEBUG "%s: set_encrypt - low-level disable"
+                              " failed\n", dev->name);
+                       ret = -EINVAL;
+               }
+               kfree(keyconf);
+
+               if (set_tx_key || sdata->default_key == key) {
+                       ieee80211_debugfs_key_remove_default(sdata);
+                       sdata->default_key = NULL;
+               }
+               ieee80211_debugfs_key_remove(key);
+               if (sta)
+                       sta->key = NULL;
+               else
+                       sdata->keys[idx] = NULL;
+               ieee80211_key_free(key);
+               key = NULL;
+       } else {
+               old_key = key;
+               key = ieee80211_key_alloc(sta ? NULL : sdata, idx, key_len,
+                                         GFP_KERNEL);
+               if (!key) {
+                       ret = -ENOMEM;
+                       goto err_out;
+               }
+
+               /* default to sw encryption; low-level driver sets these if the
+                * requested encryption is supported */
+               key->hw_key_idx = HW_KEY_IDX_INVALID;
+               key->force_sw_encrypt = 1;
+
+               key->alg = alg;
+               key->keyidx = idx;
+               key->keylen = key_len;
+               memcpy(key->key, _key, key_len);
+               if (set_tx_key)
+                       key->default_tx_key = 1;
+
+               if (alg == ALG_CCMP) {
+                       /* Initialize AES key state here as an optimization
+                        * so that it does not need to be initialized for every
+                        * packet. */
+                       key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(
+                               key->key);
+                       if (!key->u.ccmp.tfm) {
+                               ret = -ENOMEM;
+                               goto err_free;
+                       }
+               }
+
+               if (set_tx_key || sdata->default_key == old_key) {
+                       ieee80211_debugfs_key_remove_default(sdata);
+                       sdata->default_key = NULL;
+               }
+               ieee80211_debugfs_key_remove(old_key);
+               if (sta)
+                       sta->key = key;
+               else
+                       sdata->keys[idx] = key;
+               ieee80211_key_free(old_key);
+               ieee80211_debugfs_key_add(local, key);
+               if (sta)
+                       ieee80211_debugfs_key_sta_link(key, sta);
+
+               if (try_hwaccel &&
+                   (alg == ALG_WEP || alg == ALG_TKIP || alg == ALG_CCMP))
+                       ieee80211_set_hw_encryption(dev, sta, sta_addr, key);
+       }
+
+       if (set_tx_key || (!sta && !sdata->default_key && key)) {
+               sdata->default_key = key;
+               if (key)
+                       ieee80211_debugfs_key_add_default(sdata);
+
+               if (local->ops->set_key_idx &&
+                   local->ops->set_key_idx(local_to_hw(local), idx))
+                       printk(KERN_DEBUG "%s: failed to set TX key idx for "
+                              "low-level driver\n", dev->name);
+       }
+
+       if (sta)
+               sta_info_put(sta);
+
+       return 0;
+
+err_free:
+       ieee80211_key_free(key);
+err_out:
+       if (sta)
+               sta_info_put(sta);
+       return ret;
+}
+
+static int ieee80211_ioctl_siwgenie(struct net_device *dev,
+                                   struct iw_request_info *info,
+                                   struct iw_point *data, char *extra)
+{
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+       if (local->user_space_mlme)
+               return -EOPNOTSUPP;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       if (sdata->type == IEEE80211_IF_TYPE_STA ||
+           sdata->type == IEEE80211_IF_TYPE_IBSS) {
+               int ret = ieee80211_sta_set_extra_ie(dev, extra, data->length);
+               if (ret)
+                       return ret;
+               sdata->u.sta.auto_bssid_sel = 0;
+               ieee80211_sta_req_auth(dev, &sdata->u.sta);
+               return 0;
+       }
+
+       if (sdata->type == IEEE80211_IF_TYPE_AP) {
+               kfree(sdata->u.ap.generic_elem);
+               sdata->u.ap.generic_elem = kmalloc(data->length, GFP_KERNEL);
+               if (!sdata->u.ap.generic_elem)
+                       return -ENOMEM;
+               memcpy(sdata->u.ap.generic_elem, extra, data->length);
+               sdata->u.ap.generic_elem_len = data->length;
+               return ieee80211_if_config(dev);
+       }
+       return -EOPNOTSUPP;
+}
+
+static int ieee80211_ioctl_set_radio_enabled(struct net_device *dev,
+                                            int val)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_conf *conf = &local->hw.conf;
+
+       conf->radio_enabled = val;
+       return ieee80211_hw_config(wdev_priv(dev->ieee80211_ptr));
+}
+
+static int ieee80211_ioctl_giwname(struct net_device *dev,
+                                  struct iw_request_info *info,
+                                  char *name, char *extra)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+       switch (local->hw.conf.phymode) {
+       case MODE_IEEE80211A:
+               strcpy(name, "IEEE 802.11a");
+               break;
+       case MODE_IEEE80211B:
+               strcpy(name, "IEEE 802.11b");
+               break;
+       case MODE_IEEE80211G:
+               strcpy(name, "IEEE 802.11g");
+               break;
+       case MODE_ATHEROS_TURBO:
+               strcpy(name, "5GHz Turbo");
+               break;
+       default:
+               strcpy(name, "IEEE 802.11");
+               break;
+       }
+
+       return 0;
+}
+
+
+static int ieee80211_ioctl_giwrange(struct net_device *dev,
+                                struct iw_request_info *info,
+                                struct iw_point *data, char *extra)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct iw_range *range = (struct iw_range *) extra;
+
+       data->length = sizeof(struct iw_range);
+       memset(range, 0, sizeof(struct iw_range));
+
+       range->we_version_compiled = WIRELESS_EXT;
+       range->we_version_source = 21;
+       range->retry_capa = IW_RETRY_LIMIT;
+       range->retry_flags = IW_RETRY_LIMIT;
+       range->min_retry = 0;
+       range->max_retry = 255;
+       range->min_rts = 0;
+       range->max_rts = 2347;
+       range->min_frag = 256;
+       range->max_frag = 2346;
+
+       range->encoding_size[0] = 5;
+       range->encoding_size[1] = 13;
+       range->num_encoding_sizes = 2;
+       range->max_encoding_tokens = NUM_DEFAULT_KEYS;
+
+       range->max_qual.qual = local->hw.max_signal;
+       range->max_qual.level = local->hw.max_rssi;
+       range->max_qual.noise = local->hw.max_noise;
+       range->max_qual.updated = local->wstats_flags;
+
+       range->avg_qual.qual = local->hw.max_signal/2;
+       range->avg_qual.level = 0;
+       range->avg_qual.noise = 0;
+       range->avg_qual.updated = local->wstats_flags;
+
+       range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+                         IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+
+       IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
+       IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
+       IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
+       IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
+
+       return 0;
+}
+
+
+struct ieee80211_channel_range {
+       short start_freq;
+       short end_freq;
+       unsigned char power_level;
+       unsigned char antenna_max;
+};
+
+static const struct ieee80211_channel_range ieee80211_fcc_channels[] = {
+       { 2412, 2462, 27, 6 } /* IEEE 802.11b/g, channels 1..11 */,
+       { 5180, 5240, 17, 6 } /* IEEE 802.11a, channels 36..48 */,
+       { 5260, 5320, 23, 6 } /* IEEE 802.11a, channels 52..64 */,
+       { 5745, 5825, 30, 6 } /* IEEE 802.11a, channels 149..165, outdoor */,
+       { 0 }
+};
+
+static const struct ieee80211_channel_range ieee80211_mkk_channels[] = {
+       { 2412, 2472, 20, 6 } /* IEEE 802.11b/g, channels 1..13 */,
+       { 5170, 5240, 20, 6 } /* IEEE 802.11a, channels 34..48 */,
+       { 5260, 5320, 20, 6 } /* IEEE 802.11a, channels 52..64 */,
+       { 0 }
+};
+
+
+static const struct ieee80211_channel_range *channel_range =
+       ieee80211_fcc_channels;
+
+
+static void ieee80211_unmask_channel(struct net_device *dev, int mode,
+                                    struct ieee80211_channel *chan)
+{
+       int i;
+
+       chan->flag = 0;
+
+       if (ieee80211_regdom == 64 &&
+           (mode == MODE_ATHEROS_TURBO || mode == MODE_ATHEROS_TURBOG)) {
+               /* Do not allow Turbo modes in Japan. */
+               return;
+       }
+
+       for (i = 0; channel_range[i].start_freq; i++) {
+               const struct ieee80211_channel_range *r = &channel_range[i];
+               if (r->start_freq <= chan->freq && r->end_freq >= chan->freq) {
+                       if (ieee80211_regdom == 64 && !ieee80211_japan_5ghz &&
+                           chan->freq >= 5260 && chan->freq <= 5320) {
+                               /*
+                                * Skip new channels in Japan since the
+                                * firmware was not marked having been upgraded
+                                * by the vendor.
+                                */
+                               continue;
+                       }
+
+                       if (ieee80211_regdom == 0x10 &&
+                           (chan->freq == 5190 || chan->freq == 5210 ||
+                            chan->freq == 5230)) {
+                                   /* Skip MKK channels when in FCC domain. */
+                                   continue;
+                       }
+
+                       chan->flag |= IEEE80211_CHAN_W_SCAN |
+                               IEEE80211_CHAN_W_ACTIVE_SCAN |
+                               IEEE80211_CHAN_W_IBSS;
+                       chan->power_level = r->power_level;
+                       chan->antenna_max = r->antenna_max;
+
+                       if (ieee80211_regdom == 64 &&
+                           (chan->freq == 5170 || chan->freq == 5190 ||
+                            chan->freq == 5210 || chan->freq == 5230)) {
+                               /*
+                                * New regulatory rules in Japan have backwards
+                                * compatibility with old channels in 5.15-5.25
+                                * GHz band, but the station is not allowed to
+                                * use active scan on these old channels.
+                                */
+                               chan->flag &= ~IEEE80211_CHAN_W_ACTIVE_SCAN;
+                       }
+
+                       if (ieee80211_regdom == 64 &&
+                           (chan->freq == 5260 || chan->freq == 5280 ||
+                            chan->freq == 5300 || chan->freq == 5320)) {
+                               /*
+                                * IBSS is not allowed on 5.25-5.35 GHz band
+                                * due to radar detection requirements.
+                                */
+                               chan->flag &= ~IEEE80211_CHAN_W_IBSS;
+                       }
+
+                       break;
+               }
+       }
+}
+
+
+static int ieee80211_unmask_channels(struct net_device *dev)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_hw_mode *mode;
+       int c;
+
+       list_for_each_entry(mode, &local->modes_list, list) {
+               for (c = 0; c < mode->num_channels; c++) {
+                       ieee80211_unmask_channel(dev, mode->mode,
+                                                &mode->channels[c]);
+               }
+       }
+       return 0;
+}
+
+
+int ieee80211_init_client(struct net_device *dev)
+{
+       if (ieee80211_regdom == 0x40)
+               channel_range = ieee80211_mkk_channels;
+       ieee80211_unmask_channels(dev);
+       return 0;
+}
+
+
+static int ieee80211_ioctl_siwmode(struct net_device *dev,
+                                  struct iw_request_info *info,
+                                  __u32 *mode, char *extra)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       int type;
+
+       if (sdata->type == IEEE80211_IF_TYPE_VLAN)
+               return -EOPNOTSUPP;
+
+       switch (*mode) {
+       case IW_MODE_INFRA:
+               type = IEEE80211_IF_TYPE_STA;
+               break;
+       case IW_MODE_ADHOC:
+               type = IEEE80211_IF_TYPE_IBSS;
+               break;
+       case IW_MODE_MONITOR:
+               type = IEEE80211_IF_TYPE_MNTR;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (type == sdata->type)
+               return 0;
+       if (netif_running(dev))
+               return -EBUSY;
+
+       ieee80211_if_reinit(dev);
+       ieee80211_if_set_type(dev, type);
+
+       return 0;
+}
+
+
+static int ieee80211_ioctl_giwmode(struct net_device *dev,
+                                  struct iw_request_info *info,
+                                  __u32 *mode, char *extra)
+{
+       struct ieee80211_sub_if_data *sdata;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       switch (sdata->type) {
+       case IEEE80211_IF_TYPE_AP:
+               *mode = IW_MODE_MASTER;
+               break;
+       case IEEE80211_IF_TYPE_STA:
+               *mode = IW_MODE_INFRA;
+               break;
+       case IEEE80211_IF_TYPE_IBSS:
+               *mode = IW_MODE_ADHOC;
+               break;
+       case IEEE80211_IF_TYPE_MNTR:
+               *mode = IW_MODE_MONITOR;
+               break;
+       case IEEE80211_IF_TYPE_WDS:
+               *mode = IW_MODE_REPEAT;
+               break;
+       case IEEE80211_IF_TYPE_VLAN:
+               *mode = IW_MODE_SECOND;         /* FIXME */
+               break;
+       default:
+               *mode = IW_MODE_AUTO;
+               break;
+       }
+       return 0;
+}
+
+int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq)
+{
+       struct ieee80211_hw_mode *mode;
+       int c, set = 0;
+       int ret = -EINVAL;
+
+       list_for_each_entry(mode, &local->modes_list, list) {
+               if (!(local->enabled_modes & (1 << mode->mode)))
+                       continue;
+               for (c = 0; c < mode->num_channels; c++) {
+                       struct ieee80211_channel *chan = &mode->channels[c];
+                       if (chan->flag & IEEE80211_CHAN_W_SCAN &&
+                           ((chan->chan == channel) || (chan->freq == freq))) {
+                               /* Use next_mode as the mode preference to
+                                * resolve non-unique channel numbers. */
+                               if (set && mode->mode != local->next_mode)
+                                       continue;
+
+                               local->oper_channel = chan;
+                               local->oper_hw_mode = mode;
+                               set++;
+                       }
+               }
+       }
+
+       if (set) {
+               if (local->sta_scanning)
+                       ret = 0;
+               else
+                       ret = ieee80211_hw_config(local);
+
+               rate_control_clear(local);
+       }
+
+       return ret;
+}
+
+static int ieee80211_ioctl_siwfreq(struct net_device *dev,
+                                  struct iw_request_info *info,
+                                  struct iw_freq *freq, char *extra)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+       if (sdata->type == IEEE80211_IF_TYPE_STA)
+               sdata->u.sta.auto_channel_sel = 0;
+
+       /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
+       if (freq->e == 0) {
+               if (freq->m < 0) {
+                       if (sdata->type == IEEE80211_IF_TYPE_STA)
+                               sdata->u.sta.auto_channel_sel = 1;
+                       return 0;
+               } else
+                       return ieee80211_set_channel(local, freq->m, -1);
+       } else {
+               int i, div = 1000000;
+               for (i = 0; i < freq->e; i++)
+                       div /= 10;
+               if (div > 0)
+                       return ieee80211_set_channel(local, -1, freq->m / div);
+               else
+                       return -EINVAL;
+       }
+}
+
+
+static int ieee80211_ioctl_giwfreq(struct net_device *dev,
+                                  struct iw_request_info *info,
+                                  struct iw_freq *freq, char *extra)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+       /* TODO: in station mode (Managed/Ad-hoc) might need to poll low-level
+        * driver for the current channel with firmware-based management */
+
+       freq->m = local->hw.conf.freq;
+       freq->e = 6;
+
+       return 0;
+}
+
+
+static int ieee80211_ioctl_siwessid(struct net_device *dev,
+                                   struct iw_request_info *info,
+                                   struct iw_point *data, char *ssid)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata;
+       size_t len = data->length;
+
+       /* iwconfig uses nul termination in SSID.. */
+       if (len > 0 && ssid[len - 1] == '\0')
+               len--;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       if (sdata->type == IEEE80211_IF_TYPE_STA ||
+           sdata->type == IEEE80211_IF_TYPE_IBSS) {
+               int ret;
+               if (local->user_space_mlme) {
+                       if (len > IEEE80211_MAX_SSID_LEN)
+                               return -EINVAL;
+                       memcpy(sdata->u.sta.ssid, ssid, len);
+                       sdata->u.sta.ssid_len = len;
+                       return 0;
+               }
+               sdata->u.sta.auto_ssid_sel = !data->flags;
+               ret = ieee80211_sta_set_ssid(dev, ssid, len);
+               if (ret)
+                       return ret;
+               ieee80211_sta_req_auth(dev, &sdata->u.sta);
+               return 0;
+       }
+
+       if (sdata->type == IEEE80211_IF_TYPE_AP) {
+               memcpy(sdata->u.ap.ssid, ssid, len);
+               memset(sdata->u.ap.ssid + len, 0,
+                      IEEE80211_MAX_SSID_LEN - len);
+               sdata->u.ap.ssid_len = len;
+               return ieee80211_if_config(dev);
+       }
+       return -EOPNOTSUPP;
+}
+
+
+static int ieee80211_ioctl_giwessid(struct net_device *dev,
+                                   struct iw_request_info *info,
+                                   struct iw_point *data, char *ssid)
+{
+       size_t len;
+
+       struct ieee80211_sub_if_data *sdata;
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       if (sdata->type == IEEE80211_IF_TYPE_STA ||
+           sdata->type == IEEE80211_IF_TYPE_IBSS) {
+               int res = ieee80211_sta_get_ssid(dev, ssid, &len);
+               if (res == 0) {
+                       data->length = len;
+                       data->flags = 1;
+               } else
+                       data->flags = 0;
+               return res;
+       }
+
+       if (sdata->type == IEEE80211_IF_TYPE_AP) {
+               len = sdata->u.ap.ssid_len;
+               if (len > IW_ESSID_MAX_SIZE)
+                       len = IW_ESSID_MAX_SIZE;
+               memcpy(ssid, sdata->u.ap.ssid, len);
+               data->length = len;
+               data->flags = 1;
+               return 0;
+       }
+       return -EOPNOTSUPP;
+}
+
+
+static int ieee80211_ioctl_siwap(struct net_device *dev,
+                                struct iw_request_info *info,
+                                struct sockaddr *ap_addr, char *extra)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       if (sdata->type == IEEE80211_IF_TYPE_STA ||
+           sdata->type == IEEE80211_IF_TYPE_IBSS) {
+               int ret;
+               if (local->user_space_mlme) {
+                       memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data,
+                              ETH_ALEN);
+                       return 0;
+               }
+               if (is_zero_ether_addr((u8 *) &ap_addr->sa_data)) {
+                       sdata->u.sta.auto_bssid_sel = 1;
+                       sdata->u.sta.auto_channel_sel = 1;
+               } else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
+                       sdata->u.sta.auto_bssid_sel = 1;
+               else
+                       sdata->u.sta.auto_bssid_sel = 0;
+               ret = ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data);
+               if (ret)
+                       return ret;
+               ieee80211_sta_req_auth(dev, &sdata->u.sta);
+               return 0;
+       } else if (sdata->type == IEEE80211_IF_TYPE_WDS) {
+               if (memcmp(sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
+                          ETH_ALEN) == 0)
+                       return 0;
+               return ieee80211_if_update_wds(dev, (u8 *) &ap_addr->sa_data);
+       }
+
+       return -EOPNOTSUPP;
+}
+
+
+static int ieee80211_ioctl_giwap(struct net_device *dev,
+                                struct iw_request_info *info,
+                                struct sockaddr *ap_addr, char *extra)
+{
+       struct ieee80211_sub_if_data *sdata;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       if (sdata->type == IEEE80211_IF_TYPE_STA ||
+           sdata->type == IEEE80211_IF_TYPE_IBSS) {
+               ap_addr->sa_family = ARPHRD_ETHER;
+               memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN);
+               return 0;
+       } else if (sdata->type == IEEE80211_IF_TYPE_WDS) {
+               ap_addr->sa_family = ARPHRD_ETHER;
+               memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
+               return 0;
+       }
+
+       return -EOPNOTSUPP;
+}
+
+
+static int ieee80211_ioctl_siwscan(struct net_device *dev,
+                                  struct iw_request_info *info,
+                                  struct iw_point *data, char *extra)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       u8 *ssid = NULL;
+       size_t ssid_len = 0;
+
+       if (!netif_running(dev))
+               return -ENETDOWN;
+
+       if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) {
+               if (sdata->type == IEEE80211_IF_TYPE_STA ||
+                   sdata->type == IEEE80211_IF_TYPE_IBSS) {
+                       ssid = sdata->u.sta.ssid;
+                       ssid_len = sdata->u.sta.ssid_len;
+               } else if (sdata->type == IEEE80211_IF_TYPE_AP) {
+                       ssid = sdata->u.ap.ssid;
+                       ssid_len = sdata->u.ap.ssid_len;
+               } else
+                       return -EINVAL;
+       }
+       return ieee80211_sta_req_scan(dev, ssid, ssid_len);
+}
+
+
+static int ieee80211_ioctl_giwscan(struct net_device *dev,
+                                  struct iw_request_info *info,
+                                  struct iw_point *data, char *extra)
+{
+       int res;
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       if (local->sta_scanning)
+               return -EAGAIN;
+       res = ieee80211_sta_scan_results(dev, extra, data->length);
+       if (res >= 0) {
+               data->length = res;
+               return 0;
+       }
+       data->length = 0;
+       return res;
+}
+
+
+static int ieee80211_ioctl_siwrts(struct net_device *dev,
+                                 struct iw_request_info *info,
+                                 struct iw_param *rts, char *extra)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+       if (rts->disabled)
+               local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
+       else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD)
+               return -EINVAL;
+       else
+               local->rts_threshold = rts->value;
+
+       /* If the wlan card performs RTS/CTS in hardware/firmware,
+        * configure it here */
+
+       if (local->ops->set_rts_threshold)
+               local->ops->set_rts_threshold(local_to_hw(local),
+                                            local->rts_threshold);
+
+       return 0;
+}
+
+static int ieee80211_ioctl_giwrts(struct net_device *dev,
+                                 struct iw_request_info *info,
+                                 struct iw_param *rts, char *extra)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+       rts->value = local->rts_threshold;
+       rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD);
+       rts->fixed = 1;
+
+       return 0;
+}
+
+
+static int ieee80211_ioctl_siwfrag(struct net_device *dev,
+                                  struct iw_request_info *info,
+                                  struct iw_param *frag, char *extra)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+       if (frag->disabled)
+               local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
+       else if (frag->value < 256 ||
+                frag->value > IEEE80211_MAX_FRAG_THRESHOLD)
+               return -EINVAL;
+       else {
+               /* Fragment length must be even, so strip LSB. */
+               local->fragmentation_threshold = frag->value & ~0x1;
+       }
+
+       /* If the wlan card performs fragmentation in hardware/firmware,
+        * configure it here */
+
+       if (local->ops->set_frag_threshold)
+               local->ops->set_frag_threshold(
+                       local_to_hw(local),
+                       local->fragmentation_threshold);
+
+       return 0;
+}
+
+static int ieee80211_ioctl_giwfrag(struct net_device *dev,
+                                  struct iw_request_info *info,
+                                  struct iw_param *frag, char *extra)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+       frag->value = local->fragmentation_threshold;
+       frag->disabled = (frag->value >= IEEE80211_MAX_RTS_THRESHOLD);
+       frag->fixed = 1;
+
+       return 0;
+}
+
+
+static int ieee80211_ioctl_siwretry(struct net_device *dev,
+                                   struct iw_request_info *info,
+                                   struct iw_param *retry, char *extra)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+       if (retry->disabled ||
+           (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
+               return -EINVAL;
+
+       if (retry->flags & IW_RETRY_MAX)
+               local->long_retry_limit = retry->value;
+       else if (retry->flags & IW_RETRY_MIN)
+               local->short_retry_limit = retry->value;
+       else {
+               local->long_retry_limit = retry->value;
+               local->short_retry_limit = retry->value;
+       }
+
+       if (local->ops->set_retry_limit) {
+               return local->ops->set_retry_limit(
+                       local_to_hw(local),
+                       local->short_retry_limit,
+                       local->long_retry_limit);
+       }
+
+       return 0;
+}
+
+
+static int ieee80211_ioctl_giwretry(struct net_device *dev,
+                                   struct iw_request_info *info,
+                                   struct iw_param *retry, char *extra)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+       retry->disabled = 0;
+       if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) {
+               /* first return min value, iwconfig will ask max value
+                * later if needed */
+               retry->flags |= IW_RETRY_LIMIT;
+               retry->value = local->short_retry_limit;
+               if (local->long_retry_limit != local->short_retry_limit)
+                       retry->flags |= IW_RETRY_MIN;
+               return 0;
+       }
+       if (retry->flags & IW_RETRY_MAX) {
+               retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+               retry->value = local->long_retry_limit;
+       }
+
+       return 0;
+}
+
+static int ieee80211_ioctl_clear_keys(struct net_device *dev)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_key_conf key;
+       int i;
+       u8 addr[ETH_ALEN];
+       struct ieee80211_key_conf *keyconf;
+       struct ieee80211_sub_if_data *sdata;
+       struct sta_info *sta;
+
+       memset(addr, 0xff, ETH_ALEN);
+       read_lock(&local->sub_if_lock);
+       list_for_each_entry(sdata, &local->sub_if_list, list) {
+               for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+                       keyconf = NULL;
+                       if (sdata->keys[i] &&
+                           !sdata->keys[i]->force_sw_encrypt &&
+                           local->ops->set_key &&
+                           (keyconf = ieee80211_key_data2conf(local,
+                                                              sdata->keys[i])))
+                               local->ops->set_key(local_to_hw(local),
+                                                  DISABLE_KEY, addr,
+                                                  keyconf, 0);
+                       kfree(keyconf);
+                       ieee80211_key_free(sdata->keys[i]);
+                       sdata->keys[i] = NULL;
+               }
+               sdata->default_key = NULL;
+       }
+       read_unlock(&local->sub_if_lock);
+
+       spin_lock_bh(&local->sta_lock);
+       list_for_each_entry(sta, &local->sta_list, list) {
+               keyconf = NULL;
+               if (sta->key && !sta->key->force_sw_encrypt &&
+                   local->ops->set_key &&
+                   (keyconf = ieee80211_key_data2conf(local, sta->key)))
+                       local->ops->set_key(local_to_hw(local), DISABLE_KEY,
+                                          sta->addr, keyconf, sta->aid);
+               kfree(keyconf);
+               ieee80211_key_free(sta->key);
+               sta->key = NULL;
+       }
+       spin_unlock_bh(&local->sta_lock);
+
+       memset(&key, 0, sizeof(key));
+       if (local->ops->set_key &&
+                   local->ops->set_key(local_to_hw(local), REMOVE_ALL_KEYS,
+                                      NULL, &key, 0))
+               printk(KERN_DEBUG "%s: failed to remove hwaccel keys\n",
+                      dev->name);
+
+       return 0;
+}
+
+
+static int
+ieee80211_ioctl_force_unicast_rate(struct net_device *dev,
+                                  struct ieee80211_sub_if_data *sdata,
+                                  int rate)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_hw_mode *mode;
+       int i;
+
+       if (sdata->type != IEEE80211_IF_TYPE_AP)
+               return -ENOENT;
+
+       if (rate == 0) {
+               sdata->u.ap.force_unicast_rateidx = -1;
+               return 0;
+       }
+
+       mode = local->oper_hw_mode;
+       for (i = 0; i < mode->num_rates; i++) {
+               if (mode->rates[i].rate == rate) {
+                       sdata->u.ap.force_unicast_rateidx = i;
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+
+static int
+ieee80211_ioctl_max_ratectrl_rate(struct net_device *dev,
+                                 struct ieee80211_sub_if_data *sdata,
+                                 int rate)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_hw_mode *mode;
+       int i;
+
+       if (sdata->type != IEEE80211_IF_TYPE_AP)
+               return -ENOENT;
+
+       if (rate == 0) {
+               sdata->u.ap.max_ratectrl_rateidx = -1;
+               return 0;
+       }
+
+       mode = local->oper_hw_mode;
+       for (i = 0; i < mode->num_rates; i++) {
+               if (mode->rates[i].rate == rate) {
+                       sdata->u.ap.max_ratectrl_rateidx = i;
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+
+static void ieee80211_key_enable_hwaccel(struct ieee80211_local *local,
+                                        struct ieee80211_key *key)
+{
+       struct ieee80211_key_conf *keyconf;
+       u8 addr[ETH_ALEN];
+
+       if (!key || key->alg != ALG_WEP || !key->force_sw_encrypt ||
+           (local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP))
+               return;
+
+       memset(addr, 0xff, ETH_ALEN);
+       keyconf = ieee80211_key_data2conf(local, key);
+       if (keyconf && local->ops->set_key &&
+           local->ops->set_key(local_to_hw(local),
+                              SET_KEY, addr, keyconf, 0) == 0) {
+               key->force_sw_encrypt =
+                       !!(keyconf->flags & IEEE80211_KEY_FORCE_SW_ENCRYPT);
+               key->hw_key_idx = keyconf->hw_key_idx;
+       }
+       kfree(keyconf);
+}
+
+
+static void ieee80211_key_disable_hwaccel(struct ieee80211_local *local,
+                                         struct ieee80211_key *key)
+{
+       struct ieee80211_key_conf *keyconf;
+       u8 addr[ETH_ALEN];
+
+       if (!key || key->alg != ALG_WEP || key->force_sw_encrypt ||
+           (local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP))
+               return;
+
+       memset(addr, 0xff, ETH_ALEN);
+       keyconf = ieee80211_key_data2conf(local, key);
+       if (keyconf && local->ops->set_key)
+               local->ops->set_key(local_to_hw(local), DISABLE_KEY,
+                                  addr, keyconf, 0);
+       kfree(keyconf);
+       key->force_sw_encrypt = 1;
+}
+
+
+static int ieee80211_ioctl_default_wep_only(struct ieee80211_local *local,
+                                           int value)
+{
+       int i;
+       struct ieee80211_sub_if_data *sdata;
+
+       local->default_wep_only = value;
+       read_lock(&local->sub_if_lock);
+       list_for_each_entry(sdata, &local->sub_if_list, list)
+               for (i = 0; i < NUM_DEFAULT_KEYS; i++)
+                       if (value)
+                               ieee80211_key_enable_hwaccel(local,
+                                                            sdata->keys[i]);
+                       else
+                               ieee80211_key_disable_hwaccel(local,
+                                                             sdata->keys[i]);
+       read_unlock(&local->sub_if_lock);
+
+       return 0;
+}
+
+
+void ieee80211_update_default_wep_only(struct ieee80211_local *local)
+{
+       int i = 0;
+       struct ieee80211_sub_if_data *sdata;
+
+       read_lock(&local->sub_if_lock);
+       list_for_each_entry(sdata, &local->sub_if_list, list) {
+
+               if (sdata->dev == local->mdev)
+                       continue;
+
+               /* If there is an AP interface then depend on userspace to
+                  set default_wep_only correctly. */
+               if (sdata->type == IEEE80211_IF_TYPE_AP) {
+                       read_unlock(&local->sub_if_lock);
+                       return;
+               }
+
+               i++;
+       }
+
+       read_unlock(&local->sub_if_lock);
+
+       if (i <= 1)
+               ieee80211_ioctl_default_wep_only(local, 1);
+       else
+               ieee80211_ioctl_default_wep_only(local, 0);
+}
+
+
+static int ieee80211_ioctl_prism2_param(struct net_device *dev,
+                                       struct iw_request_info *info,
+                                       void *wrqu, char *extra)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata;
+       int *i = (int *) extra;
+       int param = *i;
+       int value = *(i + 1);
+       int ret = 0;
+
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+       switch (param) {
+       case PRISM2_PARAM_IEEE_802_1X:
+               if (local->ops->set_ieee8021x)
+                       ret = local->ops->set_ieee8021x(local_to_hw(local),
+                                                       value);
+               if (ret)
+                       printk(KERN_DEBUG "%s: failed to set IEEE 802.1X (%d) "
+                              "for low-level driver\n", dev->name, value);
+               else
+                       sdata->ieee802_1x = value;
+               break;
+
+       case PRISM2_PARAM_ANTSEL_TX:
+               local->hw.conf.antenna_sel_tx = value;
+               if (ieee80211_hw_config(local))
+                       ret = -EINVAL;
+               break;
+
+       case PRISM2_PARAM_ANTSEL_RX:
+               local->hw.conf.antenna_sel_rx = value;
+               if (ieee80211_hw_config(local))
+                       ret = -EINVAL;
+               break;
+
+       case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES:
+               local->cts_protect_erp_frames = value;
+               break;
+
+       case PRISM2_PARAM_DROP_UNENCRYPTED:
+               sdata->drop_unencrypted = value;
+               break;
+
+       case PRISM2_PARAM_PREAMBLE:
+               local->short_preamble = value;
+               break;
+
+       case PRISM2_PARAM_STAT_TIME:
+               if (!local->stat_time && value) {
+                       local->stat_timer.expires = jiffies + HZ * value / 100;
+                       add_timer(&local->stat_timer);
+               } else if (local->stat_time && !value) {
+                       del_timer_sync(&local->stat_timer);
+               }
+               local->stat_time = value;
+               break;
+       case PRISM2_PARAM_SHORT_SLOT_TIME:
+               if (value)
+                       local->hw.conf.flags |= IEEE80211_CONF_SHORT_SLOT_TIME;
+               else
+                       local->hw.conf.flags &= ~IEEE80211_CONF_SHORT_SLOT_TIME;
+               if (ieee80211_hw_config(local))
+                       ret = -EINVAL;
+               break;
+
+       case PRISM2_PARAM_NEXT_MODE:
+               local->next_mode = value;
+               break;
+
+       case PRISM2_PARAM_CLEAR_KEYS:
+               ret = ieee80211_ioctl_clear_keys(dev);
+               break;
+
+       case PRISM2_PARAM_RADIO_ENABLED:
+               ret = ieee80211_ioctl_set_radio_enabled(dev, value);
+               break;
+
+       case PRISM2_PARAM_ANTENNA_MODE:
+               local->hw.conf.antenna_mode = value;
+               if (ieee80211_hw_config(local))
+                       ret = -EINVAL;
+               break;
+
+       case PRISM2_PARAM_STA_ANTENNA_SEL:
+               local->sta_antenna_sel = value;
+               break;
+
+       case PRISM2_PARAM_FORCE_UNICAST_RATE:
+               ret = ieee80211_ioctl_force_unicast_rate(dev, sdata, value);
+               break;
+
+       case PRISM2_PARAM_MAX_RATECTRL_RATE:
+               ret = ieee80211_ioctl_max_ratectrl_rate(dev, sdata, value);
+               break;
+
+       case PRISM2_PARAM_RATE_CTRL_NUM_UP:
+               local->rate_ctrl_num_up = value;
+               break;
+
+       case PRISM2_PARAM_RATE_CTRL_NUM_DOWN:
+               local->rate_ctrl_num_down = value;
+               break;
+
+       case PRISM2_PARAM_TX_POWER_REDUCTION:
+               if (value < 0)
+                       ret = -EINVAL;
+               else
+                       local->hw.conf.tx_power_reduction = value;
+               break;
+
+       case PRISM2_PARAM_KEY_TX_RX_THRESHOLD:
+               local->key_tx_rx_threshold = value;
+               break;
+
+       case PRISM2_PARAM_DEFAULT_WEP_ONLY:
+               ret = ieee80211_ioctl_default_wep_only(local, value);
+               break;
+
+       case PRISM2_PARAM_WIFI_WME_NOACK_TEST:
+               local->wifi_wme_noack_test = value;
+               break;
+
+       case PRISM2_PARAM_SCAN_FLAGS:
+               local->scan_flags = value;
+               break;
+
+       case PRISM2_PARAM_MIXED_CELL:
+               if (sdata->type != IEEE80211_IF_TYPE_STA &&
+                   sdata->type != IEEE80211_IF_TYPE_IBSS)
+                       ret = -EINVAL;
+               else
+                       sdata->u.sta.mixed_cell = !!value;
+               break;
+
+       case PRISM2_PARAM_HW_MODES:
+               local->enabled_modes = value;
+               break;
+
+       case PRISM2_PARAM_CREATE_IBSS:
+               if (sdata->type != IEEE80211_IF_TYPE_IBSS)
+                       ret = -EINVAL;
+               else
+                       sdata->u.sta.create_ibss = !!value;
+               break;
+       case PRISM2_PARAM_WMM_ENABLED:
+               if (sdata->type != IEEE80211_IF_TYPE_STA &&
+                   sdata->type != IEEE80211_IF_TYPE_IBSS)
+                       ret = -EINVAL;
+               else
+                       sdata->u.sta.wmm_enabled = !!value;
+               break;
+       case PRISM2_PARAM_RADAR_DETECT:
+               local->hw.conf.radar_detect = value;
+               break;
+       case PRISM2_PARAM_SPECTRUM_MGMT:
+               local->hw.conf.spect_mgmt = value;
+               break;
+       default:
+               ret = -EOPNOTSUPP;
+               break;
+       }
+
+       return ret;
+}
+
+
+static int ieee80211_ioctl_get_prism2_param(struct net_device *dev,
+                                           struct iw_request_info *info,
+                                           void *wrqu, char *extra)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata;
+       int *param = (int *) extra;
+       int ret = 0;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+       switch (*param) {
+       case PRISM2_PARAM_IEEE_802_1X:
+               *param = sdata->ieee802_1x;
+               break;
+
+       case PRISM2_PARAM_ANTSEL_TX:
+               *param = local->hw.conf.antenna_sel_tx;
+               break;
+
+       case PRISM2_PARAM_ANTSEL_RX:
+               *param = local->hw.conf.antenna_sel_rx;
+               break;
+
+       case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES:
+               *param = local->cts_protect_erp_frames;
+               break;
+
+       case PRISM2_PARAM_DROP_UNENCRYPTED:
+               *param = sdata->drop_unencrypted;
+               break;
+
+       case PRISM2_PARAM_PREAMBLE:
+               *param = local->short_preamble;
+               break;
+
+       case PRISM2_PARAM_STAT_TIME:
+               *param = local->stat_time;
+               break;
+       case PRISM2_PARAM_SHORT_SLOT_TIME:
+               *param = !!(local->hw.conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME);
+               break;
+
+       case PRISM2_PARAM_NEXT_MODE:
+               *param = local->next_mode;
+               break;
+
+       case PRISM2_PARAM_ANTENNA_MODE:
+               *param = local->hw.conf.antenna_mode;
+               break;
+
+       case PRISM2_PARAM_STA_ANTENNA_SEL:
+               *param = local->sta_antenna_sel;
+               break;
+
+       case PRISM2_PARAM_RATE_CTRL_NUM_UP:
+               *param = local->rate_ctrl_num_up;
+               break;
+
+       case PRISM2_PARAM_RATE_CTRL_NUM_DOWN:
+               *param = local->rate_ctrl_num_down;
+               break;
+
+       case PRISM2_PARAM_TX_POWER_REDUCTION:
+               *param = local->hw.conf.tx_power_reduction;
+               break;
+
+       case PRISM2_PARAM_KEY_TX_RX_THRESHOLD:
+               *param = local->key_tx_rx_threshold;
+               break;
+
+       case PRISM2_PARAM_DEFAULT_WEP_ONLY:
+               *param = local->default_wep_only;
+               break;
+
+       case PRISM2_PARAM_WIFI_WME_NOACK_TEST:
+               *param = local->wifi_wme_noack_test;
+               break;
+
+       case PRISM2_PARAM_SCAN_FLAGS:
+               *param = local->scan_flags;
+               break;
+
+       case PRISM2_PARAM_HW_MODES:
+               *param = local->enabled_modes;
+               break;
+
+       case PRISM2_PARAM_CREATE_IBSS:
+               if (sdata->type != IEEE80211_IF_TYPE_IBSS)
+                       ret = -EINVAL;
+               else
+                       *param = !!sdata->u.sta.create_ibss;
+               break;
+
+       case PRISM2_PARAM_MIXED_CELL:
+               if (sdata->type != IEEE80211_IF_TYPE_STA &&
+                   sdata->type != IEEE80211_IF_TYPE_IBSS)
+                       ret = -EINVAL;
+               else
+                       *param = !!sdata->u.sta.mixed_cell;
+               break;
+       case PRISM2_PARAM_WMM_ENABLED:
+               if (sdata->type != IEEE80211_IF_TYPE_STA &&
+                   sdata->type != IEEE80211_IF_TYPE_IBSS)
+                       ret = -EINVAL;
+               else
+                       *param = !!sdata->u.sta.wmm_enabled;
+               break;
+       default:
+               ret = -EOPNOTSUPP;
+               break;
+       }
+
+       return ret;
+}
+
+static int ieee80211_ioctl_siwmlme(struct net_device *dev,
+                                  struct iw_request_info *info,
+                                  struct iw_point *data, char *extra)
+{
+       struct ieee80211_sub_if_data *sdata;
+       struct iw_mlme *mlme = (struct iw_mlme *) extra;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       if (sdata->type != IEEE80211_IF_TYPE_STA &&
+           sdata->type != IEEE80211_IF_TYPE_IBSS)
+               return -EINVAL;
+
+       switch (mlme->cmd) {
+       case IW_MLME_DEAUTH:
+               /* TODO: mlme->addr.sa_data */
+               return ieee80211_sta_deauthenticate(dev, mlme->reason_code);
+       case IW_MLME_DISASSOC:
+               /* TODO: mlme->addr.sa_data */
+               return ieee80211_sta_disassociate(dev, mlme->reason_code);
+       default:
+               return -EOPNOTSUPP;
+       }
+}
+
+
+static int ieee80211_ioctl_siwencode(struct net_device *dev,
+                                    struct iw_request_info *info,
+                                    struct iw_point *erq, char *keybuf)
+{
+       struct ieee80211_sub_if_data *sdata;
+       int idx, i, alg = ALG_WEP;
+       u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+       idx = erq->flags & IW_ENCODE_INDEX;
+       if (idx == 0) {
+               if (sdata->default_key)
+                       for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+                               if (sdata->default_key == sdata->keys[i]) {
+                                       idx = i;
+                                       break;
+                               }
+                       }
+       } else if (idx < 1 || idx > 4)
+               return -EINVAL;
+       else
+               idx--;
+
+       if (erq->flags & IW_ENCODE_DISABLED)
+               alg = ALG_NONE;
+       else if (erq->length == 0) {
+               /* No key data - just set the default TX key index */
+               if (sdata->default_key != sdata->keys[idx]) {
+                       ieee80211_debugfs_key_remove_default(sdata);
+                       sdata->default_key = sdata->keys[idx];
+                       if (sdata->default_key)
+                               ieee80211_debugfs_key_add_default(sdata);
+               }
+               return 0;
+       }
+
+       return ieee80211_set_encryption(
+               dev, bcaddr,
+               idx, alg,
+               !sdata->default_key,
+               keybuf, erq->length);
+}
+
+
+static int ieee80211_ioctl_giwencode(struct net_device *dev,
+                                    struct iw_request_info *info,
+                                    struct iw_point *erq, char *key)
+{
+       struct ieee80211_sub_if_data *sdata;
+       int idx, i;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+       idx = erq->flags & IW_ENCODE_INDEX;
+       if (idx < 1 || idx > 4) {
+               idx = -1;
+               if (!sdata->default_key)
+                       idx = 0;
+               else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+                       if (sdata->default_key == sdata->keys[i]) {
+                               idx = i;
+                               break;
+                       }
+               }
+               if (idx < 0)
+                       return -EINVAL;
+       } else
+               idx--;
+
+       erq->flags = idx + 1;
+
+       if (!sdata->keys[idx]) {
+               erq->length = 0;
+               erq->flags |= IW_ENCODE_DISABLED;
+               return 0;
+       }
+
+       memcpy(key, sdata->keys[idx]->key,
+              min((int)erq->length, sdata->keys[idx]->keylen));
+       erq->length = sdata->keys[idx]->keylen;
+       erq->flags |= IW_ENCODE_ENABLED;
+
+       return 0;
+}
+
+static int ieee80211_ioctl_siwauth(struct net_device *dev,
+                                  struct iw_request_info *info,
+                                  struct iw_param *data, char *extra)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       int ret = 0;
+
+       switch (data->flags & IW_AUTH_INDEX) {
+       case IW_AUTH_WPA_VERSION:
+       case IW_AUTH_CIPHER_PAIRWISE:
+       case IW_AUTH_CIPHER_GROUP:
+       case IW_AUTH_WPA_ENABLED:
+       case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+               break;
+       case IW_AUTH_KEY_MGMT:
+               if (sdata->type != IEEE80211_IF_TYPE_STA)
+                       ret = -EINVAL;
+               else {
+                       /*
+                        * TODO: sdata->u.sta.key_mgmt does not match with WE18
+                        * value completely; could consider modifying this to
+                        * be closer to WE18. For now, this value is not really
+                        * used for anything else than Privacy matching, so the
+                        * current code here should be more or less OK.
+                        */
+                       if (data->value & IW_AUTH_KEY_MGMT_802_1X) {
+                               sdata->u.sta.key_mgmt =
+                                       IEEE80211_KEY_MGMT_WPA_EAP;
+                       } else if (data->value & IW_AUTH_KEY_MGMT_PSK) {
+                               sdata->u.sta.key_mgmt =
+                                       IEEE80211_KEY_MGMT_WPA_PSK;
+                       } else {
+                               sdata->u.sta.key_mgmt =
+                                       IEEE80211_KEY_MGMT_NONE;
+                       }
+               }
+               break;
+       case IW_AUTH_80211_AUTH_ALG:
+               if (sdata->type == IEEE80211_IF_TYPE_STA ||
+                   sdata->type == IEEE80211_IF_TYPE_IBSS)
+                       sdata->u.sta.auth_algs = data->value;
+               else
+                       ret = -EOPNOTSUPP;
+               break;
+       case IW_AUTH_PRIVACY_INVOKED:
+               if (local->ops->set_privacy_invoked)
+                       ret = local->ops->set_privacy_invoked(
+                                       local_to_hw(local), data->value);
+               break;
+       default:
+               ret = -EOPNOTSUPP;
+               break;
+       }
+       return ret;
+}
+
+/* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
+static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct iw_statistics *wstats = &local->wstats;
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct sta_info *sta = NULL;
+
+       if (sdata->type == IEEE80211_IF_TYPE_STA ||
+           sdata->type == IEEE80211_IF_TYPE_IBSS)
+               sta = sta_info_get(local, sdata->u.sta.bssid);
+       if (!sta) {
+               wstats->discard.fragment = 0;
+               wstats->discard.misc = 0;
+               wstats->qual.qual = 0;
+               wstats->qual.level = 0;
+               wstats->qual.noise = 0;
+               wstats->qual.updated = IW_QUAL_ALL_INVALID;
+       } else {
+               wstats->qual.level = sta->last_rssi;
+               wstats->qual.qual = sta->last_signal;
+               wstats->qual.noise = sta->last_noise;
+               wstats->qual.updated = local->wstats_flags;
+               sta_info_put(sta);
+       }
+       return wstats;
+}
+
+static int ieee80211_ioctl_giwauth(struct net_device *dev,
+                                  struct iw_request_info *info,
+                                  struct iw_param *data, char *extra)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       int ret = 0;
+
+       switch (data->flags & IW_AUTH_INDEX) {
+       case IW_AUTH_80211_AUTH_ALG:
+               if (sdata->type == IEEE80211_IF_TYPE_STA ||
+                   sdata->type == IEEE80211_IF_TYPE_IBSS)
+                       data->value = sdata->u.sta.auth_algs;
+               else
+                       ret = -EOPNOTSUPP;
+               break;
+       default:
+               ret = -EOPNOTSUPP;
+               break;
+       }
+       return ret;
+}
+
+
+static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
+                                       struct iw_request_info *info,
+                                       struct iw_point *erq, char *extra)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
+       int alg, idx, i;
+
+       switch (ext->alg) {
+       case IW_ENCODE_ALG_NONE:
+               alg = ALG_NONE;
+               break;
+       case IW_ENCODE_ALG_WEP:
+               alg = ALG_WEP;
+               break;
+       case IW_ENCODE_ALG_TKIP:
+               alg = ALG_TKIP;
+               break;
+       case IW_ENCODE_ALG_CCMP:
+               alg = ALG_CCMP;
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       if (erq->flags & IW_ENCODE_DISABLED)
+               alg = ALG_NONE;
+
+       idx = erq->flags & IW_ENCODE_INDEX;
+       if (idx < 1 || idx > 4) {
+               idx = -1;
+               if (!sdata->default_key)
+                       idx = 0;
+               else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+                       if (sdata->default_key == sdata->keys[i]) {
+                               idx = i;
+                               break;
+                       }
+               }
+               if (idx < 0)
+                       return -EINVAL;
+       } else
+               idx--;
+
+       return ieee80211_set_encryption(dev, ext->addr.sa_data, idx, alg,
+                                       ext->ext_flags &
+                                       IW_ENCODE_EXT_SET_TX_KEY,
+                                       ext->key, ext->key_len);
+}
+
+
+static const struct iw_priv_args ieee80211_ioctl_priv[] = {
+       { PRISM2_IOCTL_PRISM2_PARAM,
+         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "param" },
+       { PRISM2_IOCTL_GET_PRISM2_PARAM,
+         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_param" },
+};
+
+/* Structures to export the Wireless Handlers */
+
+static const iw_handler ieee80211_handler[] =
+{
+       (iw_handler) NULL,                              /* SIOCSIWCOMMIT */
+       (iw_handler) ieee80211_ioctl_giwname,           /* SIOCGIWNAME */
+       (iw_handler) NULL,                              /* SIOCSIWNWID */
+       (iw_handler) NULL,                              /* SIOCGIWNWID */
+       (iw_handler) ieee80211_ioctl_siwfreq,           /* SIOCSIWFREQ */
+       (iw_handler) ieee80211_ioctl_giwfreq,           /* SIOCGIWFREQ */
+       (iw_handler) ieee80211_ioctl_siwmode,           /* SIOCSIWMODE */
+       (iw_handler) ieee80211_ioctl_giwmode,           /* SIOCGIWMODE */
+       (iw_handler) NULL,                              /* SIOCSIWSENS */
+       (iw_handler) NULL,                              /* SIOCGIWSENS */
+       (iw_handler) NULL /* not used */,               /* SIOCSIWRANGE */
+       (iw_handler) ieee80211_ioctl_giwrange,          /* SIOCGIWRANGE */
+       (iw_handler) NULL /* not used */,               /* SIOCSIWPRIV */
+       (iw_handler) NULL /* kernel code */,            /* SIOCGIWPRIV */
+       (iw_handler) NULL /* not used */,               /* SIOCSIWSTATS */
+       (iw_handler) NULL /* kernel code */,            /* SIOCGIWSTATS */
+       iw_handler_set_spy,                             /* SIOCSIWSPY */
+       iw_handler_get_spy,                             /* SIOCGIWSPY */
+       iw_handler_set_thrspy,                          /* SIOCSIWTHRSPY */
+       iw_handler_get_thrspy,                          /* SIOCGIWTHRSPY */
+       (iw_handler) ieee80211_ioctl_siwap,             /* SIOCSIWAP */
+       (iw_handler) ieee80211_ioctl_giwap,             /* SIOCGIWAP */
+       (iw_handler) ieee80211_ioctl_siwmlme,           /* SIOCSIWMLME */
+       (iw_handler) NULL,                              /* SIOCGIWAPLIST */
+       (iw_handler) ieee80211_ioctl_siwscan,           /* SIOCSIWSCAN */
+       (iw_handler) ieee80211_ioctl_giwscan,           /* SIOCGIWSCAN */
+       (iw_handler) ieee80211_ioctl_siwessid,          /* SIOCSIWESSID */
+       (iw_handler) ieee80211_ioctl_giwessid,          /* SIOCGIWESSID */
+       (iw_handler) NULL,                              /* SIOCSIWNICKN */
+       (iw_handler) NULL,                              /* SIOCGIWNICKN */
+       (iw_handler) NULL,                              /* -- hole -- */
+       (iw_handler) NULL,                              /* -- hole -- */
+       (iw_handler) NULL,                              /* SIOCSIWRATE */
+       (iw_handler) NULL,                              /* SIOCGIWRATE */
+       (iw_handler) ieee80211_ioctl_siwrts,            /* SIOCSIWRTS */
+       (iw_handler) ieee80211_ioctl_giwrts,            /* SIOCGIWRTS */
+       (iw_handler) ieee80211_ioctl_siwfrag,           /* SIOCSIWFRAG */
+       (iw_handler) ieee80211_ioctl_giwfrag,           /* SIOCGIWFRAG */
+       (iw_handler) NULL,                              /* SIOCSIWTXPOW */
+       (iw_handler) NULL,                              /* SIOCGIWTXPOW */
+       (iw_handler) ieee80211_ioctl_siwretry,          /* SIOCSIWRETRY */
+       (iw_handler) ieee80211_ioctl_giwretry,          /* SIOCGIWRETRY */
+       (iw_handler) ieee80211_ioctl_siwencode,         /* SIOCSIWENCODE */
+       (iw_handler) ieee80211_ioctl_giwencode,         /* SIOCGIWENCODE */
+       (iw_handler) NULL,                              /* SIOCSIWPOWER */
+       (iw_handler) NULL,                              /* SIOCGIWPOWER */
+       (iw_handler) NULL,                              /* -- hole -- */
+       (iw_handler) NULL,                              /* -- hole -- */
+       (iw_handler) ieee80211_ioctl_siwgenie,          /* SIOCSIWGENIE */
+       (iw_handler) NULL,                              /* SIOCGIWGENIE */
+       (iw_handler) ieee80211_ioctl_siwauth,           /* SIOCSIWAUTH */
+       (iw_handler) ieee80211_ioctl_giwauth,           /* SIOCGIWAUTH */
+       (iw_handler) ieee80211_ioctl_siwencodeext,      /* SIOCSIWENCODEEXT */
+       (iw_handler) NULL,                              /* SIOCGIWENCODEEXT */
+       (iw_handler) NULL,                              /* SIOCSIWPMKSA */
+       (iw_handler) NULL,                              /* -- hole -- */
+};
+
+static const iw_handler ieee80211_private_handler[] =
+{                                                      /* SIOCIWFIRSTPRIV + */
+       (iw_handler) ieee80211_ioctl_prism2_param,      /* 0 */
+       (iw_handler) ieee80211_ioctl_get_prism2_param,  /* 1 */
+};
+
+const struct iw_handler_def ieee80211_iw_handler_def =
+{
+       .num_standard   = ARRAY_SIZE(ieee80211_handler),
+       .num_private    = ARRAY_SIZE(ieee80211_private_handler),
+       .num_private_args = ARRAY_SIZE(ieee80211_ioctl_priv),
+       .standard       = (iw_handler *) ieee80211_handler,
+       .private        = (iw_handler *) ieee80211_private_handler,
+       .private_args   = (struct iw_priv_args *) ieee80211_ioctl_priv,
+       .get_wireless_stats = ieee80211_get_wireless_stats,
+};
diff --git a/net/mac80211/ieee80211_key.h b/net/mac80211/ieee80211_key.h
new file mode 100644 (file)
index 0000000..c333849
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2002-2004, Instant802 Networks, Inc.
+ * Copyright 2005, Devicescape Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef IEEE80211_KEY_H
+#define IEEE80211_KEY_H
+
+#include <linux/types.h>
+#include <linux/kref.h>
+#include <linux/crypto.h>
+#include <net/mac80211.h>
+
+/* ALG_TKIP
+ * struct ieee80211_key::key is encoded as a 256-bit (32 byte) data block:
+ * Temporal Encryption Key (128 bits)
+ * Temporal Authenticator Tx MIC Key (64 bits)
+ * Temporal Authenticator Rx MIC Key (64 bits)
+ */
+
+#define WEP_IV_LEN 4
+#define WEP_ICV_LEN 4
+
+#define ALG_TKIP_KEY_LEN 32
+/* Starting offsets for each key */
+#define ALG_TKIP_TEMP_ENCR_KEY 0
+#define ALG_TKIP_TEMP_AUTH_TX_MIC_KEY 16
+#define ALG_TKIP_TEMP_AUTH_RX_MIC_KEY 24
+#define TKIP_IV_LEN 8
+#define TKIP_ICV_LEN 4
+
+#define ALG_CCMP_KEY_LEN 16
+#define CCMP_HDR_LEN 8
+#define CCMP_MIC_LEN 8
+#define CCMP_TK_LEN 16
+#define CCMP_PN_LEN 6
+
+#define NUM_RX_DATA_QUEUES 17
+
+struct ieee80211_key {
+       struct kref kref;
+
+       int hw_key_idx; /* filled and used by low-level driver */
+       ieee80211_key_alg alg;
+       union {
+               struct {
+                       /* last used TSC */
+                       u32 iv32;
+                       u16 iv16;
+                       u16 p1k[5];
+                       int tx_initialized;
+
+                       /* last received RSC */
+                       u32 iv32_rx[NUM_RX_DATA_QUEUES];
+                       u16 iv16_rx[NUM_RX_DATA_QUEUES];
+                       u16 p1k_rx[NUM_RX_DATA_QUEUES][5];
+                       int rx_initialized[NUM_RX_DATA_QUEUES];
+               } tkip;
+               struct {
+                       u8 tx_pn[6];
+                       u8 rx_pn[NUM_RX_DATA_QUEUES][6];
+                       struct crypto_cipher *tfm;
+                       u32 replays; /* dot11RSNAStatsCCMPReplays */
+                       /* scratch buffers for virt_to_page() (crypto API) */
+#ifndef AES_BLOCK_LEN
+#define AES_BLOCK_LEN 16
+#endif
+                       u8 tx_crypto_buf[6 * AES_BLOCK_LEN];
+                       u8 rx_crypto_buf[6 * AES_BLOCK_LEN];
+               } ccmp;
+       } u;
+       int tx_rx_count; /* number of times this key has been used */
+       int keylen;
+
+       /* if the low level driver can provide hardware acceleration it should
+        * clear this flag */
+       unsigned int force_sw_encrypt:1;
+       unsigned int default_tx_key:1; /* This key is the new default TX key
+                                       * (used only for broadcast keys). */
+       s8 keyidx; /* WEP key index */
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+       struct {
+               struct dentry *stalink;
+               struct dentry *dir;
+               struct dentry *keylen;
+               struct dentry *force_sw_encrypt;
+               struct dentry *keyidx;
+               struct dentry *hw_key_idx;
+               struct dentry *tx_rx_count;
+               struct dentry *algorithm;
+               struct dentry *tx_spec;
+               struct dentry *rx_spec;
+               struct dentry *replays;
+               struct dentry *key;
+       } debugfs;
+#endif
+
+       u8 key[0];
+};
+
+#endif /* IEEE80211_KEY_H */
diff --git a/net/mac80211/ieee80211_led.c b/net/mac80211/ieee80211_led.c
new file mode 100644 (file)
index 0000000..719d75b
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2006, Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* just for IFNAMSIZ */
+#include <linux/if.h>
+#include "ieee80211_led.h"
+
+void ieee80211_led_rx(struct ieee80211_local *local)
+{
+       if (unlikely(!local->rx_led))
+               return;
+       if (local->rx_led_counter++ % 2 == 0)
+               led_trigger_event(local->rx_led, LED_OFF);
+       else
+               led_trigger_event(local->rx_led, LED_FULL);
+}
+
+/* q is 1 if a packet was enqueued, 0 if it has been transmitted */
+void ieee80211_led_tx(struct ieee80211_local *local, int q)
+{
+       if (unlikely(!local->tx_led))
+               return;
+       /* not sure how this is supposed to work ... */
+       local->tx_led_counter += 2*q-1;
+       if (local->tx_led_counter % 2 == 0)
+               led_trigger_event(local->tx_led, LED_OFF);
+       else
+               led_trigger_event(local->tx_led, LED_FULL);
+}
+
+void ieee80211_led_init(struct ieee80211_local *local)
+{
+       local->rx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
+       if (!local->rx_led)
+               return;
+       snprintf(local->rx_led_name, sizeof(local->rx_led_name),
+                "%srx", wiphy_name(local->hw.wiphy));
+       local->rx_led->name = local->rx_led_name;
+       if (led_trigger_register(local->rx_led)) {
+               kfree(local->rx_led);
+               local->rx_led = NULL;
+       }
+
+       local->tx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
+       if (!local->tx_led)
+               return;
+       snprintf(local->tx_led_name, sizeof(local->tx_led_name),
+                "%stx", wiphy_name(local->hw.wiphy));
+       local->tx_led->name = local->tx_led_name;
+       if (led_trigger_register(local->tx_led)) {
+               kfree(local->tx_led);
+               local->tx_led = NULL;
+       }
+}
+
+void ieee80211_led_exit(struct ieee80211_local *local)
+{
+       if (local->tx_led) {
+               led_trigger_unregister(local->tx_led);
+               kfree(local->tx_led);
+       }
+       if (local->rx_led) {
+               led_trigger_unregister(local->rx_led);
+               kfree(local->rx_led);
+       }
+}
+
+char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+
+       if (local->tx_led)
+               return local->tx_led_name;
+       return NULL;
+}
+EXPORT_SYMBOL(__ieee80211_get_tx_led_name);
+
+char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+
+       if (local->rx_led)
+               return local->rx_led_name;
+       return NULL;
+}
+EXPORT_SYMBOL(__ieee80211_get_rx_led_name);
diff --git a/net/mac80211/ieee80211_led.h b/net/mac80211/ieee80211_led.h
new file mode 100644 (file)
index 0000000..5c8ab82
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2006, Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/leds.h>
+#include "ieee80211_i.h"
+
+#ifdef CONFIG_MAC80211_LEDS
+extern void ieee80211_led_rx(struct ieee80211_local *local);
+extern void ieee80211_led_tx(struct ieee80211_local *local, int q);
+extern void ieee80211_led_init(struct ieee80211_local *local);
+extern void ieee80211_led_exit(struct ieee80211_local *local);
+#else
+static inline void ieee80211_led_rx(struct ieee80211_local *local)
+{
+}
+static inline void ieee80211_led_tx(struct ieee80211_local *local, int q)
+{
+}
+static inline void ieee80211_led_init(struct ieee80211_local *local)
+{
+}
+static inline void ieee80211_led_exit(struct ieee80211_local *local)
+{
+}
+#endif
diff --git a/net/mac80211/ieee80211_rate.c b/net/mac80211/ieee80211_rate.c
new file mode 100644 (file)
index 0000000..16e8508
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2002-2005, Instant802 Networks, Inc.
+ * Copyright 2005-2006, Devicescape Software, Inc.
+ * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include "ieee80211_rate.h"
+#include "ieee80211_i.h"
+
+struct rate_control_alg {
+       struct list_head list;
+       struct rate_control_ops *ops;
+};
+
+static LIST_HEAD(rate_ctrl_algs);
+static DEFINE_MUTEX(rate_ctrl_mutex);
+
+int ieee80211_rate_control_register(struct rate_control_ops *ops)
+{
+       struct rate_control_alg *alg;
+
+       alg = kmalloc(sizeof(*alg), GFP_KERNEL);
+       if (alg == NULL) {
+               return -ENOMEM;
+       }
+       memset(alg, 0, sizeof(*alg));
+       alg->ops = ops;
+
+       mutex_lock(&rate_ctrl_mutex);
+       list_add_tail(&alg->list, &rate_ctrl_algs);
+       mutex_unlock(&rate_ctrl_mutex);
+
+       return 0;
+}
+EXPORT_SYMBOL(ieee80211_rate_control_register);
+
+void ieee80211_rate_control_unregister(struct rate_control_ops *ops)
+{
+       struct rate_control_alg *alg;
+
+       mutex_lock(&rate_ctrl_mutex);
+       list_for_each_entry(alg, &rate_ctrl_algs, list) {
+               if (alg->ops == ops) {
+                       list_del(&alg->list);
+                       break;
+               }
+       }
+       mutex_unlock(&rate_ctrl_mutex);
+       kfree(alg);
+}
+EXPORT_SYMBOL(ieee80211_rate_control_unregister);
+
+static struct rate_control_ops *
+ieee80211_try_rate_control_ops_get(const char *name)
+{
+       struct rate_control_alg *alg;
+       struct rate_control_ops *ops = NULL;
+
+       mutex_lock(&rate_ctrl_mutex);
+       list_for_each_entry(alg, &rate_ctrl_algs, list) {
+               if (!name || !strcmp(alg->ops->name, name))
+                       if (try_module_get(alg->ops->module)) {
+                               ops = alg->ops;
+                               break;
+                       }
+       }
+       mutex_unlock(&rate_ctrl_mutex);
+       return ops;
+}
+
+/* Get the rate control algorithm. If `name' is NULL, get the first
+ * available algorithm. */
+static struct rate_control_ops *
+ieee80211_rate_control_ops_get(const char *name)
+{
+       struct rate_control_ops *ops;
+
+       ops = ieee80211_try_rate_control_ops_get(name);
+       if (!ops) {
+               request_module("rc80211_%s", name ? name : "default");
+               ops = ieee80211_try_rate_control_ops_get(name);
+       }
+       return ops;
+}
+
+static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops)
+{
+       module_put(ops->module);
+}
+
+struct rate_control_ref *rate_control_alloc(const char *name,
+                                           struct ieee80211_local *local)
+{
+       struct rate_control_ref *ref;
+
+       ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL);
+       if (!ref)
+               goto fail_ref;
+       kref_init(&ref->kref);
+       ref->ops = ieee80211_rate_control_ops_get(name);
+       if (!ref->ops)
+               goto fail_ops;
+       ref->priv = ref->ops->alloc(local);
+       if (!ref->priv)
+               goto fail_priv;
+       return ref;
+
+fail_priv:
+       ieee80211_rate_control_ops_put(ref->ops);
+fail_ops:
+       kfree(ref);
+fail_ref:
+       return NULL;
+}
+
+static void rate_control_release(struct kref *kref)
+{
+       struct rate_control_ref *ctrl_ref;
+
+       ctrl_ref = container_of(kref, struct rate_control_ref, kref);
+       ctrl_ref->ops->free(ctrl_ref->priv);
+       ieee80211_rate_control_ops_put(ctrl_ref->ops);
+       kfree(ctrl_ref);
+}
+
+struct rate_control_ref *rate_control_get(struct rate_control_ref *ref)
+{
+       kref_get(&ref->kref);
+       return ref;
+}
+
+void rate_control_put(struct rate_control_ref *ref)
+{
+       kref_put(&ref->kref, rate_control_release);
+}
diff --git a/net/mac80211/ieee80211_rate.h b/net/mac80211/ieee80211_rate.h
new file mode 100644 (file)
index 0000000..f021a02
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2002-2005, Instant802 Networks, Inc.
+ * Copyright 2005, Devicescape Software, Inc.
+ * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef IEEE80211_RATE_H
+#define IEEE80211_RATE_H
+
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/types.h>
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+#include "sta_info.h"
+
+#define RATE_CONTROL_NUM_DOWN 20
+#define RATE_CONTROL_NUM_UP   15
+
+
+struct rate_control_extra {
+       /* values from rate_control_get_rate() to the caller: */
+       struct ieee80211_rate *probe; /* probe with this rate, or NULL for no
+                                      * probing */
+       struct ieee80211_rate *nonerp;
+
+       /* parameters from the caller to rate_control_get_rate(): */
+       struct ieee80211_hw_mode *mode;
+       int mgmt_data; /* this is data frame that is used for management
+                       * (e.g., IEEE 802.1X EAPOL) */
+       u16 ethertype;
+};
+
+
+struct rate_control_ops {
+       struct module *module;
+       const char *name;
+       void (*tx_status)(void *priv, struct net_device *dev,
+                         struct sk_buff *skb,
+                         struct ieee80211_tx_status *status);
+       struct ieee80211_rate *(*get_rate)(void *priv, struct net_device *dev,
+                                          struct sk_buff *skb,
+                                          struct rate_control_extra *extra);
+       void (*rate_init)(void *priv, void *priv_sta,
+                         struct ieee80211_local *local, struct sta_info *sta);
+       void (*clear)(void *priv);
+
+       void *(*alloc)(struct ieee80211_local *local);
+       void (*free)(void *priv);
+       void *(*alloc_sta)(void *priv, gfp_t gfp);
+       void (*free_sta)(void *priv, void *priv_sta);
+
+       int (*add_attrs)(void *priv, struct kobject *kobj);
+       void (*remove_attrs)(void *priv, struct kobject *kobj);
+       void (*add_sta_debugfs)(void *priv, void *priv_sta,
+                               struct dentry *dir);
+       void (*remove_sta_debugfs)(void *priv, void *priv_sta);
+};
+
+struct rate_control_ref {
+       struct rate_control_ops *ops;
+       void *priv;
+       struct kref kref;
+};
+
+int ieee80211_rate_control_register(struct rate_control_ops *ops);
+void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
+
+/* Get a reference to the rate control algorithm. If `name' is NULL, get the
+ * first available algorithm. */
+struct rate_control_ref *rate_control_alloc(const char *name,
+                                           struct ieee80211_local *local);
+struct rate_control_ref *rate_control_get(struct rate_control_ref *ref);
+void rate_control_put(struct rate_control_ref *ref);
+
+static inline void rate_control_tx_status(struct ieee80211_local *local,
+                                         struct net_device *dev,
+                                         struct sk_buff *skb,
+                                         struct ieee80211_tx_status *status)
+{
+       struct rate_control_ref *ref = local->rate_ctrl;
+       ref->ops->tx_status(ref->priv, dev, skb, status);
+}
+
+
+static inline struct ieee80211_rate *
+rate_control_get_rate(struct ieee80211_local *local, struct net_device *dev,
+                     struct sk_buff *skb, struct rate_control_extra *extra)
+{
+       struct rate_control_ref *ref = local->rate_ctrl;
+       return ref->ops->get_rate(ref->priv, dev, skb, extra);
+}
+
+
+static inline void rate_control_rate_init(struct sta_info *sta,
+                                         struct ieee80211_local *local)
+{
+       struct rate_control_ref *ref = sta->rate_ctrl;
+       ref->ops->rate_init(ref->priv, sta->rate_ctrl_priv, local, sta);
+}
+
+
+static inline void rate_control_clear(struct ieee80211_local *local)
+{
+       struct rate_control_ref *ref = local->rate_ctrl;
+       ref->ops->clear(ref->priv);
+}
+
+static inline void *rate_control_alloc_sta(struct rate_control_ref *ref,
+                                          gfp_t gfp)
+{
+       return ref->ops->alloc_sta(ref->priv, gfp);
+}
+
+static inline void rate_control_free_sta(struct rate_control_ref *ref,
+                                        void *priv)
+{
+       ref->ops->free_sta(ref->priv, priv);
+}
+
+static inline void rate_control_add_sta_debugfs(struct sta_info *sta)
+{
+#ifdef CONFIG_MAC80211_DEBUGFS
+       struct rate_control_ref *ref = sta->rate_ctrl;
+       if (sta->debugfs.dir && ref->ops->add_sta_debugfs)
+               ref->ops->add_sta_debugfs(ref->priv, sta->rate_ctrl_priv,
+                                         sta->debugfs.dir);
+#endif
+}
+
+static inline void rate_control_remove_sta_debugfs(struct sta_info *sta)
+{
+#ifdef CONFIG_MAC80211_DEBUGFS
+       struct rate_control_ref *ref = sta->rate_ctrl;
+       if (ref->ops->remove_sta_debugfs)
+               ref->ops->remove_sta_debugfs(ref->priv, sta->rate_ctrl_priv);
+#endif
+}
+
+#endif /* IEEE80211_RATE_H */
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
new file mode 100644 (file)
index 0000000..822917d
--- /dev/null
@@ -0,0 +1,3060 @@
+/*
+ * BSS client mode implementation
+ * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright 2004, Instant802 Networks, Inc.
+ * Copyright 2005, Devicescape Software, Inc.
+ * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
+ * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* TODO:
+ * BSS table: use <BSSID,SSID> as the key to support multi-SSID APs
+ * order BSS list by RSSI(?) ("quality of AP")
+ * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE,
+ *    SSID)
+ */
+#include <linux/if_ether.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/wireless.h>
+#include <linux/random.h>
+#include <linux/etherdevice.h>
+#include <linux/rtnetlink.h>
+#include <net/iw_handler.h>
+#include <asm/types.h>
+#include <asm/delay.h>
+
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+#include "ieee80211_rate.h"
+#include "hostapd_ioctl.h"
+
+#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
+#define IEEE80211_AUTH_MAX_TRIES 3
+#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
+#define IEEE80211_ASSOC_MAX_TRIES 3
+#define IEEE80211_MONITORING_INTERVAL (2 * HZ)
+#define IEEE80211_PROBE_INTERVAL (60 * HZ)
+#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ)
+#define IEEE80211_SCAN_INTERVAL (2 * HZ)
+#define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ)
+#define IEEE80211_IBSS_JOIN_TIMEOUT (20 * HZ)
+
+#define IEEE80211_PROBE_DELAY (HZ / 33)
+#define IEEE80211_CHANNEL_TIME (HZ / 33)
+#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5)
+#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ)
+#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ)
+#define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ)
+
+#define IEEE80211_IBSS_MAX_STA_ENTRIES 128
+
+
+#define IEEE80211_FC(type, stype) cpu_to_le16(type | stype)
+
+#define ERP_INFO_USE_PROTECTION BIT(1)
+
+static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
+                                    u8 *ssid, size_t ssid_len);
+static struct ieee80211_sta_bss *
+ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid);
+static void ieee80211_rx_bss_put(struct net_device *dev,
+                                struct ieee80211_sta_bss *bss);
+static int ieee80211_sta_find_ibss(struct net_device *dev,
+                                  struct ieee80211_if_sta *ifsta);
+static int ieee80211_sta_wep_configured(struct net_device *dev);
+static int ieee80211_sta_start_scan(struct net_device *dev,
+                                   u8 *ssid, size_t ssid_len);
+static int ieee80211_sta_config_auth(struct net_device *dev,
+                                    struct ieee80211_if_sta *ifsta);
+
+
+/* Parsed Information Elements */
+struct ieee802_11_elems {
+       u8 *ssid;
+       u8 ssid_len;
+       u8 *supp_rates;
+       u8 supp_rates_len;
+       u8 *fh_params;
+       u8 fh_params_len;
+       u8 *ds_params;
+       u8 ds_params_len;
+       u8 *cf_params;
+       u8 cf_params_len;
+       u8 *tim;
+       u8 tim_len;
+       u8 *ibss_params;
+       u8 ibss_params_len;
+       u8 *challenge;
+       u8 challenge_len;
+       u8 *wpa;
+       u8 wpa_len;
+       u8 *rsn;
+       u8 rsn_len;
+       u8 *erp_info;
+       u8 erp_info_len;
+       u8 *ext_supp_rates;
+       u8 ext_supp_rates_len;
+       u8 *wmm_info;
+       u8 wmm_info_len;
+       u8 *wmm_param;
+       u8 wmm_param_len;
+};
+
+typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
+
+
+static ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
+                                      struct ieee802_11_elems *elems)
+{
+       size_t left = len;
+       u8 *pos = start;
+       int unknown = 0;
+
+       memset(elems, 0, sizeof(*elems));
+
+       while (left >= 2) {
+               u8 id, elen;
+
+               id = *pos++;
+               elen = *pos++;
+               left -= 2;
+
+               if (elen > left) {
+#if 0
+                       if (net_ratelimit())
+                               printk(KERN_DEBUG "IEEE 802.11 element parse "
+                                      "failed (id=%d elen=%d left=%d)\n",
+                                      id, elen, left);
+#endif
+                       return ParseFailed;
+               }
+
+               switch (id) {
+               case WLAN_EID_SSID:
+                       elems->ssid = pos;
+                       elems->ssid_len = elen;
+                       break;
+               case WLAN_EID_SUPP_RATES:
+                       elems->supp_rates = pos;
+                       elems->supp_rates_len = elen;
+                       break;
+               case WLAN_EID_FH_PARAMS:
+                       elems->fh_params = pos;
+                       elems->fh_params_len = elen;
+                       break;
+               case WLAN_EID_DS_PARAMS:
+                       elems->ds_params = pos;
+                       elems->ds_params_len = elen;
+                       break;
+               case WLAN_EID_CF_PARAMS:
+                       elems->cf_params = pos;
+                       elems->cf_params_len = elen;
+                       break;
+               case WLAN_EID_TIM:
+                       elems->tim = pos;
+                       elems->tim_len = elen;
+                       break;
+               case WLAN_EID_IBSS_PARAMS:
+                       elems->ibss_params = pos;
+                       elems->ibss_params_len = elen;
+                       break;
+               case WLAN_EID_CHALLENGE:
+                       elems->challenge = pos;
+                       elems->challenge_len = elen;
+                       break;
+               case WLAN_EID_WPA:
+                       if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
+                           pos[2] == 0xf2) {
+                               /* Microsoft OUI (00:50:F2) */
+                               if (pos[3] == 1) {
+                                       /* OUI Type 1 - WPA IE */
+                                       elems->wpa = pos;
+                                       elems->wpa_len = elen;
+                               } else if (elen >= 5 && pos[3] == 2) {
+                                       if (pos[4] == 0) {
+                                               elems->wmm_info = pos;
+                                               elems->wmm_info_len = elen;
+                                       } else if (pos[4] == 1) {
+                                               elems->wmm_param = pos;
+                                               elems->wmm_param_len = elen;
+                                       }
+                               }
+                       }
+                       break;
+               case WLAN_EID_RSN:
+                       elems->rsn = pos;
+                       elems->rsn_len = elen;
+                       break;
+               case WLAN_EID_ERP_INFO:
+                       elems->erp_info = pos;
+                       elems->erp_info_len = elen;
+                       break;
+               case WLAN_EID_EXT_SUPP_RATES:
+                       elems->ext_supp_rates = pos;
+                       elems->ext_supp_rates_len = elen;
+                       break;
+               default:
+#if 0
+                       printk(KERN_DEBUG "IEEE 802.11 element parse ignored "
+                                     "unknown element (id=%d elen=%d)\n",
+                                     id, elen);
+#endif
+                       unknown++;
+                       break;
+               }
+
+               left -= elen;
+               pos += elen;
+       }
+
+       /* Do not trigger error if left == 1 as Apple Airport base stations
+        * send AssocResps that are one spurious byte too long. */
+
+       return unknown ? ParseUnknown : ParseOK;
+}
+
+
+
+
+static int ecw2cw(int ecw)
+{
+       int cw = 1;
+       while (ecw > 0) {
+               cw <<= 1;
+               ecw--;
+       }
+       return cw - 1;
+}
+
+
+static void ieee80211_sta_wmm_params(struct net_device *dev,
+                                    struct ieee80211_if_sta *ifsta,
+                                    u8 *wmm_param, size_t wmm_param_len)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_tx_queue_params params;
+       size_t left;
+       int count;
+       u8 *pos;
+
+       if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
+               return;
+       count = wmm_param[6] & 0x0f;
+       if (count == ifsta->wmm_last_param_set)
+               return;
+       ifsta->wmm_last_param_set = count;
+
+       pos = wmm_param + 8;
+       left = wmm_param_len - 8;
+
+       memset(&params, 0, sizeof(params));
+
+       if (!local->ops->conf_tx)
+               return;
+
+       local->wmm_acm = 0;
+       for (; left >= 4; left -= 4, pos += 4) {
+               int aci = (pos[0] >> 5) & 0x03;
+               int acm = (pos[0] >> 4) & 0x01;
+               int queue;
+
+               switch (aci) {
+               case 1:
+                       queue = IEEE80211_TX_QUEUE_DATA3;
+                       if (acm) {
+                               local->wmm_acm |= BIT(0) | BIT(3);
+                       }
+                       break;
+               case 2:
+                       queue = IEEE80211_TX_QUEUE_DATA1;
+                       if (acm) {
+                               local->wmm_acm |= BIT(4) | BIT(5);
+                       }
+                       break;
+               case 3:
+                       queue = IEEE80211_TX_QUEUE_DATA0;
+                       if (acm) {
+                               local->wmm_acm |= BIT(6) | BIT(7);
+                       }
+                       break;
+               case 0:
+               default:
+                       queue = IEEE80211_TX_QUEUE_DATA2;
+                       if (acm) {
+                               local->wmm_acm |= BIT(1) | BIT(2);
+                       }
+                       break;
+               }
+
+               params.aifs = pos[0] & 0x0f;
+               params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
+               params.cw_min = ecw2cw(pos[1] & 0x0f);
+               /* TXOP is in units of 32 usec; burst_time in 0.1 ms */
+               params.burst_time = (pos[2] | (pos[3] << 8)) * 32 / 100;
+               printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
+                      "cWmin=%d cWmax=%d burst=%d\n",
+                      dev->name, queue, aci, acm, params.aifs, params.cw_min,
+                      params.cw_max, params.burst_time);
+               /* TODO: handle ACM (block TX, fallback to next lowest allowed
+                * AC for now) */
+               if (local->ops->conf_tx(local_to_hw(local), queue, &params)) {
+                       printk(KERN_DEBUG "%s: failed to set TX queue "
+                              "parameters for queue %d\n", dev->name, queue);
+               }
+       }
+}
+
+
+static void ieee80211_sta_send_associnfo(struct net_device *dev,
+                                        struct ieee80211_if_sta *ifsta)
+{
+       char *buf;
+       size_t len;
+       int i;
+       union iwreq_data wrqu;
+
+       if (!ifsta->assocreq_ies && !ifsta->assocresp_ies)
+               return;
+
+       buf = kmalloc(50 + 2 * (ifsta->assocreq_ies_len +
+                               ifsta->assocresp_ies_len), GFP_ATOMIC);
+       if (!buf)
+               return;
+
+       len = sprintf(buf, "ASSOCINFO(");
+       if (ifsta->assocreq_ies) {
+               len += sprintf(buf + len, "ReqIEs=");
+               for (i = 0; i < ifsta->assocreq_ies_len; i++) {
+                       len += sprintf(buf + len, "%02x",
+                                      ifsta->assocreq_ies[i]);
+               }
+       }
+       if (ifsta->assocresp_ies) {
+               if (ifsta->assocreq_ies)
+                       len += sprintf(buf + len, " ");
+               len += sprintf(buf + len, "RespIEs=");
+               for (i = 0; i < ifsta->assocresp_ies_len; i++) {
+                       len += sprintf(buf + len, "%02x",
+                                      ifsta->assocresp_ies[i]);
+               }
+       }
+       len += sprintf(buf + len, ")");
+
+       if (len > IW_CUSTOM_MAX) {
+               len = sprintf(buf, "ASSOCRESPIE=");
+               for (i = 0; i < ifsta->assocresp_ies_len; i++) {
+                       len += sprintf(buf + len, "%02x",
+                                      ifsta->assocresp_ies[i]);
+               }
+       }
+
+       memset(&wrqu, 0, sizeof(wrqu));
+       wrqu.data.length = len;
+       wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
+
+       kfree(buf);
+}
+
+
+static void ieee80211_set_associated(struct net_device *dev,
+                                    struct ieee80211_if_sta *ifsta, int assoc)
+{
+       union iwreq_data wrqu;
+
+       if (ifsta->associated == assoc)
+               return;
+
+       ifsta->associated = assoc;
+
+       if (assoc) {
+               struct ieee80211_sub_if_data *sdata;
+               sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+               if (sdata->type != IEEE80211_IF_TYPE_STA)
+                       return;
+               netif_carrier_on(dev);
+               ifsta->prev_bssid_set = 1;
+               memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
+               memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN);
+               ieee80211_sta_send_associnfo(dev, ifsta);
+       } else {
+               netif_carrier_off(dev);
+               memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+       }
+       wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+       wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+       ifsta->last_probe = jiffies;
+}
+
+static void ieee80211_set_disassoc(struct net_device *dev,
+                                  struct ieee80211_if_sta *ifsta, int deauth)
+{
+       if (deauth)
+               ifsta->auth_tries = 0;
+       ifsta->assoc_tries = 0;
+       ieee80211_set_associated(dev, ifsta, 0);
+}
+
+static void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb,
+                            int encrypt)
+{
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_tx_packet_data *pkt_data;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       skb->dev = sdata->local->mdev;
+       skb_set_mac_header(skb, 0);
+       skb_set_network_header(skb, 0);
+       skb_set_transport_header(skb, 0);
+
+       pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
+       memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
+       pkt_data->ifindex = sdata->dev->ifindex;
+       pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT);
+       pkt_data->do_not_encrypt = !encrypt;
+
+       dev_queue_xmit(skb);
+}
+
+
+static void ieee80211_send_auth(struct net_device *dev,
+                               struct ieee80211_if_sta *ifsta,
+                               int transaction, u8 *extra, size_t extra_len,
+                               int encrypt)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct sk_buff *skb;
+       struct ieee80211_mgmt *mgmt;
+
+       skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+                           sizeof(*mgmt) + 6 + extra_len);
+       if (!skb) {
+               printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
+                      "frame\n", dev->name);
+               return;
+       }
+       skb_reserve(skb, local->hw.extra_tx_headroom);
+
+       mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6);
+       memset(mgmt, 0, 24 + 6);
+       mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+                                          IEEE80211_STYPE_AUTH);
+       if (encrypt)
+               mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+       memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
+       memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+       memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+       mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg);
+       mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
+       ifsta->auth_transaction = transaction + 1;
+       mgmt->u.auth.status_code = cpu_to_le16(0);
+       if (extra)
+               memcpy(skb_put(skb, extra_len), extra, extra_len);
+
+       ieee80211_sta_tx(dev, skb, encrypt);
+}
+
+
+static void ieee80211_authenticate(struct net_device *dev,
+                                  struct ieee80211_if_sta *ifsta)
+{
+       ifsta->auth_tries++;
+       if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
+               printk(KERN_DEBUG "%s: authentication with AP " MAC_FMT
+                      " timed out\n",
+                      dev->name, MAC_ARG(ifsta->bssid));
+               ifsta->state = IEEE80211_DISABLED;
+               return;
+       }
+
+       ifsta->state = IEEE80211_AUTHENTICATE;
+       printk(KERN_DEBUG "%s: authenticate with AP " MAC_FMT "\n",
+              dev->name, MAC_ARG(ifsta->bssid));
+
+       ieee80211_send_auth(dev, ifsta, 1, NULL, 0, 0);
+
+       mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
+}
+
+
+static void ieee80211_send_assoc(struct net_device *dev,
+                                struct ieee80211_if_sta *ifsta)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_hw_mode *mode;
+       struct sk_buff *skb;
+       struct ieee80211_mgmt *mgmt;
+       u8 *pos, *ies;
+       int i, len;
+       u16 capab;
+       struct ieee80211_sta_bss *bss;
+       int wmm = 0;
+
+       skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+                           sizeof(*mgmt) + 200 + ifsta->extra_ie_len +
+                           ifsta->ssid_len);
+       if (!skb) {
+               printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
+                      "frame\n", dev->name);
+               return;
+       }
+       skb_reserve(skb, local->hw.extra_tx_headroom);
+
+       mode = local->oper_hw_mode;
+       capab = ifsta->capab;
+       if (mode->mode == MODE_IEEE80211G) {
+               capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME |
+                       WLAN_CAPABILITY_SHORT_PREAMBLE;
+       }
+       bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
+       if (bss) {
+               if (bss->capability & WLAN_CAPABILITY_PRIVACY)
+                       capab |= WLAN_CAPABILITY_PRIVACY;
+               if (bss->wmm_ie) {
+                       wmm = 1;
+               }
+               ieee80211_rx_bss_put(dev, bss);
+       }
+
+       mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+       memset(mgmt, 0, 24);
+       memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
+       memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+       memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+
+       if (ifsta->prev_bssid_set) {
+               skb_put(skb, 10);
+               mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+                                                  IEEE80211_STYPE_REASSOC_REQ);
+               mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
+               mgmt->u.reassoc_req.listen_interval = cpu_to_le16(1);
+               memcpy(mgmt->u.reassoc_req.current_ap, ifsta->prev_bssid,
+                      ETH_ALEN);
+       } else {
+               skb_put(skb, 4);
+               mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+                                                  IEEE80211_STYPE_ASSOC_REQ);
+               mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
+               mgmt->u.assoc_req.listen_interval = cpu_to_le16(1);
+       }
+
+       /* SSID */
+       ies = pos = skb_put(skb, 2 + ifsta->ssid_len);
+       *pos++ = WLAN_EID_SSID;
+       *pos++ = ifsta->ssid_len;
+       memcpy(pos, ifsta->ssid, ifsta->ssid_len);
+
+       len = mode->num_rates;
+       if (len > 8)
+               len = 8;
+       pos = skb_put(skb, len + 2);
+       *pos++ = WLAN_EID_SUPP_RATES;
+       *pos++ = len;
+       for (i = 0; i < len; i++) {
+               int rate = mode->rates[i].rate;
+               if (mode->mode == MODE_ATHEROS_TURBO)
+                       rate /= 2;
+               *pos++ = (u8) (rate / 5);
+       }
+
+       if (mode->num_rates > len) {
+               pos = skb_put(skb, mode->num_rates - len + 2);
+               *pos++ = WLAN_EID_EXT_SUPP_RATES;
+               *pos++ = mode->num_rates - len;
+               for (i = len; i < mode->num_rates; i++) {
+                       int rate = mode->rates[i].rate;
+                       if (mode->mode == MODE_ATHEROS_TURBO)
+                               rate /= 2;
+                       *pos++ = (u8) (rate / 5);
+               }
+       }
+
+       if (ifsta->extra_ie) {
+               pos = skb_put(skb, ifsta->extra_ie_len);
+               memcpy(pos, ifsta->extra_ie, ifsta->extra_ie_len);
+       }
+
+       if (wmm && ifsta->wmm_enabled) {
+               pos = skb_put(skb, 9);
+               *pos++ = WLAN_EID_VENDOR_SPECIFIC;
+               *pos++ = 7; /* len */
+               *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
+               *pos++ = 0x50;
+               *pos++ = 0xf2;
+               *pos++ = 2; /* WME */
+               *pos++ = 0; /* WME info */
+               *pos++ = 1; /* WME ver */
+               *pos++ = 0;
+       }
+
+       kfree(ifsta->assocreq_ies);
+       ifsta->assocreq_ies_len = (skb->data + skb->len) - ies;
+       ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_ATOMIC);
+       if (ifsta->assocreq_ies)
+               memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len);
+
+       ieee80211_sta_tx(dev, skb, 0);
+}
+
+
+static void ieee80211_send_deauth(struct net_device *dev,
+                                 struct ieee80211_if_sta *ifsta, u16 reason)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct sk_buff *skb;
+       struct ieee80211_mgmt *mgmt;
+
+       skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
+       if (!skb) {
+               printk(KERN_DEBUG "%s: failed to allocate buffer for deauth "
+                      "frame\n", dev->name);
+               return;
+       }
+       skb_reserve(skb, local->hw.extra_tx_headroom);
+
+       mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+       memset(mgmt, 0, 24);
+       memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
+       memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+       memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+       mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+                                          IEEE80211_STYPE_DEAUTH);
+       skb_put(skb, 2);
+       mgmt->u.deauth.reason_code = cpu_to_le16(reason);
+
+       ieee80211_sta_tx(dev, skb, 0);
+}
+
+
+static void ieee80211_send_disassoc(struct net_device *dev,
+                                   struct ieee80211_if_sta *ifsta, u16 reason)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct sk_buff *skb;
+       struct ieee80211_mgmt *mgmt;
+
+       skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
+       if (!skb) {
+               printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc "
+                      "frame\n", dev->name);
+               return;
+       }
+       skb_reserve(skb, local->hw.extra_tx_headroom);
+
+       mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+       memset(mgmt, 0, 24);
+       memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
+       memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+       memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+       mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+                                          IEEE80211_STYPE_DISASSOC);
+       skb_put(skb, 2);
+       mgmt->u.disassoc.reason_code = cpu_to_le16(reason);
+
+       ieee80211_sta_tx(dev, skb, 0);
+}
+
+
+static int ieee80211_privacy_mismatch(struct net_device *dev,
+                                     struct ieee80211_if_sta *ifsta)
+{
+       struct ieee80211_sta_bss *bss;
+       int res = 0;
+
+       if (!ifsta || ifsta->mixed_cell ||
+           ifsta->key_mgmt != IEEE80211_KEY_MGMT_NONE)
+               return 0;
+
+       bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
+       if (!bss)
+               return 0;
+
+       if (ieee80211_sta_wep_configured(dev) !=
+           !!(bss->capability & WLAN_CAPABILITY_PRIVACY))
+               res = 1;
+
+       ieee80211_rx_bss_put(dev, bss);
+
+       return res;
+}
+
+
+static void ieee80211_associate(struct net_device *dev,
+                               struct ieee80211_if_sta *ifsta)
+{
+       ifsta->assoc_tries++;
+       if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) {
+               printk(KERN_DEBUG "%s: association with AP " MAC_FMT
+                      " timed out\n",
+                      dev->name, MAC_ARG(ifsta->bssid));
+               ifsta->state = IEEE80211_DISABLED;
+               return;
+       }
+
+       ifsta->state = IEEE80211_ASSOCIATE;
+       printk(KERN_DEBUG "%s: associate with AP " MAC_FMT "\n",
+              dev->name, MAC_ARG(ifsta->bssid));
+       if (ieee80211_privacy_mismatch(dev, ifsta)) {
+               printk(KERN_DEBUG "%s: mismatch in privacy configuration and "
+                      "mixed-cell disabled - abort association\n", dev->name);
+               ifsta->state = IEEE80211_DISABLED;
+               return;
+       }
+
+       ieee80211_send_assoc(dev, ifsta);
+
+       mod_timer(&ifsta->timer, jiffies + IEEE80211_ASSOC_TIMEOUT);
+}
+
+
+static void ieee80211_associated(struct net_device *dev,
+                                struct ieee80211_if_sta *ifsta)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct sta_info *sta;
+       int disassoc;
+
+       /* TODO: start monitoring current AP signal quality and number of
+        * missed beacons. Scan other channels every now and then and search
+        * for better APs. */
+       /* TODO: remove expired BSSes */
+
+       ifsta->state = IEEE80211_ASSOCIATED;
+
+       sta = sta_info_get(local, ifsta->bssid);
+       if (!sta) {
+               printk(KERN_DEBUG "%s: No STA entry for own AP " MAC_FMT "\n",
+                      dev->name, MAC_ARG(ifsta->bssid));
+               disassoc = 1;
+       } else {
+               disassoc = 0;
+               if (time_after(jiffies,
+                              sta->last_rx + IEEE80211_MONITORING_INTERVAL)) {
+                       if (ifsta->probereq_poll) {
+                               printk(KERN_DEBUG "%s: No ProbeResp from "
+                                      "current AP " MAC_FMT " - assume out of "
+                                      "range\n",
+                                      dev->name, MAC_ARG(ifsta->bssid));
+                               disassoc = 1;
+                               sta_info_free(sta, 0);
+                               ifsta->probereq_poll = 0;
+                       } else {
+                               ieee80211_send_probe_req(dev, ifsta->bssid,
+                                                        local->scan_ssid,
+                                                        local->scan_ssid_len);
+                               ifsta->probereq_poll = 1;
+                       }
+               } else {
+                       ifsta->probereq_poll = 0;
+                       if (time_after(jiffies, ifsta->last_probe +
+                                      IEEE80211_PROBE_INTERVAL)) {
+                               ifsta->last_probe = jiffies;
+                               ieee80211_send_probe_req(dev, ifsta->bssid,
+                                                        ifsta->ssid,
+                                                        ifsta->ssid_len);
+                       }
+               }
+               sta_info_put(sta);
+       }
+       if (disassoc) {
+               union iwreq_data wrqu;
+               memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+               wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+               wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+               mod_timer(&ifsta->timer, jiffies +
+                                     IEEE80211_MONITORING_INTERVAL + 30 * HZ);
+       } else {
+               mod_timer(&ifsta->timer, jiffies +
+                                     IEEE80211_MONITORING_INTERVAL);
+       }
+}
+
+
+static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
+                                    u8 *ssid, size_t ssid_len)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_hw_mode *mode;
+       struct sk_buff *skb;
+       struct ieee80211_mgmt *mgmt;
+       u8 *pos, *supp_rates, *esupp_rates = NULL;
+       int i;
+
+       skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200);
+       if (!skb) {
+               printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
+                      "request\n", dev->name);
+               return;
+       }
+       skb_reserve(skb, local->hw.extra_tx_headroom);
+
+       mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
+       memset(mgmt, 0, 24);
+       mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+                                          IEEE80211_STYPE_PROBE_REQ);
+       memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+       if (dst) {
+               memcpy(mgmt->da, dst, ETH_ALEN);
+               memcpy(mgmt->bssid, dst, ETH_ALEN);
+       } else {
+               memset(mgmt->da, 0xff, ETH_ALEN);
+               memset(mgmt->bssid, 0xff, ETH_ALEN);
+       }
+       pos = skb_put(skb, 2 + ssid_len);
+       *pos++ = WLAN_EID_SSID;
+       *pos++ = ssid_len;
+       memcpy(pos, ssid, ssid_len);
+
+       supp_rates = skb_put(skb, 2);
+       supp_rates[0] = WLAN_EID_SUPP_RATES;
+       supp_rates[1] = 0;
+       mode = local->oper_hw_mode;
+       for (i = 0; i < mode->num_rates; i++) {
+               struct ieee80211_rate *rate = &mode->rates[i];
+               if (!(rate->flags & IEEE80211_RATE_SUPPORTED))
+                       continue;
+               if (esupp_rates) {
+                       pos = skb_put(skb, 1);
+                       esupp_rates[1]++;
+               } else if (supp_rates[1] == 8) {
+                       esupp_rates = skb_put(skb, 3);
+                       esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES;
+                       esupp_rates[1] = 1;
+                       pos = &esupp_rates[2];
+               } else {
+                       pos = skb_put(skb, 1);
+                       supp_rates[1]++;
+               }
+               if (mode->mode == MODE_ATHEROS_TURBO)
+                       *pos = rate->rate / 10;
+               else
+                       *pos = rate->rate / 5;
+       }
+
+       ieee80211_sta_tx(dev, skb, 0);
+}
+
+
+static int ieee80211_sta_wep_configured(struct net_device *dev)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       if (!sdata || !sdata->default_key ||
+           sdata->default_key->alg != ALG_WEP)
+               return 0;
+       return 1;
+}
+
+
+static void ieee80211_auth_completed(struct net_device *dev,
+                                    struct ieee80211_if_sta *ifsta)
+{
+       printk(KERN_DEBUG "%s: authenticated\n", dev->name);
+       ifsta->authenticated = 1;
+       ieee80211_associate(dev, ifsta);
+}
+
+
+static void ieee80211_auth_challenge(struct net_device *dev,
+                                    struct ieee80211_if_sta *ifsta,
+                                    struct ieee80211_mgmt *mgmt,
+                                    size_t len)
+{
+       u8 *pos;
+       struct ieee802_11_elems elems;
+
+       printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name);
+       pos = mgmt->u.auth.variable;
+       if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems)
+           == ParseFailed) {
+               printk(KERN_DEBUG "%s: failed to parse Auth(challenge)\n",
+                      dev->name);
+               return;
+       }
+       if (!elems.challenge) {
+               printk(KERN_DEBUG "%s: no challenge IE in shared key auth "
+                      "frame\n", dev->name);
+               return;
+       }
+       ieee80211_send_auth(dev, ifsta, 3, elems.challenge - 2,
+                           elems.challenge_len + 2, 1);
+}
+
+
+static void ieee80211_rx_mgmt_auth(struct net_device *dev,
+                                  struct ieee80211_if_sta *ifsta,
+                                  struct ieee80211_mgmt *mgmt,
+                                  size_t len)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       u16 auth_alg, auth_transaction, status_code;
+
+       if (ifsta->state != IEEE80211_AUTHENTICATE &&
+           sdata->type != IEEE80211_IF_TYPE_IBSS) {
+               printk(KERN_DEBUG "%s: authentication frame received from "
+                      MAC_FMT ", but not in authenticate state - ignored\n",
+                      dev->name, MAC_ARG(mgmt->sa));
+               return;
+       }
+
+       if (len < 24 + 6) {
+               printk(KERN_DEBUG "%s: too short (%zd) authentication frame "
+                      "received from " MAC_FMT " - ignored\n",
+                      dev->name, len, MAC_ARG(mgmt->sa));
+               return;
+       }
+
+       if (sdata->type != IEEE80211_IF_TYPE_IBSS &&
+           memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
+               printk(KERN_DEBUG "%s: authentication frame received from "
+                      "unknown AP (SA=" MAC_FMT " BSSID=" MAC_FMT ") - "
+                      "ignored\n", dev->name, MAC_ARG(mgmt->sa),
+                      MAC_ARG(mgmt->bssid));
+               return;
+       }
+
+       if (sdata->type != IEEE80211_IF_TYPE_IBSS &&
+           memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) {
+               printk(KERN_DEBUG "%s: authentication frame received from "
+                      "unknown BSSID (SA=" MAC_FMT " BSSID=" MAC_FMT ") - "
+                      "ignored\n", dev->name, MAC_ARG(mgmt->sa),
+                      MAC_ARG(mgmt->bssid));
+               return;
+       }
+
+       auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
+       auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
+       status_code = le16_to_cpu(mgmt->u.auth.status_code);
+
+       printk(KERN_DEBUG "%s: RX authentication from " MAC_FMT " (alg=%d "
+              "transaction=%d status=%d)\n",
+              dev->name, MAC_ARG(mgmt->sa), auth_alg,
+              auth_transaction, status_code);
+
+       if (sdata->type == IEEE80211_IF_TYPE_IBSS) {
+               /* IEEE 802.11 standard does not require authentication in IBSS
+                * networks and most implementations do not seem to use it.
+                * However, try to reply to authentication attempts if someone
+                * has actually implemented this.
+                * TODO: Could implement shared key authentication. */
+               if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) {
+                       printk(KERN_DEBUG "%s: unexpected IBSS authentication "
+                              "frame (alg=%d transaction=%d)\n",
+                              dev->name, auth_alg, auth_transaction);
+                       return;
+               }
+               ieee80211_send_auth(dev, ifsta, 2, NULL, 0, 0);
+       }
+
+       if (auth_alg != ifsta->auth_alg ||
+           auth_transaction != ifsta->auth_transaction) {
+               printk(KERN_DEBUG "%s: unexpected authentication frame "
+                      "(alg=%d transaction=%d)\n",
+                      dev->name, auth_alg, auth_transaction);
+               return;
+       }
+
+       if (status_code != WLAN_STATUS_SUCCESS) {
+               printk(KERN_DEBUG "%s: AP denied authentication (auth_alg=%d "
+                      "code=%d)\n", dev->name, ifsta->auth_alg, status_code);
+               if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
+                       u8 algs[3];
+                       const int num_algs = ARRAY_SIZE(algs);
+                       int i, pos;
+                       algs[0] = algs[1] = algs[2] = 0xff;
+                       if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN)
+                               algs[0] = WLAN_AUTH_OPEN;
+                       if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
+                               algs[1] = WLAN_AUTH_SHARED_KEY;
+                       if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP)
+                               algs[2] = WLAN_AUTH_LEAP;
+                       if (ifsta->auth_alg == WLAN_AUTH_OPEN)
+                               pos = 0;
+                       else if (ifsta->auth_alg == WLAN_AUTH_SHARED_KEY)
+                               pos = 1;
+                       else
+                               pos = 2;
+                       for (i = 0; i < num_algs; i++) {
+                               pos++;
+                               if (pos >= num_algs)
+                                       pos = 0;
+                               if (algs[pos] == ifsta->auth_alg ||
+                                   algs[pos] == 0xff)
+                                       continue;
+                               if (algs[pos] == WLAN_AUTH_SHARED_KEY &&
+                                   !ieee80211_sta_wep_configured(dev))
+                                       continue;
+                               ifsta->auth_alg = algs[pos];
+                               printk(KERN_DEBUG "%s: set auth_alg=%d for "
+                                      "next try\n",
+                                      dev->name, ifsta->auth_alg);
+                               break;
+                       }
+               }
+               return;
+       }
+
+       switch (ifsta->auth_alg) {
+       case WLAN_AUTH_OPEN:
+       case WLAN_AUTH_LEAP:
+               ieee80211_auth_completed(dev, ifsta);
+               break;
+       case WLAN_AUTH_SHARED_KEY:
+               if (ifsta->auth_transaction == 4)
+                       ieee80211_auth_completed(dev, ifsta);
+               else
+                       ieee80211_auth_challenge(dev, ifsta, mgmt, len);
+               break;
+       }
+}
+
+
+static void ieee80211_rx_mgmt_deauth(struct net_device *dev,
+                                    struct ieee80211_if_sta *ifsta,
+                                    struct ieee80211_mgmt *mgmt,
+                                    size_t len)
+{
+       u16 reason_code;
+
+       if (len < 24 + 2) {
+               printk(KERN_DEBUG "%s: too short (%zd) deauthentication frame "
+                      "received from " MAC_FMT " - ignored\n",
+                      dev->name, len, MAC_ARG(mgmt->sa));
+               return;
+       }
+
+       if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
+               printk(KERN_DEBUG "%s: deauthentication frame received from "
+                      "unknown AP (SA=" MAC_FMT " BSSID=" MAC_FMT ") - "
+                      "ignored\n", dev->name, MAC_ARG(mgmt->sa),
+                      MAC_ARG(mgmt->bssid));
+               return;
+       }
+
+       reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
+
+       printk(KERN_DEBUG "%s: RX deauthentication from " MAC_FMT
+              " (reason=%d)\n",
+              dev->name, MAC_ARG(mgmt->sa), reason_code);
+
+       if (ifsta->authenticated) {
+               printk(KERN_DEBUG "%s: deauthenticated\n", dev->name);
+       }
+
+       if (ifsta->state == IEEE80211_AUTHENTICATE ||
+           ifsta->state == IEEE80211_ASSOCIATE ||
+           ifsta->state == IEEE80211_ASSOCIATED) {
+               ifsta->state = IEEE80211_AUTHENTICATE;
+               mod_timer(&ifsta->timer, jiffies +
+                                     IEEE80211_RETRY_AUTH_INTERVAL);
+       }
+
+       ieee80211_set_disassoc(dev, ifsta, 1);
+       ifsta->authenticated = 0;
+}
+
+
+static void ieee80211_rx_mgmt_disassoc(struct net_device *dev,
+                                      struct ieee80211_if_sta *ifsta,
+                                      struct ieee80211_mgmt *mgmt,
+                                      size_t len)
+{
+       u16 reason_code;
+
+       if (len < 24 + 2) {
+               printk(KERN_DEBUG "%s: too short (%zd) disassociation frame "
+                      "received from " MAC_FMT " - ignored\n",
+                      dev->name, len, MAC_ARG(mgmt->sa));
+               return;
+       }
+
+       if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
+               printk(KERN_DEBUG "%s: disassociation frame received from "
+                      "unknown AP (SA=" MAC_FMT " BSSID=" MAC_FMT ") - "
+                      "ignored\n", dev->name, MAC_ARG(mgmt->sa),
+                      MAC_ARG(mgmt->bssid));
+               return;
+       }
+
+       reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
+
+       printk(KERN_DEBUG "%s: RX disassociation from " MAC_FMT
+              " (reason=%d)\n",
+              dev->name, MAC_ARG(mgmt->sa), reason_code);
+
+       if (ifsta->associated)
+               printk(KERN_DEBUG "%s: disassociated\n", dev->name);
+
+       if (ifsta->state == IEEE80211_ASSOCIATED) {
+               ifsta->state = IEEE80211_ASSOCIATE;
+               mod_timer(&ifsta->timer, jiffies +
+                                     IEEE80211_RETRY_AUTH_INTERVAL);
+       }
+
+       ieee80211_set_disassoc(dev, ifsta, 0);
+}
+
+
+static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
+                                        struct ieee80211_if_sta *ifsta,
+                                        struct ieee80211_mgmt *mgmt,
+                                        size_t len,
+                                        int reassoc)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_hw_mode *mode;
+       struct sta_info *sta;
+       u32 rates;
+       u16 capab_info, status_code, aid;
+       struct ieee802_11_elems elems;
+       u8 *pos;
+       int i, j;
+
+       /* AssocResp and ReassocResp have identical structure, so process both
+        * of them in this function. */
+
+       if (ifsta->state != IEEE80211_ASSOCIATE) {
+               printk(KERN_DEBUG "%s: association frame received from "
+                      MAC_FMT ", but not in associate state - ignored\n",
+                      dev->name, MAC_ARG(mgmt->sa));
+               return;
+       }
+
+       if (len < 24 + 6) {
+               printk(KERN_DEBUG "%s: too short (%zd) association frame "
+                      "received from " MAC_FMT " - ignored\n",
+                      dev->name, len, MAC_ARG(mgmt->sa));
+               return;
+       }
+
+       if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
+               printk(KERN_DEBUG "%s: association frame received from "
+                      "unknown AP (SA=" MAC_FMT " BSSID=" MAC_FMT ") - "
+                      "ignored\n", dev->name, MAC_ARG(mgmt->sa),
+                      MAC_ARG(mgmt->bssid));
+               return;
+       }
+
+       capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
+       status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
+       aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
+       if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
+               printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
+                      "set\n", dev->name, aid);
+       aid &= ~(BIT(15) | BIT(14));
+
+       printk(KERN_DEBUG "%s: RX %sssocResp from " MAC_FMT " (capab=0x%x "
+              "status=%d aid=%d)\n",
+              dev->name, reassoc ? "Rea" : "A", MAC_ARG(mgmt->sa),
+              capab_info, status_code, aid);
+
+       if (status_code != WLAN_STATUS_SUCCESS) {
+               printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
+                      dev->name, status_code);
+               return;
+       }
+
+       pos = mgmt->u.assoc_resp.variable;
+       if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems)
+           == ParseFailed) {
+               printk(KERN_DEBUG "%s: failed to parse AssocResp\n",
+                      dev->name);
+               return;
+       }
+
+       if (!elems.supp_rates) {
+               printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
+                      dev->name);
+               return;
+       }
+
+       printk(KERN_DEBUG "%s: associated\n", dev->name);
+       ifsta->aid = aid;
+       ifsta->ap_capab = capab_info;
+
+       kfree(ifsta->assocresp_ies);
+       ifsta->assocresp_ies_len = len - (pos - (u8 *) mgmt);
+       ifsta->assocresp_ies = kmalloc(ifsta->assocresp_ies_len, GFP_ATOMIC);
+       if (ifsta->assocresp_ies)
+               memcpy(ifsta->assocresp_ies, pos, ifsta->assocresp_ies_len);
+
+       ieee80211_set_associated(dev, ifsta, 1);
+
+       /* Add STA entry for the AP */
+       sta = sta_info_get(local, ifsta->bssid);
+       if (!sta) {
+               struct ieee80211_sta_bss *bss;
+               sta = sta_info_add(local, dev, ifsta->bssid, GFP_ATOMIC);
+               if (!sta) {
+                       printk(KERN_DEBUG "%s: failed to add STA entry for the"
+                              " AP\n", dev->name);
+                       return;
+               }
+               bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
+               if (bss) {
+                       sta->last_rssi = bss->rssi;
+                       sta->last_signal = bss->signal;
+                       sta->last_noise = bss->noise;
+                       ieee80211_rx_bss_put(dev, bss);
+               }
+       }
+
+       sta->dev = dev;
+       sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
+       sta->assoc_ap = 1;
+
+       rates = 0;
+       mode = local->oper_hw_mode;
+       for (i = 0; i < elems.supp_rates_len; i++) {
+               int rate = (elems.supp_rates[i] & 0x7f) * 5;
+               if (mode->mode == MODE_ATHEROS_TURBO)
+                       rate *= 2;
+               for (j = 0; j < mode->num_rates; j++)
+                       if (mode->rates[j].rate == rate)
+                               rates |= BIT(j);
+       }
+       for (i = 0; i < elems.ext_supp_rates_len; i++) {
+               int rate = (elems.ext_supp_rates[i] & 0x7f) * 5;
+               if (mode->mode == MODE_ATHEROS_TURBO)
+                       rate *= 2;
+               for (j = 0; j < mode->num_rates; j++)
+                       if (mode->rates[j].rate == rate)
+                               rates |= BIT(j);
+       }
+       sta->supp_rates = rates;
+
+       rate_control_rate_init(sta, local);
+
+       if (elems.wmm_param && ifsta->wmm_enabled) {
+               sta->flags |= WLAN_STA_WME;
+               ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
+                                        elems.wmm_param_len);
+       }
+
+
+       sta_info_put(sta);
+
+       ieee80211_associated(dev, ifsta);
+}
+
+
+/* Caller must hold local->sta_bss_lock */
+static void __ieee80211_rx_bss_hash_add(struct net_device *dev,
+                                       struct ieee80211_sta_bss *bss)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       bss->hnext = local->sta_bss_hash[STA_HASH(bss->bssid)];
+       local->sta_bss_hash[STA_HASH(bss->bssid)] = bss;
+}
+
+
+/* Caller must hold local->sta_bss_lock */
+static void __ieee80211_rx_bss_hash_del(struct net_device *dev,
+                                       struct ieee80211_sta_bss *bss)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sta_bss *b, *prev = NULL;
+       b = local->sta_bss_hash[STA_HASH(bss->bssid)];
+       while (b) {
+               if (b == bss) {
+                       if (!prev)
+                               local->sta_bss_hash[STA_HASH(bss->bssid)] =
+                                       bss->hnext;
+                       else
+                               prev->hnext = bss->hnext;
+                       break;
+               }
+               prev = b;
+               b = b->hnext;
+       }
+}
+
+
+static struct ieee80211_sta_bss *
+ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sta_bss *bss;
+
+       bss = kmalloc(sizeof(*bss), GFP_ATOMIC);
+       if (!bss)
+               return NULL;
+       memset(bss, 0, sizeof(*bss));
+       atomic_inc(&bss->users);
+       atomic_inc(&bss->users);
+       memcpy(bss->bssid, bssid, ETH_ALEN);
+
+       spin_lock_bh(&local->sta_bss_lock);
+       /* TODO: order by RSSI? */
+       list_add_tail(&bss->list, &local->sta_bss_list);
+       __ieee80211_rx_bss_hash_add(dev, bss);
+       spin_unlock_bh(&local->sta_bss_lock);
+       return bss;
+}
+
+
+static struct ieee80211_sta_bss *
+ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sta_bss *bss;
+
+       spin_lock_bh(&local->sta_bss_lock);
+       bss = local->sta_bss_hash[STA_HASH(bssid)];
+       while (bss) {
+               if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0) {
+                       atomic_inc(&bss->users);
+                       break;
+               }
+               bss = bss->hnext;
+       }
+       spin_unlock_bh(&local->sta_bss_lock);
+       return bss;
+}
+
+
+static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss)
+{
+       kfree(bss->wpa_ie);
+       kfree(bss->rsn_ie);
+       kfree(bss->wmm_ie);
+       kfree(bss);
+}
+
+
+static void ieee80211_rx_bss_put(struct net_device *dev,
+                                struct ieee80211_sta_bss *bss)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       if (!atomic_dec_and_test(&bss->users))
+               return;
+
+       spin_lock_bh(&local->sta_bss_lock);
+       __ieee80211_rx_bss_hash_del(dev, bss);
+       list_del(&bss->list);
+       spin_unlock_bh(&local->sta_bss_lock);
+       ieee80211_rx_bss_free(bss);
+}
+
+
+void ieee80211_rx_bss_list_init(struct net_device *dev)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       spin_lock_init(&local->sta_bss_lock);
+       INIT_LIST_HEAD(&local->sta_bss_list);
+}
+
+
+void ieee80211_rx_bss_list_deinit(struct net_device *dev)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sta_bss *bss, *tmp;
+
+       list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list)
+               ieee80211_rx_bss_put(dev, bss);
+}
+
+
+static void ieee80211_rx_bss_info(struct net_device *dev,
+                                 struct ieee80211_mgmt *mgmt,
+                                 size_t len,
+                                 struct ieee80211_rx_status *rx_status,
+                                 int beacon)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee802_11_elems elems;
+       size_t baselen;
+       int channel, invalid = 0, clen;
+       struct ieee80211_sta_bss *bss;
+       struct sta_info *sta;
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       u64 timestamp;
+
+       if (!beacon && memcmp(mgmt->da, dev->dev_addr, ETH_ALEN))
+               return; /* ignore ProbeResp to foreign address */
+
+#if 0
+       printk(KERN_DEBUG "%s: RX %s from " MAC_FMT " to " MAC_FMT "\n",
+              dev->name, beacon ? "Beacon" : "Probe Response",
+              MAC_ARG(mgmt->sa), MAC_ARG(mgmt->da));
+#endif
+
+       baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
+       if (baselen > len)
+               return;
+
+       timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
+
+       if (sdata->type == IEEE80211_IF_TYPE_IBSS && beacon &&
+           memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
+#ifdef CONFIG_MAC80211_IBSS_DEBUG
+               static unsigned long last_tsf_debug = 0;
+               u64 tsf;
+               if (local->ops->get_tsf)
+                       tsf = local->ops->get_tsf(local_to_hw(local));
+               else
+                       tsf = -1LLU;
+               if (time_after(jiffies, last_tsf_debug + 5 * HZ)) {
+                       printk(KERN_DEBUG "RX beacon SA=" MAC_FMT " BSSID="
+                              MAC_FMT " TSF=0x%llx BCN=0x%llx diff=%lld "
+                              "@%lu\n",
+                              MAC_ARG(mgmt->sa), MAC_ARG(mgmt->bssid),
+                              (unsigned long long)tsf,
+                              (unsigned long long)timestamp,
+                              (unsigned long long)(tsf - timestamp),
+                              jiffies);
+                       last_tsf_debug = jiffies;
+               }
+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+       }
+
+       if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen,
+                                  &elems) == ParseFailed)
+               invalid = 1;
+
+       if (sdata->type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&
+           memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&
+           (sta = sta_info_get(local, mgmt->sa))) {
+               struct ieee80211_hw_mode *mode;
+               struct ieee80211_rate *rates;
+               size_t num_rates;
+               u32 supp_rates, prev_rates;
+               int i, j;
+
+               mode = local->sta_scanning ?
+                      local->scan_hw_mode : local->oper_hw_mode;
+               rates = mode->rates;
+               num_rates = mode->num_rates;
+
+               supp_rates = 0;
+               for (i = 0; i < elems.supp_rates_len +
+                            elems.ext_supp_rates_len; i++) {
+                       u8 rate = 0;
+                       int own_rate;
+                       if (i < elems.supp_rates_len)
+                               rate = elems.supp_rates[i];
+                       else if (elems.ext_supp_rates)
+                               rate = elems.ext_supp_rates
+                                       [i - elems.supp_rates_len];
+                       own_rate = 5 * (rate & 0x7f);
+                       if (mode->mode == MODE_ATHEROS_TURBO)
+                               own_rate *= 2;
+                       for (j = 0; j < num_rates; j++)
+                               if (rates[j].rate == own_rate)
+                                       supp_rates |= BIT(j);
+               }
+
+               prev_rates = sta->supp_rates;
+               sta->supp_rates &= supp_rates;
+               if (sta->supp_rates == 0) {
+                       /* No matching rates - this should not really happen.
+                        * Make sure that at least one rate is marked
+                        * supported to avoid issues with TX rate ctrl. */
+                       sta->supp_rates = sdata->u.sta.supp_rates_bits;
+               }
+               if (sta->supp_rates != prev_rates) {
+                       printk(KERN_DEBUG "%s: updated supp_rates set for "
+                              MAC_FMT " based on beacon info (0x%x & 0x%x -> "
+                              "0x%x)\n",
+                              dev->name, MAC_ARG(sta->addr), prev_rates,
+                              supp_rates, sta->supp_rates);
+               }
+               sta_info_put(sta);
+       }
+
+       if (!elems.ssid)
+               return;
+
+       if (elems.ds_params && elems.ds_params_len == 1)
+               channel = elems.ds_params[0];
+       else
+               channel = rx_status->channel;
+
+       bss = ieee80211_rx_bss_get(dev, mgmt->bssid);
+       if (!bss) {
+               bss = ieee80211_rx_bss_add(dev, mgmt->bssid);
+               if (!bss)
+                       return;
+       } else {
+#if 0
+               /* TODO: order by RSSI? */
+               spin_lock_bh(&local->sta_bss_lock);
+               list_move_tail(&bss->list, &local->sta_bss_list);
+               spin_unlock_bh(&local->sta_bss_lock);
+#endif
+       }
+
+       if (bss->probe_resp && beacon) {
+               /* Do not allow beacon to override data from Probe Response. */
+               ieee80211_rx_bss_put(dev, bss);
+               return;
+       }
+
+       bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
+       bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
+       if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) {
+               memcpy(bss->ssid, elems.ssid, elems.ssid_len);
+               bss->ssid_len = elems.ssid_len;
+       }
+
+       bss->supp_rates_len = 0;
+       if (elems.supp_rates) {
+               clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
+               if (clen > elems.supp_rates_len)
+                       clen = elems.supp_rates_len;
+               memcpy(&bss->supp_rates[bss->supp_rates_len], elems.supp_rates,
+                      clen);
+               bss->supp_rates_len += clen;
+       }
+       if (elems.ext_supp_rates) {
+               clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
+               if (clen > elems.ext_supp_rates_len)
+                       clen = elems.ext_supp_rates_len;
+               memcpy(&bss->supp_rates[bss->supp_rates_len],
+                      elems.ext_supp_rates, clen);
+               bss->supp_rates_len += clen;
+       }
+
+       if (elems.wpa &&
+           (!bss->wpa_ie || bss->wpa_ie_len != elems.wpa_len ||
+            memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) {
+               kfree(bss->wpa_ie);
+               bss->wpa_ie = kmalloc(elems.wpa_len + 2, GFP_ATOMIC);
+               if (bss->wpa_ie) {
+                       memcpy(bss->wpa_ie, elems.wpa - 2, elems.wpa_len + 2);
+                       bss->wpa_ie_len = elems.wpa_len + 2;
+               } else
+                       bss->wpa_ie_len = 0;
+       } else if (!elems.wpa && bss->wpa_ie) {
+               kfree(bss->wpa_ie);
+               bss->wpa_ie = NULL;
+               bss->wpa_ie_len = 0;
+       }
+
+       if (elems.rsn &&
+           (!bss->rsn_ie || bss->rsn_ie_len != elems.rsn_len ||
+            memcmp(bss->rsn_ie, elems.rsn, elems.rsn_len))) {
+               kfree(bss->rsn_ie);
+               bss->rsn_ie = kmalloc(elems.rsn_len + 2, GFP_ATOMIC);
+               if (bss->rsn_ie) {
+                       memcpy(bss->rsn_ie, elems.rsn - 2, elems.rsn_len + 2);
+                       bss->rsn_ie_len = elems.rsn_len + 2;
+               } else
+                       bss->rsn_ie_len = 0;
+       } else if (!elems.rsn && bss->rsn_ie) {
+               kfree(bss->rsn_ie);
+               bss->rsn_ie = NULL;
+               bss->rsn_ie_len = 0;
+       }
+
+       if (elems.wmm_param &&
+           (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_param_len ||
+            memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) {
+               kfree(bss->wmm_ie);
+               bss->wmm_ie = kmalloc(elems.wmm_param_len + 2, GFP_ATOMIC);
+               if (bss->wmm_ie) {
+                       memcpy(bss->wmm_ie, elems.wmm_param - 2,
+                              elems.wmm_param_len + 2);
+                       bss->wmm_ie_len = elems.wmm_param_len + 2;
+               } else
+                       bss->wmm_ie_len = 0;
+       } else if (!elems.wmm_param && bss->wmm_ie) {
+               kfree(bss->wmm_ie);
+               bss->wmm_ie = NULL;
+               bss->wmm_ie_len = 0;
+       }
+
+
+       bss->hw_mode = rx_status->phymode;
+       bss->channel = channel;
+       bss->freq = rx_status->freq;
+       if (channel != rx_status->channel &&
+           (bss->hw_mode == MODE_IEEE80211G ||
+            bss->hw_mode == MODE_IEEE80211B) &&
+           channel >= 1 && channel <= 14) {
+               static const int freq_list[] = {
+                       2412, 2417, 2422, 2427, 2432, 2437, 2442,
+                       2447, 2452, 2457, 2462, 2467, 2472, 2484
+               };
+               /* IEEE 802.11g/b mode can receive packets from neighboring
+                * channels, so map the channel into frequency. */
+               bss->freq = freq_list[channel - 1];
+       }
+       bss->timestamp = timestamp;
+       bss->last_update = jiffies;
+       bss->rssi = rx_status->ssi;
+       bss->signal = rx_status->signal;
+       bss->noise = rx_status->noise;
+       if (!beacon)
+               bss->probe_resp++;
+       ieee80211_rx_bss_put(dev, bss);
+}
+
+
+static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev,
+                                        struct ieee80211_mgmt *mgmt,
+                                        size_t len,
+                                        struct ieee80211_rx_status *rx_status)
+{
+       ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 0);
+}
+
+
+static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
+                                    struct ieee80211_mgmt *mgmt,
+                                    size_t len,
+                                    struct ieee80211_rx_status *rx_status)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_if_sta *ifsta;
+       int use_protection;
+       size_t baselen;
+       struct ieee802_11_elems elems;
+
+       ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 1);
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       if (sdata->type != IEEE80211_IF_TYPE_STA)
+               return;
+       ifsta = &sdata->u.sta;
+
+       if (!ifsta->associated ||
+           memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
+               return;
+
+       /* Process beacon from the current BSS */
+       baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
+       if (baselen > len)
+               return;
+
+       if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen,
+                                  &elems) == ParseFailed)
+               return;
+
+       use_protection = 0;
+       if (elems.erp_info && elems.erp_info_len >= 1) {
+               use_protection =
+                       (elems.erp_info[0] & ERP_INFO_USE_PROTECTION) != 0;
+       }
+
+       if (use_protection != !!ifsta->use_protection) {
+               if (net_ratelimit()) {
+                       printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
+                              MAC_FMT ")\n",
+                              dev->name,
+                              use_protection ? "enabled" : "disabled",
+                              MAC_ARG(ifsta->bssid));
+               }
+               ifsta->use_protection = use_protection ? 1 : 0;
+               local->cts_protect_erp_frames = use_protection;
+       }
+
+       if (elems.wmm_param && ifsta->wmm_enabled) {
+               ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
+                                        elems.wmm_param_len);
+       }
+}
+
+
+static void ieee80211_rx_mgmt_probe_req(struct net_device *dev,
+                                       struct ieee80211_if_sta *ifsta,
+                                       struct ieee80211_mgmt *mgmt,
+                                       size_t len,
+                                       struct ieee80211_rx_status *rx_status)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       int tx_last_beacon;
+       struct sk_buff *skb;
+       struct ieee80211_mgmt *resp;
+       u8 *pos, *end;
+
+       if (sdata->type != IEEE80211_IF_TYPE_IBSS ||
+           ifsta->state != IEEE80211_IBSS_JOINED ||
+           len < 24 + 2 || !ifsta->probe_resp)
+               return;
+
+       if (local->ops->tx_last_beacon)
+               tx_last_beacon = local->ops->tx_last_beacon(local_to_hw(local));
+       else
+               tx_last_beacon = 1;
+
+#ifdef CONFIG_MAC80211_IBSS_DEBUG
+       printk(KERN_DEBUG "%s: RX ProbeReq SA=" MAC_FMT " DA=" MAC_FMT " BSSID="
+              MAC_FMT " (tx_last_beacon=%d)\n",
+              dev->name, MAC_ARG(mgmt->sa), MAC_ARG(mgmt->da),
+              MAC_ARG(mgmt->bssid), tx_last_beacon);
+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+
+       if (!tx_last_beacon)
+               return;
+
+       if (memcmp(mgmt->bssid, ifsta->bssid, ETH_ALEN) != 0 &&
+           memcmp(mgmt->bssid, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0)
+               return;
+
+       end = ((u8 *) mgmt) + len;
+       pos = mgmt->u.probe_req.variable;
+       if (pos[0] != WLAN_EID_SSID ||
+           pos + 2 + pos[1] > end) {
+               if (net_ratelimit()) {
+                       printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq "
+                              "from " MAC_FMT "\n",
+                              dev->name, MAC_ARG(mgmt->sa));
+               }
+               return;
+       }
+       if (pos[1] != 0 &&
+           (pos[1] != ifsta->ssid_len ||
+            memcmp(pos + 2, ifsta->ssid, ifsta->ssid_len) != 0)) {
+               /* Ignore ProbeReq for foreign SSID */
+               return;
+       }
+
+       /* Reply with ProbeResp */
+       skb = skb_copy(ifsta->probe_resp, GFP_ATOMIC);
+       if (!skb)
+               return;
+
+       resp = (struct ieee80211_mgmt *) skb->data;
+       memcpy(resp->da, mgmt->sa, ETH_ALEN);
+#ifdef CONFIG_MAC80211_IBSS_DEBUG
+       printk(KERN_DEBUG "%s: Sending ProbeResp to " MAC_FMT "\n",
+              dev->name, MAC_ARG(resp->da));
+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+       ieee80211_sta_tx(dev, skb, 0);
+}
+
+
+void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
+                          struct ieee80211_rx_status *rx_status)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_if_sta *ifsta;
+       struct ieee80211_mgmt *mgmt;
+       u16 fc;
+
+       if (skb->len < 24)
+               goto fail;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       ifsta = &sdata->u.sta;
+
+       mgmt = (struct ieee80211_mgmt *) skb->data;
+       fc = le16_to_cpu(mgmt->frame_control);
+
+       switch (fc & IEEE80211_FCTL_STYPE) {
+       case IEEE80211_STYPE_PROBE_REQ:
+       case IEEE80211_STYPE_PROBE_RESP:
+       case IEEE80211_STYPE_BEACON:
+               memcpy(skb->cb, rx_status, sizeof(*rx_status));
+       case IEEE80211_STYPE_AUTH:
+       case IEEE80211_STYPE_ASSOC_RESP:
+       case IEEE80211_STYPE_REASSOC_RESP:
+       case IEEE80211_STYPE_DEAUTH:
+       case IEEE80211_STYPE_DISASSOC:
+               skb_queue_tail(&ifsta->skb_queue, skb);
+               queue_work(local->hw.workqueue, &ifsta->work);
+               return;
+       default:
+               printk(KERN_DEBUG "%s: received unknown management frame - "
+                      "stype=%d\n", dev->name,
+                      (fc & IEEE80211_FCTL_STYPE) >> 4);
+               break;
+       }
+
+ fail:
+       kfree_skb(skb);
+}
+
+
+static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev,
+                                        struct sk_buff *skb)
+{
+       struct ieee80211_rx_status *rx_status;
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_if_sta *ifsta;
+       struct ieee80211_mgmt *mgmt;
+       u16 fc;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       ifsta = &sdata->u.sta;
+
+       rx_status = (struct ieee80211_rx_status *) skb->cb;
+       mgmt = (struct ieee80211_mgmt *) skb->data;
+       fc = le16_to_cpu(mgmt->frame_control);
+
+       switch (fc & IEEE80211_FCTL_STYPE) {
+       case IEEE80211_STYPE_PROBE_REQ:
+               ieee80211_rx_mgmt_probe_req(dev, ifsta, mgmt, skb->len,
+                                           rx_status);
+               break;
+       case IEEE80211_STYPE_PROBE_RESP:
+               ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status);
+               break;
+       case IEEE80211_STYPE_BEACON:
+               ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status);
+               break;
+       case IEEE80211_STYPE_AUTH:
+               ieee80211_rx_mgmt_auth(dev, ifsta, mgmt, skb->len);
+               break;
+       case IEEE80211_STYPE_ASSOC_RESP:
+               ieee80211_rx_mgmt_assoc_resp(dev, ifsta, mgmt, skb->len, 0);
+               break;
+       case IEEE80211_STYPE_REASSOC_RESP:
+               ieee80211_rx_mgmt_assoc_resp(dev, ifsta, mgmt, skb->len, 1);
+               break;
+       case IEEE80211_STYPE_DEAUTH:
+               ieee80211_rx_mgmt_deauth(dev, ifsta, mgmt, skb->len);
+               break;
+       case IEEE80211_STYPE_DISASSOC:
+               ieee80211_rx_mgmt_disassoc(dev, ifsta, mgmt, skb->len);
+               break;
+       }
+
+       kfree_skb(skb);
+}
+
+
+void ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb,
+                          struct ieee80211_rx_status *rx_status)
+{
+       struct ieee80211_mgmt *mgmt;
+       u16 fc;
+
+       if (skb->len < 24) {
+               dev_kfree_skb(skb);
+               return;
+       }
+
+       mgmt = (struct ieee80211_mgmt *) skb->data;
+       fc = le16_to_cpu(mgmt->frame_control);
+
+       if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
+               if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP) {
+                       ieee80211_rx_mgmt_probe_resp(dev, mgmt,
+                                                    skb->len, rx_status);
+               } else if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) {
+                       ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len,
+                                                rx_status);
+               }
+       }
+
+       dev_kfree_skb(skb);
+}
+
+
+static int ieee80211_sta_active_ibss(struct net_device *dev)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       int active = 0;
+       struct sta_info *sta;
+
+       spin_lock_bh(&local->sta_lock);
+       list_for_each_entry(sta, &local->sta_list, list) {
+               if (sta->dev == dev &&
+                   time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL,
+                              jiffies)) {
+                       active++;
+                       break;
+               }
+       }
+       spin_unlock_bh(&local->sta_lock);
+
+       return active;
+}
+
+
+static void ieee80211_sta_expire(struct net_device *dev)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct sta_info *sta, *tmp;
+
+       spin_lock_bh(&local->sta_lock);
+       list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
+               if (time_after(jiffies, sta->last_rx +
+                              IEEE80211_IBSS_INACTIVITY_LIMIT)) {
+                       printk(KERN_DEBUG "%s: expiring inactive STA " MAC_FMT
+                              "\n", dev->name, MAC_ARG(sta->addr));
+                       sta_info_free(sta, 1);
+               }
+       spin_unlock_bh(&local->sta_lock);
+}
+
+
+static void ieee80211_sta_merge_ibss(struct net_device *dev,
+                                    struct ieee80211_if_sta *ifsta)
+{
+       mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
+
+       ieee80211_sta_expire(dev);
+       if (ieee80211_sta_active_ibss(dev))
+               return;
+
+       printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other "
+              "IBSS networks with same SSID (merge)\n", dev->name);
+       ieee80211_sta_req_scan(dev, ifsta->ssid, ifsta->ssid_len);
+}
+
+
+void ieee80211_sta_timer(unsigned long data)
+{
+       struct ieee80211_sub_if_data *sdata =
+               (struct ieee80211_sub_if_data *) data;
+       struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+       struct ieee80211_local *local = wdev_priv(&sdata->wdev);
+
+       set_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
+       queue_work(local->hw.workqueue, &ifsta->work);
+}
+
+
+void ieee80211_sta_work(struct work_struct *work)
+{
+       struct ieee80211_sub_if_data *sdata =
+               container_of(work, struct ieee80211_sub_if_data, u.sta.work);
+       struct net_device *dev = sdata->dev;
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_if_sta *ifsta;
+       struct sk_buff *skb;
+
+       if (!netif_running(dev))
+               return;
+
+       if (local->sta_scanning)
+               return;
+
+       if (sdata->type != IEEE80211_IF_TYPE_STA &&
+           sdata->type != IEEE80211_IF_TYPE_IBSS) {
+               printk(KERN_DEBUG "%s: ieee80211_sta_work: non-STA interface "
+                      "(type=%d)\n", dev->name, sdata->type);
+               return;
+       }
+       ifsta = &sdata->u.sta;
+
+       while ((skb = skb_dequeue(&ifsta->skb_queue)))
+               ieee80211_sta_rx_queued_mgmt(dev, skb);
+
+       if (ifsta->state != IEEE80211_AUTHENTICATE &&
+           ifsta->state != IEEE80211_ASSOCIATE &&
+           test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) {
+               ieee80211_sta_start_scan(dev, NULL, 0);
+               return;
+       }
+
+       if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) {
+               if (ieee80211_sta_config_auth(dev, ifsta))
+                       return;
+               clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
+       } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request))
+               return;
+
+       switch (ifsta->state) {
+       case IEEE80211_DISABLED:
+               break;
+       case IEEE80211_AUTHENTICATE:
+               ieee80211_authenticate(dev, ifsta);
+               break;
+       case IEEE80211_ASSOCIATE:
+               ieee80211_associate(dev, ifsta);
+               break;
+       case IEEE80211_ASSOCIATED:
+               ieee80211_associated(dev, ifsta);
+               break;
+       case IEEE80211_IBSS_SEARCH:
+               ieee80211_sta_find_ibss(dev, ifsta);
+               break;
+       case IEEE80211_IBSS_JOINED:
+               ieee80211_sta_merge_ibss(dev, ifsta);
+               break;
+       default:
+               printk(KERN_DEBUG "ieee80211_sta_work: Unknown state %d\n",
+                      ifsta->state);
+               break;
+       }
+
+       if (ieee80211_privacy_mismatch(dev, ifsta)) {
+               printk(KERN_DEBUG "%s: privacy configuration mismatch and "
+                      "mixed-cell disabled - disassociate\n", dev->name);
+
+               ieee80211_send_disassoc(dev, ifsta, WLAN_REASON_UNSPECIFIED);
+               ieee80211_set_disassoc(dev, ifsta, 0);
+       }
+}
+
+
+static void ieee80211_sta_reset_auth(struct net_device *dev,
+                                    struct ieee80211_if_sta *ifsta)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+       if (local->ops->reset_tsf) {
+               /* Reset own TSF to allow time synchronization work. */
+               local->ops->reset_tsf(local_to_hw(local));
+       }
+
+       ifsta->wmm_last_param_set = -1; /* allow any WMM update */
+
+
+       if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN)
+               ifsta->auth_alg = WLAN_AUTH_OPEN;
+       else if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
+               ifsta->auth_alg = WLAN_AUTH_SHARED_KEY;
+       else if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP)
+               ifsta->auth_alg = WLAN_AUTH_LEAP;
+       else
+               ifsta->auth_alg = WLAN_AUTH_OPEN;
+       printk(KERN_DEBUG "%s: Initial auth_alg=%d\n", dev->name,
+              ifsta->auth_alg);
+       ifsta->auth_transaction = -1;
+       ifsta->associated = ifsta->auth_tries = ifsta->assoc_tries = 0;
+       netif_carrier_off(dev);
+}
+
+
+void ieee80211_sta_req_auth(struct net_device *dev,
+                           struct ieee80211_if_sta *ifsta)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+       if (sdata->type != IEEE80211_IF_TYPE_STA)
+               return;
+
+       if ((ifsta->bssid_set || ifsta->auto_bssid_sel) &&
+           (ifsta->ssid_set || ifsta->auto_ssid_sel)) {
+               set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
+               queue_work(local->hw.workqueue, &ifsta->work);
+       }
+}
+
+static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta,
+                                   const char *ssid, int ssid_len)
+{
+       int tmp, hidden_ssid;
+
+       if (!memcmp(ifsta->ssid, ssid, ssid_len))
+               return 1;
+
+       if (ifsta->auto_bssid_sel)
+               return 0;
+
+       hidden_ssid = 1;
+       tmp = ssid_len;
+       while (tmp--) {
+               if (ssid[tmp] != '\0') {
+                       hidden_ssid = 0;
+                       break;
+               }
+       }
+
+       if (hidden_ssid && ifsta->ssid_len == ssid_len)
+               return 1;
+
+       if (ssid_len == 1 && ssid[0] == ' ')
+               return 1;
+
+       return 0;
+}
+
+static int ieee80211_sta_config_auth(struct net_device *dev,
+                                    struct ieee80211_if_sta *ifsta)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_sta_bss *bss, *selected = NULL;
+       int top_rssi = 0, freq;
+
+       rtnl_lock();
+
+       if (!ifsta->auto_channel_sel && !ifsta->auto_bssid_sel &&
+           !ifsta->auto_ssid_sel) {
+               ifsta->state = IEEE80211_AUTHENTICATE;
+               rtnl_unlock();
+               ieee80211_sta_reset_auth(dev, ifsta);
+               return 0;
+       }
+
+       spin_lock_bh(&local->sta_bss_lock);
+       freq = local->oper_channel->freq;
+       list_for_each_entry(bss, &local->sta_bss_list, list) {
+               if (!(bss->capability & WLAN_CAPABILITY_ESS))
+                       continue;
+
+               if (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^
+                   !!sdata->default_key)
+                       continue;
+
+               if (!ifsta->auto_channel_sel && bss->freq != freq)
+                       continue;
+
+               if (!ifsta->auto_bssid_sel &&
+                   memcmp(bss->bssid, ifsta->bssid, ETH_ALEN))
+                       continue;
+
+               if (!ifsta->auto_ssid_sel &&
+                   !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len))
+                       continue;
+
+               if (!selected || top_rssi < bss->rssi) {
+                       selected = bss;
+                       top_rssi = bss->rssi;
+               }
+       }
+       if (selected)
+               atomic_inc(&selected->users);
+       spin_unlock_bh(&local->sta_bss_lock);
+
+       if (selected) {
+               ieee80211_set_channel(local, -1, selected->freq);
+               if (!ifsta->ssid_set)
+                       ieee80211_sta_set_ssid(dev, selected->ssid,
+                                              selected->ssid_len);
+               ieee80211_sta_set_bssid(dev, selected->bssid);
+               ieee80211_rx_bss_put(dev, selected);
+               ifsta->state = IEEE80211_AUTHENTICATE;
+               rtnl_unlock();
+               ieee80211_sta_reset_auth(dev, ifsta);
+               return 0;
+       } else {
+               if (ifsta->state != IEEE80211_AUTHENTICATE) {
+                       ieee80211_sta_start_scan(dev, NULL, 0);
+                       ifsta->state = IEEE80211_AUTHENTICATE;
+                       set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
+               } else
+                       ifsta->state = IEEE80211_DISABLED;
+       }
+       rtnl_unlock();
+       return -1;
+}
+
+static int ieee80211_sta_join_ibss(struct net_device *dev,
+                                  struct ieee80211_if_sta *ifsta,
+                                  struct ieee80211_sta_bss *bss)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       int res, rates, i, j;
+       struct sk_buff *skb;
+       struct ieee80211_mgmt *mgmt;
+       struct ieee80211_tx_control control;
+       struct ieee80211_rate *rate;
+       struct ieee80211_hw_mode *mode;
+       struct rate_control_extra extra;
+       u8 *pos;
+       struct ieee80211_sub_if_data *sdata;
+
+       /* Remove possible STA entries from other IBSS networks. */
+       sta_info_flush(local, NULL);
+
+       if (local->ops->reset_tsf) {
+               /* Reset own TSF to allow time synchronization work. */
+               local->ops->reset_tsf(local_to_hw(local));
+       }
+       memcpy(ifsta->bssid, bss->bssid, ETH_ALEN);
+       res = ieee80211_if_config(dev);
+       if (res)
+               return res;
+
+       local->hw.conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       sdata->drop_unencrypted = bss->capability &
+               WLAN_CAPABILITY_PRIVACY ? 1 : 0;
+
+       res = ieee80211_set_channel(local, -1, bss->freq);
+
+       if (!(local->oper_channel->flag & IEEE80211_CHAN_W_IBSS)) {
+               printk(KERN_DEBUG "%s: IBSS not allowed on channel %d "
+                      "(%d MHz)\n", dev->name, local->hw.conf.channel,
+                      local->hw.conf.freq);
+               return -1;
+       }
+
+       /* Set beacon template based on scan results */
+       skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
+       do {
+               if (!skb)
+                       break;
+
+               skb_reserve(skb, local->hw.extra_tx_headroom);
+
+               mgmt = (struct ieee80211_mgmt *)
+                       skb_put(skb, 24 + sizeof(mgmt->u.beacon));
+               memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
+               mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+                                                  IEEE80211_STYPE_BEACON);
+               memset(mgmt->da, 0xff, ETH_ALEN);
+               memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
+               memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
+               mgmt->u.beacon.beacon_int =
+                       cpu_to_le16(local->hw.conf.beacon_int);
+               mgmt->u.beacon.capab_info = cpu_to_le16(bss->capability);
+
+               pos = skb_put(skb, 2 + ifsta->ssid_len);
+               *pos++ = WLAN_EID_SSID;
+               *pos++ = ifsta->ssid_len;
+               memcpy(pos, ifsta->ssid, ifsta->ssid_len);
+
+               rates = bss->supp_rates_len;
+               if (rates > 8)
+                       rates = 8;
+               pos = skb_put(skb, 2 + rates);
+               *pos++ = WLAN_EID_SUPP_RATES;
+               *pos++ = rates;
+               memcpy(pos, bss->supp_rates, rates);
+
+               pos = skb_put(skb, 2 + 1);
+               *pos++ = WLAN_EID_DS_PARAMS;
+               *pos++ = 1;
+               *pos++ = bss->channel;
+
+               pos = skb_put(skb, 2 + 2);
+               *pos++ = WLAN_EID_IBSS_PARAMS;
+               *pos++ = 2;
+               /* FIX: set ATIM window based on scan results */
+               *pos++ = 0;
+               *pos++ = 0;
+
+               if (bss->supp_rates_len > 8) {
+                       rates = bss->supp_rates_len - 8;
+                       pos = skb_put(skb, 2 + rates);
+                       *pos++ = WLAN_EID_EXT_SUPP_RATES;
+                       *pos++ = rates;
+                       memcpy(pos, &bss->supp_rates[8], rates);
+               }
+
+               memset(&control, 0, sizeof(control));
+               memset(&extra, 0, sizeof(extra));
+               extra.mode = local->oper_hw_mode;
+               rate = rate_control_get_rate(local, dev, skb, &extra);
+               if (!rate) {
+                       printk(KERN_DEBUG "%s: Failed to determine TX rate "
+                              "for IBSS beacon\n", dev->name);
+                       break;
+               }
+               control.tx_rate = (local->short_preamble &&
+                                  (rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
+                       rate->val2 : rate->val;
+               control.antenna_sel_tx = local->hw.conf.antenna_sel_tx;
+               control.power_level = local->hw.conf.power_level;
+               control.flags |= IEEE80211_TXCTL_NO_ACK;
+               control.retry_limit = 1;
+
+               ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC);
+               if (ifsta->probe_resp) {
+                       mgmt = (struct ieee80211_mgmt *)
+                               ifsta->probe_resp->data;
+                       mgmt->frame_control =
+                               IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+                                            IEEE80211_STYPE_PROBE_RESP);
+               } else {
+                       printk(KERN_DEBUG "%s: Could not allocate ProbeResp "
+                              "template for IBSS\n", dev->name);
+               }
+
+               if (local->ops->beacon_update &&
+                   local->ops->beacon_update(local_to_hw(local),
+                                            skb, &control) == 0) {
+                       printk(KERN_DEBUG "%s: Configured IBSS beacon "
+                              "template based on scan results\n", dev->name);
+                       skb = NULL;
+               }
+
+               rates = 0;
+               mode = local->oper_hw_mode;
+               for (i = 0; i < bss->supp_rates_len; i++) {
+                       int bitrate = (bss->supp_rates[i] & 0x7f) * 5;
+                       if (mode->mode == MODE_ATHEROS_TURBO)
+                               bitrate *= 2;
+                       for (j = 0; j < mode->num_rates; j++)
+                               if (mode->rates[j].rate == bitrate)
+                                       rates |= BIT(j);
+               }
+               ifsta->supp_rates_bits = rates;
+       } while (0);
+
+       if (skb) {
+               printk(KERN_DEBUG "%s: Failed to configure IBSS beacon "
+                      "template\n", dev->name);
+               dev_kfree_skb(skb);
+       }
+
+       ifsta->state = IEEE80211_IBSS_JOINED;
+       mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
+
+       ieee80211_rx_bss_put(dev, bss);
+
+       return res;
+}
+
+
+static int ieee80211_sta_create_ibss(struct net_device *dev,
+                                    struct ieee80211_if_sta *ifsta)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sta_bss *bss;
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_hw_mode *mode;
+       u8 bssid[ETH_ALEN], *pos;
+       int i;
+
+#if 0
+       /* Easier testing, use fixed BSSID. */
+       memset(bssid, 0xfe, ETH_ALEN);
+#else
+       /* Generate random, not broadcast, locally administered BSSID. Mix in
+        * own MAC address to make sure that devices that do not have proper
+        * random number generator get different BSSID. */
+       get_random_bytes(bssid, ETH_ALEN);
+       for (i = 0; i < ETH_ALEN; i++)
+               bssid[i] ^= dev->dev_addr[i];
+       bssid[0] &= ~0x01;
+       bssid[0] |= 0x02;
+#endif
+
+       printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID " MAC_FMT "\n",
+              dev->name, MAC_ARG(bssid));
+
+       bss = ieee80211_rx_bss_add(dev, bssid);
+       if (!bss)
+               return -ENOMEM;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       mode = local->oper_hw_mode;
+
+       if (local->hw.conf.beacon_int == 0)
+               local->hw.conf.beacon_int = 100;
+       bss->beacon_int = local->hw.conf.beacon_int;
+       bss->hw_mode = local->hw.conf.phymode;
+       bss->channel = local->hw.conf.channel;
+       bss->freq = local->hw.conf.freq;
+       bss->last_update = jiffies;
+       bss->capability = WLAN_CAPABILITY_IBSS;
+       if (sdata->default_key) {
+               bss->capability |= WLAN_CAPABILITY_PRIVACY;
+       } else
+               sdata->drop_unencrypted = 0;
+       bss->supp_rates_len = mode->num_rates;
+       pos = bss->supp_rates;
+       for (i = 0; i < mode->num_rates; i++) {
+               int rate = mode->rates[i].rate;
+               if (mode->mode == MODE_ATHEROS_TURBO)
+                       rate /= 2;
+               *pos++ = (u8) (rate / 5);
+       }
+
+       return ieee80211_sta_join_ibss(dev, ifsta, bss);
+}
+
+
+static int ieee80211_sta_find_ibss(struct net_device *dev,
+                                  struct ieee80211_if_sta *ifsta)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sta_bss *bss;
+       int found = 0;
+       u8 bssid[ETH_ALEN];
+       int active_ibss;
+
+       if (ifsta->ssid_len == 0)
+               return -EINVAL;
+
+       active_ibss = ieee80211_sta_active_ibss(dev);
+#ifdef CONFIG_MAC80211_IBSS_DEBUG
+       printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n",
+              dev->name, active_ibss);
+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+       spin_lock_bh(&local->sta_bss_lock);
+       list_for_each_entry(bss, &local->sta_bss_list, list) {
+               if (ifsta->ssid_len != bss->ssid_len ||
+                   memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0
+                   || !(bss->capability & WLAN_CAPABILITY_IBSS))
+                       continue;
+#ifdef CONFIG_MAC80211_IBSS_DEBUG
+               printk(KERN_DEBUG "   bssid=" MAC_FMT " found\n",
+                      MAC_ARG(bss->bssid));
+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+               memcpy(bssid, bss->bssid, ETH_ALEN);
+               found = 1;
+               if (active_ibss || memcmp(bssid, ifsta->bssid, ETH_ALEN) != 0)
+                       break;
+       }
+       spin_unlock_bh(&local->sta_bss_lock);
+
+#ifdef CONFIG_MAC80211_IBSS_DEBUG
+       printk(KERN_DEBUG "   sta_find_ibss: selected " MAC_FMT " current "
+              MAC_FMT "\n", MAC_ARG(bssid), MAC_ARG(ifsta->bssid));
+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+       if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 &&
+           (bss = ieee80211_rx_bss_get(dev, bssid))) {
+               printk(KERN_DEBUG "%s: Selected IBSS BSSID " MAC_FMT
+                      " based on configured SSID\n",
+                      dev->name, MAC_ARG(bssid));
+               return ieee80211_sta_join_ibss(dev, ifsta, bss);
+       }
+#ifdef CONFIG_MAC80211_IBSS_DEBUG
+       printk(KERN_DEBUG "   did not try to join ibss\n");
+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
+
+       /* Selected IBSS not found in current scan results - try to scan */
+       if (ifsta->state == IEEE80211_IBSS_JOINED &&
+           !ieee80211_sta_active_ibss(dev)) {
+               mod_timer(&ifsta->timer, jiffies +
+                                     IEEE80211_IBSS_MERGE_INTERVAL);
+       } else if (time_after(jiffies, local->last_scan_completed +
+                             IEEE80211_SCAN_INTERVAL)) {
+               printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to "
+                      "join\n", dev->name);
+               return ieee80211_sta_req_scan(dev, ifsta->ssid,
+                                             ifsta->ssid_len);
+       } else if (ifsta->state != IEEE80211_IBSS_JOINED) {
+               int interval = IEEE80211_SCAN_INTERVAL;
+
+               if (time_after(jiffies, ifsta->ibss_join_req +
+                              IEEE80211_IBSS_JOIN_TIMEOUT)) {
+                       if (ifsta->create_ibss &&
+                           local->oper_channel->flag & IEEE80211_CHAN_W_IBSS)
+                               return ieee80211_sta_create_ibss(dev, ifsta);
+                       if (ifsta->create_ibss) {
+                               printk(KERN_DEBUG "%s: IBSS not allowed on the"
+                                      " configured channel %d (%d MHz)\n",
+                                      dev->name, local->hw.conf.channel,
+                                      local->hw.conf.freq);
+                       }
+
+                       /* No IBSS found - decrease scan interval and continue
+                        * scanning. */
+                       interval = IEEE80211_SCAN_INTERVAL_SLOW;
+               }
+
+               ifsta->state = IEEE80211_IBSS_SEARCH;
+               mod_timer(&ifsta->timer, jiffies + interval);
+               return 0;
+       }
+
+       return 0;
+}
+
+
+int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len)
+{
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_if_sta *ifsta;
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+       if (len > IEEE80211_MAX_SSID_LEN)
+               return -EINVAL;
+
+       /* TODO: This should always be done for IBSS, even if IEEE80211_QOS is
+        * not defined. */
+       if (local->ops->conf_tx) {
+               struct ieee80211_tx_queue_params qparam;
+               int i;
+
+               memset(&qparam, 0, sizeof(qparam));
+               /* TODO: are these ok defaults for all hw_modes? */
+               qparam.aifs = 2;
+               qparam.cw_min =
+                       local->hw.conf.phymode == MODE_IEEE80211B ? 31 : 15;
+               qparam.cw_max = 1023;
+               qparam.burst_time = 0;
+               for (i = IEEE80211_TX_QUEUE_DATA0; i < NUM_TX_DATA_QUEUES; i++)
+               {
+                       local->ops->conf_tx(local_to_hw(local),
+                                          i + IEEE80211_TX_QUEUE_DATA0,
+                                          &qparam);
+               }
+               /* IBSS uses different parameters for Beacon sending */
+               qparam.cw_min++;
+               qparam.cw_min *= 2;
+               qparam.cw_min--;
+               local->ops->conf_tx(local_to_hw(local),
+                                  IEEE80211_TX_QUEUE_BEACON, &qparam);
+       }
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       ifsta = &sdata->u.sta;
+
+       if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0)
+               ifsta->prev_bssid_set = 0;
+       memcpy(ifsta->ssid, ssid, len);
+       memset(ifsta->ssid + len, 0, IEEE80211_MAX_SSID_LEN - len);
+       ifsta->ssid_len = len;
+
+       ifsta->ssid_set = len ? 1 : 0;
+       if (sdata->type == IEEE80211_IF_TYPE_IBSS && !ifsta->bssid_set) {
+               ifsta->ibss_join_req = jiffies;
+               ifsta->state = IEEE80211_IBSS_SEARCH;
+               return ieee80211_sta_find_ibss(dev, ifsta);
+       }
+       return 0;
+}
+
+
+int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+       memcpy(ssid, ifsta->ssid, ifsta->ssid_len);
+       *len = ifsta->ssid_len;
+       return 0;
+}
+
+
+int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid)
+{
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_if_sta *ifsta;
+       int res;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       ifsta = &sdata->u.sta;
+
+       if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) {
+               memcpy(ifsta->bssid, bssid, ETH_ALEN);
+               res = ieee80211_if_config(dev);
+               if (res) {
+                       printk(KERN_DEBUG "%s: Failed to config new BSSID to "
+                              "the low-level driver\n", dev->name);
+                       return res;
+               }
+       }
+
+       if (!is_valid_ether_addr(bssid))
+               ifsta->bssid_set = 0;
+       else
+               ifsta->bssid_set = 1;
+       return 0;
+}
+
+
+static void ieee80211_send_nullfunc(struct ieee80211_local *local,
+                                   struct ieee80211_sub_if_data *sdata,
+                                   int powersave)
+{
+       struct sk_buff *skb;
+       struct ieee80211_hdr *nullfunc;
+       u16 fc;
+
+       skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24);
+       if (!skb) {
+               printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc "
+                      "frame\n", sdata->dev->name);
+               return;
+       }
+       skb_reserve(skb, local->hw.extra_tx_headroom);
+
+       nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24);
+       memset(nullfunc, 0, 24);
+       fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
+            IEEE80211_FCTL_TODS;
+       if (powersave)
+               fc |= IEEE80211_FCTL_PM;
+       nullfunc->frame_control = cpu_to_le16(fc);
+       memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN);
+       memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN);
+       memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN);
+
+       ieee80211_sta_tx(sdata->dev, skb, 0);
+}
+
+
+void ieee80211_scan_completed(struct ieee80211_hw *hw)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+       struct net_device *dev = local->scan_dev;
+       struct ieee80211_sub_if_data *sdata;
+       union iwreq_data wrqu;
+
+       local->last_scan_completed = jiffies;
+       wmb();
+       local->sta_scanning = 0;
+
+       if (ieee80211_hw_config(local))
+               printk(KERN_DEBUG "%s: failed to restore operational"
+                      "channel after scan\n", dev->name);
+
+       if (!(local->hw.flags & IEEE80211_HW_NO_PROBE_FILTERING) &&
+           ieee80211_if_config(dev))
+               printk(KERN_DEBUG "%s: failed to restore operational"
+                      "BSSID after scan\n", dev->name);
+
+       memset(&wrqu, 0, sizeof(wrqu));
+       wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
+
+       read_lock(&local->sub_if_lock);
+       list_for_each_entry(sdata, &local->sub_if_list, list) {
+               if (sdata->type == IEEE80211_IF_TYPE_STA) {
+                       if (sdata->u.sta.associated)
+                               ieee80211_send_nullfunc(local, sdata, 0);
+                       ieee80211_sta_timer((unsigned long)sdata);
+               }
+               netif_wake_queue(sdata->dev);
+       }
+       read_unlock(&local->sub_if_lock);
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       if (sdata->type == IEEE80211_IF_TYPE_IBSS) {
+               struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+               if (!ifsta->bssid_set ||
+                   (!ifsta->state == IEEE80211_IBSS_JOINED &&
+                   !ieee80211_sta_active_ibss(dev)))
+                       ieee80211_sta_find_ibss(dev, ifsta);
+       }
+}
+EXPORT_SYMBOL(ieee80211_scan_completed);
+
+void ieee80211_sta_scan_work(struct work_struct *work)
+{
+       struct ieee80211_local *local =
+               container_of(work, struct ieee80211_local, scan_work.work);
+       struct net_device *dev = local->scan_dev;
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_hw_mode *mode;
+       struct ieee80211_channel *chan;
+       int skip;
+       unsigned long next_delay = 0;
+
+       if (!local->sta_scanning)
+               return;
+
+       switch (local->scan_state) {
+       case SCAN_SET_CHANNEL:
+               mode = local->scan_hw_mode;
+               if (local->scan_hw_mode->list.next == &local->modes_list &&
+                   local->scan_channel_idx >= mode->num_channels) {
+                       ieee80211_scan_completed(local_to_hw(local));
+                       return;
+               }
+               skip = !(local->enabled_modes & (1 << mode->mode));
+               chan = &mode->channels[local->scan_channel_idx];
+               if (!(chan->flag & IEEE80211_CHAN_W_SCAN) ||
+                   (sdata->type == IEEE80211_IF_TYPE_IBSS &&
+                    !(chan->flag & IEEE80211_CHAN_W_IBSS)) ||
+                   (local->hw_modes & local->enabled_modes &
+                    (1 << MODE_IEEE80211G) && mode->mode == MODE_IEEE80211B))
+                       skip = 1;
+
+               if (!skip) {
+#if 0
+                       printk(KERN_DEBUG "%s: scan channel %d (%d MHz)\n",
+                              dev->name, chan->chan, chan->freq);
+#endif
+
+                       local->scan_channel = chan;
+                       if (ieee80211_hw_config(local)) {
+                               printk(KERN_DEBUG "%s: failed to set channel "
+                                      "%d (%d MHz) for scan\n", dev->name,
+                                      chan->chan, chan->freq);
+                               skip = 1;
+                       }
+               }
+
+               local->scan_channel_idx++;
+               if (local->scan_channel_idx >= local->scan_hw_mode->num_channels) {
+                       if (local->scan_hw_mode->list.next != &local->modes_list) {
+                               local->scan_hw_mode = list_entry(local->scan_hw_mode->list.next,
+                                                                struct ieee80211_hw_mode,
+                                                                list);
+                               local->scan_channel_idx = 0;
+                       }
+               }
+
+               if (skip)
+                       break;
+
+               next_delay = IEEE80211_PROBE_DELAY +
+                            usecs_to_jiffies(local->hw.channel_change_time);
+               local->scan_state = SCAN_SEND_PROBE;
+               break;
+       case SCAN_SEND_PROBE:
+               if (local->scan_channel->flag & IEEE80211_CHAN_W_ACTIVE_SCAN) {
+                       ieee80211_send_probe_req(dev, NULL, local->scan_ssid,
+                                                local->scan_ssid_len);
+                       next_delay = IEEE80211_CHANNEL_TIME;
+               } else
+                       next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
+               local->scan_state = SCAN_SET_CHANNEL;
+               break;
+       }
+
+       if (local->sta_scanning)
+               queue_delayed_work(local->hw.workqueue, &local->scan_work,
+                                  next_delay);
+}
+
+
+static int ieee80211_sta_start_scan(struct net_device *dev,
+                                   u8 *ssid, size_t ssid_len)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata;
+
+       if (ssid_len > IEEE80211_MAX_SSID_LEN)
+               return -EINVAL;
+
+       /* MLME-SCAN.request (page 118)  page 144 (11.1.3.1)
+        * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS
+        * BSSID: MACAddress
+        * SSID
+        * ScanType: ACTIVE, PASSIVE
+        * ProbeDelay: delay (in microseconds) to be used prior to transmitting
+        *    a Probe frame during active scanning
+        * ChannelList
+        * MinChannelTime (>= ProbeDelay), in TU
+        * MaxChannelTime: (>= MinChannelTime), in TU
+        */
+
+        /* MLME-SCAN.confirm
+         * BSSDescriptionSet
+         * ResultCode: SUCCESS, INVALID_PARAMETERS
+        */
+
+       if (local->sta_scanning) {
+               if (local->scan_dev == dev)
+                       return 0;
+               return -EBUSY;
+       }
+
+       if (local->ops->hw_scan) {
+               int rc = local->ops->hw_scan(local_to_hw(local),
+                                           ssid, ssid_len);
+               if (!rc) {
+                       local->sta_scanning = 1;
+                       local->scan_dev = dev;
+               }
+               return rc;
+       }
+
+       local->sta_scanning = 1;
+
+       read_lock(&local->sub_if_lock);
+       list_for_each_entry(sdata, &local->sub_if_list, list) {
+               netif_stop_queue(sdata->dev);
+               if (sdata->type == IEEE80211_IF_TYPE_STA &&
+                   sdata->u.sta.associated)
+                       ieee80211_send_nullfunc(local, sdata, 1);
+       }
+       read_unlock(&local->sub_if_lock);
+
+       if (ssid) {
+               local->scan_ssid_len = ssid_len;
+               memcpy(local->scan_ssid, ssid, ssid_len);
+       } else
+               local->scan_ssid_len = 0;
+       local->scan_state = SCAN_SET_CHANNEL;
+       local->scan_hw_mode = list_entry(local->modes_list.next,
+                                        struct ieee80211_hw_mode,
+                                        list);
+       local->scan_channel_idx = 0;
+       local->scan_dev = dev;
+
+       if (!(local->hw.flags & IEEE80211_HW_NO_PROBE_FILTERING) &&
+           ieee80211_if_config(dev))
+               printk(KERN_DEBUG "%s: failed to set BSSID for scan\n",
+                      dev->name);
+
+       /* TODO: start scan as soon as all nullfunc frames are ACKed */
+       queue_delayed_work(local->hw.workqueue, &local->scan_work,
+                          IEEE80211_CHANNEL_TIME);
+
+       return 0;
+}
+
+
+int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+       if (sdata->type != IEEE80211_IF_TYPE_STA)
+               return ieee80211_sta_start_scan(dev, ssid, ssid_len);
+
+       if (local->sta_scanning) {
+               if (local->scan_dev == dev)
+                       return 0;
+               return -EBUSY;
+       }
+
+       set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request);
+       queue_work(local->hw.workqueue, &ifsta->work);
+       return 0;
+}
+
+static char *
+ieee80211_sta_scan_result(struct net_device *dev,
+                         struct ieee80211_sta_bss *bss,
+                         char *current_ev, char *end_buf)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct iw_event iwe;
+
+       if (time_after(jiffies,
+                      bss->last_update + IEEE80211_SCAN_RESULT_EXPIRE))
+               return current_ev;
+
+       if (!(local->enabled_modes & (1 << bss->hw_mode)))
+               return current_ev;
+
+       if (local->scan_flags & IEEE80211_SCAN_WPA_ONLY &&
+           !bss->wpa_ie && !bss->rsn_ie)
+               return current_ev;
+
+       if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID &&
+           (local->scan_ssid_len != bss->ssid_len ||
+            memcmp(local->scan_ssid, bss->ssid, bss->ssid_len) != 0))
+               return current_ev;
+
+       memset(&iwe, 0, sizeof(iwe));
+       iwe.cmd = SIOCGIWAP;
+       iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+       memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
+       current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+                                         IW_EV_ADDR_LEN);
+
+       memset(&iwe, 0, sizeof(iwe));
+       iwe.cmd = SIOCGIWESSID;
+       iwe.u.data.length = bss->ssid_len;
+       iwe.u.data.flags = 1;
+       current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+                                         bss->ssid);
+
+       if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = SIOCGIWMODE;
+               if (bss->capability & WLAN_CAPABILITY_ESS)
+                       iwe.u.mode = IW_MODE_MASTER;
+               else
+                       iwe.u.mode = IW_MODE_ADHOC;
+               current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+                                                 IW_EV_UINT_LEN);
+       }
+
+       memset(&iwe, 0, sizeof(iwe));
+       iwe.cmd = SIOCGIWFREQ;
+       iwe.u.freq.m = bss->channel;
+       iwe.u.freq.e = 0;
+       current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+                                         IW_EV_FREQ_LEN);
+       iwe.u.freq.m = bss->freq * 100000;
+       iwe.u.freq.e = 1;
+       current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+                                         IW_EV_FREQ_LEN);
+
+       memset(&iwe, 0, sizeof(iwe));
+       iwe.cmd = IWEVQUAL;
+       iwe.u.qual.qual = bss->signal;
+       iwe.u.qual.level = bss->rssi;
+       iwe.u.qual.noise = bss->noise;
+       iwe.u.qual.updated = local->wstats_flags;
+       current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
+                                         IW_EV_QUAL_LEN);
+
+       memset(&iwe, 0, sizeof(iwe));
+       iwe.cmd = SIOCGIWENCODE;
+       if (bss->capability & WLAN_CAPABILITY_PRIVACY)
+               iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+       else
+               iwe.u.data.flags = IW_ENCODE_DISABLED;
+       iwe.u.data.length = 0;
+       current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, "");
+
+       if (bss && bss->wpa_ie) {
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = IWEVGENIE;
+               iwe.u.data.length = bss->wpa_ie_len;
+               current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+                                                 bss->wpa_ie);
+       }
+
+       if (bss && bss->rsn_ie) {
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = IWEVGENIE;
+               iwe.u.data.length = bss->rsn_ie_len;
+               current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+                                                 bss->rsn_ie);
+       }
+
+       if (bss && bss->supp_rates_len > 0) {
+               /* display all supported rates in readable format */
+               char *p = current_ev + IW_EV_LCP_LEN;
+               int i;
+
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = SIOCGIWRATE;
+               /* Those two flags are ignored... */
+               iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+
+               for (i = 0; i < bss->supp_rates_len; i++) {
+                       iwe.u.bitrate.value = ((bss->supp_rates[i] &
+                                                       0x7f) * 500000);
+                       p = iwe_stream_add_value(current_ev, p,
+                                       end_buf, &iwe, IW_EV_PARAM_LEN);
+               }
+               current_ev = p;
+       }
+
+       if (bss) {
+               char *buf;
+               buf = kmalloc(30, GFP_ATOMIC);
+               if (buf) {
+                       memset(&iwe, 0, sizeof(iwe));
+                       iwe.cmd = IWEVCUSTOM;
+                       sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp));
+                       iwe.u.data.length = strlen(buf);
+                       current_ev = iwe_stream_add_point(current_ev, end_buf,
+                                                         &iwe, buf);
+                       kfree(buf);
+               }
+       }
+
+       do {
+               char *buf;
+
+               if (!(local->scan_flags & IEEE80211_SCAN_EXTRA_INFO))
+                       break;
+
+               buf = kmalloc(100, GFP_ATOMIC);
+               if (!buf)
+                       break;
+
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = IWEVCUSTOM;
+               sprintf(buf, "bcn_int=%d", bss->beacon_int);
+               iwe.u.data.length = strlen(buf);
+               current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+                                                 buf);
+
+               memset(&iwe, 0, sizeof(iwe));
+               iwe.cmd = IWEVCUSTOM;
+               sprintf(buf, "capab=0x%04x", bss->capability);
+               iwe.u.data.length = strlen(buf);
+               current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+                                                 buf);
+
+               kfree(buf);
+               break;
+       } while (0);
+
+       return current_ev;
+}
+
+
+int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       char *current_ev = buf;
+       char *end_buf = buf + len;
+       struct ieee80211_sta_bss *bss;
+
+       spin_lock_bh(&local->sta_bss_lock);
+       list_for_each_entry(bss, &local->sta_bss_list, list) {
+               if (buf + len - current_ev <= IW_EV_ADDR_LEN) {
+                       spin_unlock_bh(&local->sta_bss_lock);
+                       return -E2BIG;
+               }
+               current_ev = ieee80211_sta_scan_result(dev, bss, current_ev,
+                                                      end_buf);
+       }
+       spin_unlock_bh(&local->sta_bss_lock);
+       return current_ev - buf;
+}
+
+
+int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+       kfree(ifsta->extra_ie);
+       if (len == 0) {
+               ifsta->extra_ie = NULL;
+               ifsta->extra_ie_len = 0;
+               return 0;
+       }
+       ifsta->extra_ie = kmalloc(len, GFP_KERNEL);
+       if (!ifsta->extra_ie) {
+               ifsta->extra_ie_len = 0;
+               return -ENOMEM;
+       }
+       memcpy(ifsta->extra_ie, ie, len);
+       ifsta->extra_ie_len = len;
+       return 0;
+}
+
+
+struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev,
+                                        struct sk_buff *skb, u8 *bssid,
+                                        u8 *addr)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct sta_info *sta;
+       struct ieee80211_sub_if_data *sdata = NULL;
+
+       /* TODO: Could consider removing the least recently used entry and
+        * allow new one to be added. */
+       if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
+               if (net_ratelimit()) {
+                       printk(KERN_DEBUG "%s: No room for a new IBSS STA "
+                              "entry " MAC_FMT "\n", dev->name, MAC_ARG(addr));
+               }
+               return NULL;
+       }
+
+       printk(KERN_DEBUG "%s: Adding new IBSS station " MAC_FMT " (dev=%s)\n",
+              local->mdev->name, MAC_ARG(addr), dev->name);
+
+       sta = sta_info_add(local, dev, addr, GFP_ATOMIC);
+       if (!sta)
+               return NULL;
+
+       sta->supp_rates = sdata->u.sta.supp_rates_bits;
+
+       rate_control_rate_init(sta, local);
+
+       return sta; /* caller will call sta_info_put() */
+}
+
+
+int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+
+       printk(KERN_DEBUG "%s: deauthenticate(reason=%d)\n",
+              dev->name, reason);
+
+       if (sdata->type != IEEE80211_IF_TYPE_STA &&
+           sdata->type != IEEE80211_IF_TYPE_IBSS)
+               return -EINVAL;
+
+       ieee80211_send_deauth(dev, ifsta, reason);
+       ieee80211_set_disassoc(dev, ifsta, 1);
+       return 0;
+}
+
+
+int ieee80211_sta_disassociate(struct net_device *dev, u16 reason)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+
+       printk(KERN_DEBUG "%s: disassociate(reason=%d)\n",
+              dev->name, reason);
+
+       if (sdata->type != IEEE80211_IF_TYPE_STA)
+               return -EINVAL;
+
+       if (!ifsta->associated)
+               return -1;
+
+       ieee80211_send_disassoc(dev, ifsta, reason);
+       ieee80211_set_disassoc(dev, ifsta, 0);
+       return 0;
+}
diff --git a/net/mac80211/michael.c b/net/mac80211/michael.c
new file mode 100644 (file)
index 0000000..0f844f7
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Michael MIC implementation - optimized for TKIP MIC operations
+ * Copyright 2002-2003, Instant802 Networks, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/types.h>
+
+#include "michael.h"
+
+static inline u32 rotr(u32 val, int bits)
+{
+       return (val >> bits) | (val << (32 - bits));
+}
+
+
+static inline u32 rotl(u32 val, int bits)
+{
+       return (val << bits) | (val >> (32 - bits));
+}
+
+
+static inline u32 xswap(u32 val)
+{
+       return ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
+}
+
+
+#define michael_block(l, r) \
+do { \
+       r ^= rotl(l, 17); \
+       l += r; \
+       r ^= xswap(l); \
+       l += r; \
+       r ^= rotl(l, 3); \
+       l += r; \
+       r ^= rotr(l, 2); \
+       l += r; \
+} while (0)
+
+
+static inline u32 michael_get32(u8 *data)
+{
+       return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
+}
+
+
+static inline void michael_put32(u32 val, u8 *data)
+{
+       data[0] = val & 0xff;
+       data[1] = (val >> 8) & 0xff;
+       data[2] = (val >> 16) & 0xff;
+       data[3] = (val >> 24) & 0xff;
+}
+
+
+void michael_mic(u8 *key, u8 *da, u8 *sa, u8 priority,
+                u8 *data, size_t data_len, u8 *mic)
+{
+       u32 l, r, val;
+       size_t block, blocks, left;
+
+       l = michael_get32(key);
+       r = michael_get32(key + 4);
+
+       /* A pseudo header (DA, SA, Priority, 0, 0, 0) is used in Michael MIC
+        * calculation, but it is _not_ transmitted */
+       l ^= michael_get32(da);
+       michael_block(l, r);
+       l ^= da[4] | (da[5] << 8) | (sa[0] << 16) | (sa[1] << 24);
+       michael_block(l, r);
+       l ^= michael_get32(&sa[2]);
+       michael_block(l, r);
+       l ^= priority;
+       michael_block(l, r);
+
+       /* Real data */
+       blocks = data_len / 4;
+       left = data_len % 4;
+
+       for (block = 0; block < blocks; block++) {
+               l ^= michael_get32(&data[block * 4]);
+               michael_block(l, r);
+       }
+
+       /* Partial block of 0..3 bytes and padding: 0x5a + 4..7 zeros to make
+        * total length a multiple of 4. */
+       val = 0x5a;
+       while (left > 0) {
+               val <<= 8;
+               left--;
+               val |= data[blocks * 4 + left];
+       }
+       l ^= val;
+       michael_block(l, r);
+       /* last block is zero, so l ^ 0 = l */
+       michael_block(l, r);
+
+       michael_put32(l, mic);
+       michael_put32(r, mic + 4);
+}
diff --git a/net/mac80211/michael.h b/net/mac80211/michael.h
new file mode 100644 (file)
index 0000000..2e6aeba
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Michael MIC implementation - optimized for TKIP MIC operations
+ * Copyright 2002-2003, Instant802 Networks, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MICHAEL_H
+#define MICHAEL_H
+
+#include <linux/types.h>
+
+#define MICHAEL_MIC_LEN 8
+
+void michael_mic(u8 *key, u8 *da, u8 *sa, u8 priority,
+                u8 *data, size_t data_len, u8 *mic);
+
+#endif /* MICHAEL_H */
diff --git a/net/mac80211/rc80211_simple.c b/net/mac80211/rc80211_simple.c
new file mode 100644 (file)
index 0000000..2048cfd
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+ * Copyright 2002-2005, Instant802 Networks, Inc.
+ * Copyright 2005, Devicescape Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/compiler.h>
+
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+#include "ieee80211_rate.h"
+#include "debugfs.h"
+
+
+/* This is a minimal implementation of TX rate controlling that can be used
+ * as the default when no improved mechanisms are available. */
+
+
+#define RATE_CONTROL_EMERG_DEC 2
+#define RATE_CONTROL_INTERVAL (HZ / 20)
+#define RATE_CONTROL_MIN_TX 10
+
+MODULE_ALIAS("rc80211_default");
+
+static void rate_control_rate_inc(struct ieee80211_local *local,
+                                 struct sta_info *sta)
+{
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_hw_mode *mode;
+       int i = sta->txrate;
+       int maxrate;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+       if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
+               /* forced unicast rate - do not change STA rate */
+               return;
+       }
+
+       mode = local->oper_hw_mode;
+       maxrate = sdata->bss ? sdata->bss->max_ratectrl_rateidx : -1;
+
+       if (i > mode->num_rates)
+               i = mode->num_rates - 2;
+
+       while (i + 1 < mode->num_rates) {
+               i++;
+               if (sta->supp_rates & BIT(i) &&
+                   mode->rates[i].flags & IEEE80211_RATE_SUPPORTED &&
+                   (maxrate < 0 || i <= maxrate)) {
+                       sta->txrate = i;
+                       break;
+               }
+       }
+}
+
+
+static void rate_control_rate_dec(struct ieee80211_local *local,
+                                 struct sta_info *sta)
+{
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_hw_mode *mode;
+       int i = sta->txrate;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+       if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
+               /* forced unicast rate - do not change STA rate */
+               return;
+       }
+
+       mode = local->oper_hw_mode;
+       if (i > mode->num_rates)
+               i = mode->num_rates;
+
+       while (i > 0) {
+               i--;
+               if (sta->supp_rates & BIT(i) &&
+                   mode->rates[i].flags & IEEE80211_RATE_SUPPORTED) {
+                       sta->txrate = i;
+                       break;
+               }
+       }
+}
+
+
+static struct ieee80211_rate *
+rate_control_lowest_rate(struct ieee80211_local *local,
+                        struct ieee80211_hw_mode *mode)
+{
+       int i;
+
+       for (i = 0; i < mode->num_rates; i++) {
+               struct ieee80211_rate *rate = &mode->rates[i];
+
+               if (rate->flags & IEEE80211_RATE_SUPPORTED)
+                       return rate;
+       }
+
+       printk(KERN_DEBUG "rate_control_lowest_rate - no supported rates "
+              "found\n");
+       return &mode->rates[0];
+}
+
+
+struct global_rate_control {
+       int dummy;
+};
+
+struct sta_rate_control {
+       unsigned long last_rate_change;
+       u32 tx_num_failures;
+       u32 tx_num_xmit;
+
+       unsigned long avg_rate_update;
+       u32 tx_avg_rate_sum;
+       u32 tx_avg_rate_num;
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+       struct dentry *tx_avg_rate_sum_dentry;
+       struct dentry *tx_avg_rate_num_dentry;
+#endif
+};
+
+
+static void rate_control_simple_tx_status(void *priv, struct net_device *dev,
+                                         struct sk_buff *skb,
+                                         struct ieee80211_tx_status *status)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       struct sta_info *sta;
+       struct sta_rate_control *srctrl;
+
+       sta = sta_info_get(local, hdr->addr1);
+
+       if (!sta)
+           return;
+
+       srctrl = sta->rate_ctrl_priv;
+       srctrl->tx_num_xmit++;
+       if (status->excessive_retries) {
+               sta->antenna_sel_tx = sta->antenna_sel_tx == 1 ? 2 : 1;
+               sta->antenna_sel_rx = sta->antenna_sel_rx == 1 ? 2 : 1;
+               if (local->sta_antenna_sel == STA_ANTENNA_SEL_SW_CTRL_DEBUG) {
+                       printk(KERN_DEBUG "%s: " MAC_FMT " TX antenna --> %d "
+                              "RX antenna --> %d (@%lu)\n",
+                              dev->name, MAC_ARG(hdr->addr1),
+                              sta->antenna_sel_tx, sta->antenna_sel_rx, jiffies);
+               }
+               srctrl->tx_num_failures++;
+               sta->tx_retry_failed++;
+               sta->tx_num_consecutive_failures++;
+               sta->tx_num_mpdu_fail++;
+       } else {
+               sta->last_ack_rssi[0] = sta->last_ack_rssi[1];
+               sta->last_ack_rssi[1] = sta->last_ack_rssi[2];
+               sta->last_ack_rssi[2] = status->ack_signal;
+               sta->tx_num_consecutive_failures = 0;
+               sta->tx_num_mpdu_ok++;
+       }
+       sta->tx_retry_count += status->retry_count;
+       sta->tx_num_mpdu_fail += status->retry_count;
+
+       if (time_after(jiffies,
+                      srctrl->last_rate_change + RATE_CONTROL_INTERVAL) &&
+               srctrl->tx_num_xmit > RATE_CONTROL_MIN_TX) {
+               u32 per_failed;
+               srctrl->last_rate_change = jiffies;
+
+               per_failed = (100 * sta->tx_num_mpdu_fail) /
+                       (sta->tx_num_mpdu_fail + sta->tx_num_mpdu_ok);
+               /* TODO: calculate average per_failed to make adjusting
+                * parameters easier */
+#if 0
+               if (net_ratelimit()) {
+                       printk(KERN_DEBUG "MPDU fail=%d ok=%d per_failed=%d\n",
+                              sta->tx_num_mpdu_fail, sta->tx_num_mpdu_ok,
+                              per_failed);
+               }
+#endif
+
+               if (per_failed > local->rate_ctrl_num_down) {
+                       rate_control_rate_dec(local, sta);
+               } else if (per_failed < local->rate_ctrl_num_up) {
+                       rate_control_rate_inc(local, sta);
+               }
+               srctrl->tx_avg_rate_sum += status->control.rate->rate;
+               srctrl->tx_avg_rate_num++;
+               srctrl->tx_num_failures = 0;
+               srctrl->tx_num_xmit = 0;
+       } else if (sta->tx_num_consecutive_failures >=
+                  RATE_CONTROL_EMERG_DEC) {
+               rate_control_rate_dec(local, sta);
+       }
+
+       if (srctrl->avg_rate_update + 60 * HZ < jiffies) {
+               srctrl->avg_rate_update = jiffies;
+               if (srctrl->tx_avg_rate_num > 0) {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+                       printk(KERN_DEBUG "%s: STA " MAC_FMT " Average rate: "
+                              "%d (%d/%d)\n",
+                              dev->name, MAC_ARG(sta->addr),
+                              srctrl->tx_avg_rate_sum /
+                              srctrl->tx_avg_rate_num,
+                              srctrl->tx_avg_rate_sum,
+                              srctrl->tx_avg_rate_num);
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+                       srctrl->tx_avg_rate_sum = 0;
+                       srctrl->tx_avg_rate_num = 0;
+               }
+       }
+
+       sta_info_put(sta);
+}
+
+
+static struct ieee80211_rate *
+rate_control_simple_get_rate(void *priv, struct net_device *dev,
+                            struct sk_buff *skb,
+                            struct rate_control_extra *extra)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       struct ieee80211_hw_mode *mode = extra->mode;
+       struct sta_info *sta;
+       int rateidx, nonerp_idx;
+       u16 fc;
+
+       memset(extra, 0, sizeof(*extra));
+
+       fc = le16_to_cpu(hdr->frame_control);
+       if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
+           (hdr->addr1[0] & 0x01)) {
+               /* Send management frames and broadcast/multicast data using
+                * lowest rate. */
+               /* TODO: this could probably be improved.. */
+               return rate_control_lowest_rate(local, mode);
+       }
+
+       sta = sta_info_get(local, hdr->addr1);
+
+       if (!sta)
+               return rate_control_lowest_rate(local, mode);
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       if (sdata->bss && sdata->bss->force_unicast_rateidx > -1)
+               sta->txrate = sdata->bss->force_unicast_rateidx;
+
+       rateidx = sta->txrate;
+
+       if (rateidx >= mode->num_rates)
+               rateidx = mode->num_rates - 1;
+
+       sta->last_txrate = rateidx;
+       nonerp_idx = rateidx;
+       while (nonerp_idx > 0 &&
+              ((mode->rates[nonerp_idx].flags & IEEE80211_RATE_ERP) ||
+               !(mode->rates[nonerp_idx].flags & IEEE80211_RATE_SUPPORTED) ||
+               !(sta->supp_rates & BIT(nonerp_idx))))
+               nonerp_idx--;
+       extra->nonerp = &mode->rates[nonerp_idx];
+
+       sta_info_put(sta);
+
+       return &mode->rates[rateidx];
+}
+
+
+static void rate_control_simple_rate_init(void *priv, void *priv_sta,
+                                         struct ieee80211_local *local,
+                                         struct sta_info *sta)
+{
+       struct ieee80211_hw_mode *mode;
+       int i;
+       sta->txrate = 0;
+       mode = local->oper_hw_mode;
+       /* TODO: what is a good starting rate for STA? About middle? Maybe not
+        * the lowest or the highest rate.. Could consider using RSSI from
+        * previous packets? Need to have IEEE 802.1X auth succeed immediately
+        * after assoc.. */
+       for (i = 0; i < mode->num_rates; i++) {
+               if ((sta->supp_rates & BIT(i)) &&
+                   (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED))
+                       sta->txrate = i;
+       }
+}
+
+
+static void * rate_control_simple_alloc(struct ieee80211_local *local)
+{
+       struct global_rate_control *rctrl;
+
+       rctrl = kzalloc(sizeof(*rctrl), GFP_ATOMIC);
+
+       return rctrl;
+}
+
+
+static void rate_control_simple_free(void *priv)
+{
+       struct global_rate_control *rctrl = priv;
+       kfree(rctrl);
+}
+
+
+static void rate_control_simple_clear(void *priv)
+{
+}
+
+
+static void * rate_control_simple_alloc_sta(void *priv, gfp_t gfp)
+{
+       struct sta_rate_control *rctrl;
+
+       rctrl = kzalloc(sizeof(*rctrl), gfp);
+
+       return rctrl;
+}
+
+
+static void rate_control_simple_free_sta(void *priv, void *priv_sta)
+{
+       struct sta_rate_control *rctrl = priv_sta;
+       kfree(rctrl);
+}
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+
+static int open_file_generic(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+static ssize_t sta_tx_avg_rate_sum_read(struct file *file,
+                                       char __user *userbuf,
+                                       size_t count, loff_t *ppos)
+{
+       struct sta_rate_control *srctrl = file->private_data;
+       char buf[20];
+
+       sprintf(buf, "%d\n", srctrl->tx_avg_rate_sum);
+       return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
+}
+
+static const struct file_operations sta_tx_avg_rate_sum_ops = {
+       .read = sta_tx_avg_rate_sum_read,
+       .open = open_file_generic,
+};
+
+static ssize_t sta_tx_avg_rate_num_read(struct file *file,
+                                       char __user *userbuf,
+                                       size_t count, loff_t *ppos)
+{
+       struct sta_rate_control *srctrl = file->private_data;
+       char buf[20];
+
+       sprintf(buf, "%d\n", srctrl->tx_avg_rate_num);
+       return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
+}
+
+static const struct file_operations sta_tx_avg_rate_num_ops = {
+       .read = sta_tx_avg_rate_num_read,
+       .open = open_file_generic,
+};
+
+static void rate_control_simple_add_sta_debugfs(void *priv, void *priv_sta,
+                                               struct dentry *dir)
+{
+       struct sta_rate_control *srctrl = priv_sta;
+
+       srctrl->tx_avg_rate_num_dentry =
+               debugfs_create_file("rc_simple_sta_tx_avg_rate_num", 0400,
+                                   dir, srctrl, &sta_tx_avg_rate_num_ops);
+       srctrl->tx_avg_rate_sum_dentry =
+               debugfs_create_file("rc_simple_sta_tx_avg_rate_sum", 0400,
+                                   dir, srctrl, &sta_tx_avg_rate_sum_ops);
+}
+
+static void rate_control_simple_remove_sta_debugfs(void *priv, void *priv_sta)
+{
+       struct sta_rate_control *srctrl = priv_sta;
+
+       debugfs_remove(srctrl->tx_avg_rate_sum_dentry);
+       debugfs_remove(srctrl->tx_avg_rate_num_dentry);
+}
+#endif
+
+static struct rate_control_ops rate_control_simple = {
+       .module = THIS_MODULE,
+       .name = "simple",
+       .tx_status = rate_control_simple_tx_status,
+       .get_rate = rate_control_simple_get_rate,
+       .rate_init = rate_control_simple_rate_init,
+       .clear = rate_control_simple_clear,
+       .alloc = rate_control_simple_alloc,
+       .free = rate_control_simple_free,
+       .alloc_sta = rate_control_simple_alloc_sta,
+       .free_sta = rate_control_simple_free_sta,
+#ifdef CONFIG_MAC80211_DEBUGFS
+       .add_sta_debugfs = rate_control_simple_add_sta_debugfs,
+       .remove_sta_debugfs = rate_control_simple_remove_sta_debugfs,
+#endif
+};
+
+
+static int __init rate_control_simple_init(void)
+{
+       return ieee80211_rate_control_register(&rate_control_simple);
+}
+
+
+static void __exit rate_control_simple_exit(void)
+{
+       ieee80211_rate_control_unregister(&rate_control_simple);
+}
+
+
+module_init(rate_control_simple_init);
+module_exit(rate_control_simple_exit);
+
+MODULE_DESCRIPTION("Simple rate control algorithm for ieee80211");
+MODULE_LICENSE("GPL");
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
new file mode 100644 (file)
index 0000000..ab7b1f0
--- /dev/null
@@ -0,0 +1,470 @@
+/*
+ * Copyright 2002-2005, Instant802 Networks, Inc.
+ * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+#include "ieee80211_rate.h"
+#include "sta_info.h"
+#include "debugfs_key.h"
+#include "debugfs_sta.h"
+
+/* Caller must hold local->sta_lock */
+static void sta_info_hash_add(struct ieee80211_local *local,
+                             struct sta_info *sta)
+{
+       sta->hnext = local->sta_hash[STA_HASH(sta->addr)];
+       local->sta_hash[STA_HASH(sta->addr)] = sta;
+}
+
+
+/* Caller must hold local->sta_lock */
+static void sta_info_hash_del(struct ieee80211_local *local,
+                             struct sta_info *sta)
+{
+       struct sta_info *s;
+
+       s = local->sta_hash[STA_HASH(sta->addr)];
+       if (!s)
+               return;
+       if (memcmp(s->addr, sta->addr, ETH_ALEN) == 0) {
+               local->sta_hash[STA_HASH(sta->addr)] = s->hnext;
+               return;
+       }
+
+       while (s->hnext && memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0)
+               s = s->hnext;
+       if (s->hnext)
+               s->hnext = s->hnext->hnext;
+       else
+               printk(KERN_ERR "%s: could not remove STA " MAC_FMT " from "
+                      "hash table\n", local->mdev->name, MAC_ARG(sta->addr));
+}
+
+static inline void __sta_info_get(struct sta_info *sta)
+{
+       kref_get(&sta->kref);
+}
+
+struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr)
+{
+       struct sta_info *sta;
+
+       spin_lock_bh(&local->sta_lock);
+       sta = local->sta_hash[STA_HASH(addr)];
+       while (sta) {
+               if (memcmp(sta->addr, addr, ETH_ALEN) == 0) {
+                       __sta_info_get(sta);
+                       break;
+               }
+               sta = sta->hnext;
+       }
+       spin_unlock_bh(&local->sta_lock);
+
+       return sta;
+}
+EXPORT_SYMBOL(sta_info_get);
+
+int sta_info_min_txrate_get(struct ieee80211_local *local)
+{
+       struct sta_info *sta;
+       struct ieee80211_hw_mode *mode;
+       int min_txrate = 9999999;
+       int i;
+
+       spin_lock_bh(&local->sta_lock);
+       mode = local->oper_hw_mode;
+       for (i = 0; i < STA_HASH_SIZE; i++) {
+               sta = local->sta_hash[i];
+               while (sta) {
+                       if (sta->txrate < min_txrate)
+                               min_txrate = sta->txrate;
+                       sta = sta->hnext;
+               }
+       }
+       spin_unlock_bh(&local->sta_lock);
+       if (min_txrate == 9999999)
+               min_txrate = 0;
+
+       return mode->rates[min_txrate].rate;
+}
+
+
+static void sta_info_release(struct kref *kref)
+{
+       struct sta_info *sta = container_of(kref, struct sta_info, kref);
+       struct ieee80211_local *local = sta->local;
+       struct sk_buff *skb;
+
+       /* free sta structure; it has already been removed from
+        * hash table etc. external structures. Make sure that all
+        * buffered frames are release (one might have been added
+        * after sta_info_free() was called). */
+       while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
+               local->total_ps_buffered--;
+               dev_kfree_skb_any(skb);
+       }
+       while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
+               dev_kfree_skb_any(skb);
+       }
+       rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv);
+       rate_control_put(sta->rate_ctrl);
+       if (sta->key)
+               ieee80211_debugfs_key_sta_del(sta->key, sta);
+       kfree(sta);
+}
+
+
+void sta_info_put(struct sta_info *sta)
+{
+       kref_put(&sta->kref, sta_info_release);
+}
+EXPORT_SYMBOL(sta_info_put);
+
+
+struct sta_info * sta_info_add(struct ieee80211_local *local,
+                              struct net_device *dev, u8 *addr, gfp_t gfp)
+{
+       struct sta_info *sta;
+
+       sta = kzalloc(sizeof(*sta), gfp);
+       if (!sta)
+               return NULL;
+
+       kref_init(&sta->kref);
+
+       sta->rate_ctrl = rate_control_get(local->rate_ctrl);
+       sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, gfp);
+       if (!sta->rate_ctrl_priv) {
+               rate_control_put(sta->rate_ctrl);
+               kref_put(&sta->kref, sta_info_release);
+               kfree(sta);
+               return NULL;
+       }
+
+       memcpy(sta->addr, addr, ETH_ALEN);
+       sta->local = local;
+       sta->dev = dev;
+       skb_queue_head_init(&sta->ps_tx_buf);
+       skb_queue_head_init(&sta->tx_filtered);
+       __sta_info_get(sta);    /* sta used by caller, decremented by
+                                * sta_info_put() */
+       spin_lock_bh(&local->sta_lock);
+       list_add(&sta->list, &local->sta_list);
+       local->num_sta++;
+       sta_info_hash_add(local, sta);
+       spin_unlock_bh(&local->sta_lock);
+       if (local->ops->sta_table_notification)
+               local->ops->sta_table_notification(local_to_hw(local),
+                                                 local->num_sta);
+       sta->key_idx_compression = HW_KEY_IDX_INVALID;
+
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+       printk(KERN_DEBUG "%s: Added STA " MAC_FMT "\n",
+              local->mdev->name, MAC_ARG(addr));
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+       if (!in_interrupt()) {
+               sta->debugfs_registered = 1;
+               ieee80211_sta_debugfs_add(sta);
+               rate_control_add_sta_debugfs(sta);
+       } else {
+               /* debugfs entry adding might sleep, so schedule process
+                * context task for adding entry for STAs that do not yet
+                * have one. */
+               queue_work(local->hw.workqueue, &local->sta_debugfs_add);
+       }
+#endif
+
+       return sta;
+}
+
+static void finish_sta_info_free(struct ieee80211_local *local,
+                                struct sta_info *sta)
+{
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+       printk(KERN_DEBUG "%s: Removed STA " MAC_FMT "\n",
+              local->mdev->name, MAC_ARG(sta->addr));
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+
+       if (sta->key) {
+               ieee80211_debugfs_key_remove(sta->key);
+               ieee80211_key_free(sta->key);
+               sta->key = NULL;
+       }
+
+       rate_control_remove_sta_debugfs(sta);
+       ieee80211_sta_debugfs_remove(sta);
+
+       sta_info_put(sta);
+}
+
+static void sta_info_remove(struct sta_info *sta)
+{
+       struct ieee80211_local *local = sta->local;
+       struct ieee80211_sub_if_data *sdata;
+
+       sta_info_hash_del(local, sta);
+       list_del(&sta->list);
+       sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+       if (sta->flags & WLAN_STA_PS) {
+               sta->flags &= ~WLAN_STA_PS;
+               if (sdata->bss)
+                       atomic_dec(&sdata->bss->num_sta_ps);
+       }
+       local->num_sta--;
+       sta_info_remove_aid_ptr(sta);
+}
+
+void sta_info_free(struct sta_info *sta, int locked)
+{
+       struct sk_buff *skb;
+       struct ieee80211_local *local = sta->local;
+
+       if (!locked) {
+               spin_lock_bh(&local->sta_lock);
+               sta_info_remove(sta);
+               spin_unlock_bh(&local->sta_lock);
+       } else {
+               sta_info_remove(sta);
+       }
+       if (local->ops->sta_table_notification)
+               local->ops->sta_table_notification(local_to_hw(local),
+                                                 local->num_sta);
+
+       while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
+               local->total_ps_buffered--;
+               dev_kfree_skb_any(skb);
+       }
+       while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
+               dev_kfree_skb_any(skb);
+       }
+
+       if (sta->key) {
+               if (local->ops->set_key) {
+                       struct ieee80211_key_conf *key;
+                       key = ieee80211_key_data2conf(local, sta->key);
+                       if (key) {
+                               local->ops->set_key(local_to_hw(local),
+                                                  DISABLE_KEY,
+                                                  sta->addr, key, sta->aid);
+                               kfree(key);
+                       }
+               }
+       } else if (sta->key_idx_compression != HW_KEY_IDX_INVALID) {
+               struct ieee80211_key_conf conf;
+               memset(&conf, 0, sizeof(conf));
+               conf.hw_key_idx = sta->key_idx_compression;
+               conf.alg = ALG_NULL;
+               conf.flags |= IEEE80211_KEY_FORCE_SW_ENCRYPT;
+               local->ops->set_key(local_to_hw(local), DISABLE_KEY,
+                                  sta->addr, &conf, sta->aid);
+               sta->key_idx_compression = HW_KEY_IDX_INVALID;
+       }
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+       if (in_atomic()) {
+               list_add(&sta->list, &local->deleted_sta_list);
+               queue_work(local->hw.workqueue, &local->sta_debugfs_add);
+       } else
+#endif
+               finish_sta_info_free(local, sta);
+}
+
+
+static inline int sta_info_buffer_expired(struct ieee80211_local *local,
+                                         struct sta_info *sta,
+                                         struct sk_buff *skb)
+{
+       struct ieee80211_tx_packet_data *pkt_data;
+       int timeout;
+
+       if (!skb)
+               return 0;
+
+       pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
+
+       /* Timeout: (2 * listen_interval * beacon_int * 1024 / 1000000) sec */
+       timeout = (sta->listen_interval * local->hw.conf.beacon_int * 32 /
+                  15625) * HZ;
+       if (timeout < STA_TX_BUFFER_EXPIRE)
+               timeout = STA_TX_BUFFER_EXPIRE;
+       return time_after(jiffies, pkt_data->jiffies + timeout);
+}
+
+
+static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
+                                            struct sta_info *sta)
+{
+       unsigned long flags;
+       struct sk_buff *skb;
+
+       if (skb_queue_empty(&sta->ps_tx_buf))
+               return;
+
+       for (;;) {
+               spin_lock_irqsave(&sta->ps_tx_buf.lock, flags);
+               skb = skb_peek(&sta->ps_tx_buf);
+               if (sta_info_buffer_expired(local, sta, skb)) {
+                       skb = __skb_dequeue(&sta->ps_tx_buf);
+                       if (skb_queue_empty(&sta->ps_tx_buf))
+                               sta->flags &= ~WLAN_STA_TIM;
+               } else
+                       skb = NULL;
+               spin_unlock_irqrestore(&sta->ps_tx_buf.lock, flags);
+
+               if (skb) {
+                       local->total_ps_buffered--;
+                       printk(KERN_DEBUG "Buffered frame expired (STA "
+                              MAC_FMT ")\n", MAC_ARG(sta->addr));
+                       dev_kfree_skb(skb);
+               } else
+                       break;
+       }
+}
+
+
+static void sta_info_cleanup(unsigned long data)
+{
+       struct ieee80211_local *local = (struct ieee80211_local *) data;
+       struct sta_info *sta;
+
+       spin_lock_bh(&local->sta_lock);
+       list_for_each_entry(sta, &local->sta_list, list) {
+               __sta_info_get(sta);
+               sta_info_cleanup_expire_buffered(local, sta);
+               sta_info_put(sta);
+       }
+       spin_unlock_bh(&local->sta_lock);
+
+       local->sta_cleanup.expires = jiffies + STA_INFO_CLEANUP_INTERVAL;
+       add_timer(&local->sta_cleanup);
+}
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+static void sta_info_debugfs_add_task(struct work_struct *work)
+{
+       struct ieee80211_local *local =
+               container_of(work, struct ieee80211_local, sta_debugfs_add);
+       struct sta_info *sta, *tmp;
+
+       while (1) {
+               spin_lock_bh(&local->sta_lock);
+               if (!list_empty(&local->deleted_sta_list)) {
+                       sta = list_entry(local->deleted_sta_list.next,
+                                        struct sta_info, list);
+                       list_del(local->deleted_sta_list.next);
+               } else
+                       sta = NULL;
+               spin_unlock_bh(&local->sta_lock);
+               if (!sta)
+                       break;
+               finish_sta_info_free(local, sta);
+       }
+
+       while (1) {
+               sta = NULL;
+               spin_lock_bh(&local->sta_lock);
+               list_for_each_entry(tmp, &local->sta_list, list) {
+                       if (!tmp->debugfs_registered) {
+                               sta = tmp;
+                               __sta_info_get(sta);
+                               break;
+                       }
+               }
+               spin_unlock_bh(&local->sta_lock);
+
+               if (!sta)
+                       break;
+
+               sta->debugfs_registered = 1;
+               ieee80211_sta_debugfs_add(sta);
+               rate_control_add_sta_debugfs(sta);
+               sta_info_put(sta);
+       }
+}
+#endif
+
+void sta_info_init(struct ieee80211_local *local)
+{
+       spin_lock_init(&local->sta_lock);
+       INIT_LIST_HEAD(&local->sta_list);
+       INIT_LIST_HEAD(&local->deleted_sta_list);
+
+       init_timer(&local->sta_cleanup);
+       local->sta_cleanup.expires = jiffies + STA_INFO_CLEANUP_INTERVAL;
+       local->sta_cleanup.data = (unsigned long) local;
+       local->sta_cleanup.function = sta_info_cleanup;
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+       INIT_WORK(&local->sta_debugfs_add, sta_info_debugfs_add_task);
+#endif
+}
+
+int sta_info_start(struct ieee80211_local *local)
+{
+       add_timer(&local->sta_cleanup);
+       return 0;
+}
+
+void sta_info_stop(struct ieee80211_local *local)
+{
+       struct sta_info *sta, *tmp;
+
+       del_timer(&local->sta_cleanup);
+
+       list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
+               /* sta_info_free must be called with 0 as the last
+                * parameter to ensure all debugfs sta entries are
+                * unregistered. We don't need locking at this
+                * point. */
+               sta_info_free(sta, 0);
+       }
+}
+
+void sta_info_remove_aid_ptr(struct sta_info *sta)
+{
+       struct ieee80211_sub_if_data *sdata;
+
+       if (sta->aid <= 0)
+               return;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+
+       if (sdata->local->ops->set_tim)
+               sdata->local->ops->set_tim(local_to_hw(sdata->local),
+                                         sta->aid, 0);
+       if (sdata->bss)
+               __bss_tim_clear(sdata->bss, sta->aid);
+}
+
+
+/**
+ * sta_info_flush - flush matching STA entries from the STA table
+ * @local: local interface data
+ * @dev: matching rule for the net device (sta->dev) or %NULL to match all STAs
+ */
+void sta_info_flush(struct ieee80211_local *local, struct net_device *dev)
+{
+       struct sta_info *sta, *tmp;
+
+       spin_lock_bh(&local->sta_lock);
+       list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
+               if (!dev || dev == sta->dev)
+                       sta_info_free(sta, 1);
+       spin_unlock_bh(&local->sta_lock);
+}
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
new file mode 100644 (file)
index 0000000..b5591d2
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2002-2005, Devicescape Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef STA_INFO_H
+#define STA_INFO_H
+
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/if_ether.h>
+#include <linux/kref.h>
+#include "ieee80211_key.h"
+
+/* Stations flags (struct sta_info::flags) */
+#define WLAN_STA_AUTH BIT(0)
+#define WLAN_STA_ASSOC BIT(1)
+#define WLAN_STA_PS BIT(2)
+#define WLAN_STA_TIM BIT(3) /* TIM bit is on for PS stations */
+#define WLAN_STA_PERM BIT(4) /* permanent; do not remove entry on expiration */
+#define WLAN_STA_AUTHORIZED BIT(5) /* If 802.1X is used, this flag is
+                                   * controlling whether STA is authorized to
+                                   * send and receive non-IEEE 802.1X frames
+                                   */
+#define WLAN_STA_SHORT_PREAMBLE BIT(7)
+#define WLAN_STA_WME BIT(9)
+#define WLAN_STA_WDS BIT(27)
+
+
+struct sta_info {
+       struct kref kref;
+       struct list_head list;
+       struct sta_info *hnext; /* next entry in hash table list */
+
+       struct ieee80211_local *local;
+
+       u8 addr[ETH_ALEN];
+       u16 aid; /* STA's unique AID (1..2007), 0 = not yet assigned */
+       u32 flags; /* WLAN_STA_ */
+
+       struct sk_buff_head ps_tx_buf; /* buffer of TX frames for station in
+                                       * power saving state */
+       int pspoll; /* whether STA has send a PS Poll frame */
+       struct sk_buff_head tx_filtered; /* buffer of TX frames that were
+                                         * already given to low-level driver,
+                                         * but were filtered */
+       int clear_dst_mask;
+
+       unsigned long rx_packets, tx_packets; /* number of RX/TX MSDUs */
+       unsigned long rx_bytes, tx_bytes;
+       unsigned long tx_retry_failed, tx_retry_count;
+       unsigned long tx_filtered_count;
+
+       unsigned int wep_weak_iv_count; /* number of RX frames with weak IV */
+
+       unsigned long last_rx;
+       u32 supp_rates; /* bitmap of supported rates in local->curr_rates */
+       int txrate; /* index in local->curr_rates */
+       int last_txrate; /* last rate used to send a frame to this STA */
+       int last_nonerp_idx;
+
+       struct net_device *dev; /* which net device is this station associated
+                                * to */
+
+       struct ieee80211_key *key;
+
+       u32 tx_num_consecutive_failures;
+       u32 tx_num_mpdu_ok;
+       u32 tx_num_mpdu_fail;
+
+       struct rate_control_ref *rate_ctrl;
+       void *rate_ctrl_priv;
+
+       /* last received seq/frag number from this STA (per RX queue) */
+       __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
+       unsigned long num_duplicates; /* number of duplicate frames received
+                                      * from this STA */
+       unsigned long tx_fragments; /* number of transmitted MPDUs */
+       unsigned long rx_fragments; /* number of received MPDUs */
+       unsigned long rx_dropped; /* number of dropped MPDUs from this STA */
+
+       int last_rssi; /* RSSI of last received frame from this STA */
+       int last_signal; /* signal of last received frame from this STA */
+       int last_noise; /* noise of last received frame from this STA */
+       int last_ack_rssi[3]; /* RSSI of last received ACKs from this STA */
+       unsigned long last_ack;
+       int channel_use;
+       int channel_use_raw;
+
+       u8 antenna_sel_tx;
+       u8 antenna_sel_rx;
+
+
+       int key_idx_compression; /* key table index for compression and TX
+                                 * filtering; used only if sta->key is not
+                                 * set */
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+       int debugfs_registered;
+#endif
+       int assoc_ap; /* whether this is an AP that we are
+                      * associated with as a client */
+
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+       unsigned int wme_rx_queue[NUM_RX_DATA_QUEUES];
+       unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES];
+#endif /* CONFIG_MAC80211_DEBUG_COUNTERS */
+
+       int vlan_id;
+
+       u16 listen_interval;
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+       struct sta_info_debugfsdentries {
+               struct dentry *dir;
+               struct dentry *flags;
+               struct dentry *num_ps_buf_frames;
+               struct dentry *last_ack_rssi;
+               struct dentry *last_ack_ms;
+               struct dentry *inactive_ms;
+               struct dentry *last_seq_ctrl;
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+               struct dentry *wme_rx_queue;
+               struct dentry *wme_tx_queue;
+#endif
+       } debugfs;
+#endif
+};
+
+
+/* Maximum number of concurrently registered stations */
+#define MAX_STA_COUNT 2007
+
+#define STA_HASH_SIZE 256
+#define STA_HASH(sta) (sta[5])
+
+
+/* Maximum number of frames to buffer per power saving station */
+#define STA_MAX_TX_BUFFER 128
+
+/* Minimum buffered frame expiry time. If STA uses listen interval that is
+ * smaller than this value, the minimum value here is used instead. */
+#define STA_TX_BUFFER_EXPIRE (10 * HZ)
+
+/* How often station data is cleaned up (e.g., expiration of buffered frames)
+ */
+#define STA_INFO_CLEANUP_INTERVAL (10 * HZ)
+
+struct sta_info * sta_info_get(struct ieee80211_local *local, u8 *addr);
+int sta_info_min_txrate_get(struct ieee80211_local *local);
+void sta_info_put(struct sta_info *sta);
+struct sta_info * sta_info_add(struct ieee80211_local *local,
+                              struct net_device *dev, u8 *addr, gfp_t gfp);
+void sta_info_free(struct sta_info *sta, int locked);
+void sta_info_init(struct ieee80211_local *local);
+int sta_info_start(struct ieee80211_local *local);
+void sta_info_stop(struct ieee80211_local *local);
+void sta_info_remove_aid_ptr(struct sta_info *sta);
+void sta_info_flush(struct ieee80211_local *local, struct net_device *dev);
+
+#endif /* STA_INFO_H */
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c
new file mode 100644 (file)
index 0000000..4162172
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * Copyright 2002-2004, Instant802 Networks, Inc.
+ * Copyright 2005, Devicescape Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+
+#include <net/mac80211.h>
+#include "ieee80211_key.h"
+#include "tkip.h"
+#include "wep.h"
+
+
+/* TKIP key mixing functions */
+
+
+#define PHASE1_LOOP_COUNT 8
+
+
+/* 2-byte by 2-byte subset of the full AES S-box table; second part of this
+ * table is identical to first part but byte-swapped */
+static const u16 tkip_sbox[256] =
+{
+       0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
+       0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
+       0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
+       0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
+       0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
+       0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
+       0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
+       0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
+       0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
+       0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
+       0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
+       0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
+       0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
+       0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
+       0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
+       0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
+       0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
+       0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
+       0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
+       0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
+       0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
+       0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
+       0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
+       0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
+       0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
+       0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
+       0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
+       0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
+       0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
+       0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
+       0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
+       0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
+};
+
+
+static inline u16 Mk16(u8 x, u8 y)
+{
+       return ((u16) x << 8) | (u16) y;
+}
+
+
+static inline u8 Hi8(u16 v)
+{
+       return v >> 8;
+}
+
+
+static inline u8 Lo8(u16 v)
+{
+       return v & 0xff;
+}
+
+
+static inline u16 Hi16(u32 v)
+{
+       return v >> 16;
+}
+
+
+static inline u16 Lo16(u32 v)
+{
+       return v & 0xffff;
+}
+
+
+static inline u16 RotR1(u16 v)
+{
+       return (v >> 1) | ((v & 0x0001) << 15);
+}
+
+
+static inline u16 tkip_S(u16 val)
+{
+       u16 a = tkip_sbox[Hi8(val)];
+
+       return tkip_sbox[Lo8(val)] ^ Hi8(a) ^ (Lo8(a) << 8);
+}
+
+
+
+/* P1K := Phase1(TA, TK, TSC)
+ * TA = transmitter address (48 bits)
+ * TK = dot11DefaultKeyValue or dot11KeyMappingValue (128 bits)
+ * TSC = TKIP sequence counter (48 bits, only 32 msb bits used)
+ * P1K: 80 bits
+ */
+static void tkip_mixing_phase1(const u8 *ta, const u8 *tk, u32 tsc_IV32,
+                              u16 *p1k)
+{
+       int i, j;
+
+       p1k[0] = Lo16(tsc_IV32);
+       p1k[1] = Hi16(tsc_IV32);
+       p1k[2] = Mk16(ta[1], ta[0]);
+       p1k[3] = Mk16(ta[3], ta[2]);
+       p1k[4] = Mk16(ta[5], ta[4]);
+
+       for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
+               j = 2 * (i & 1);
+               p1k[0] += tkip_S(p1k[4] ^ Mk16(tk[ 1 + j], tk[ 0 + j]));
+               p1k[1] += tkip_S(p1k[0] ^ Mk16(tk[ 5 + j], tk[ 4 + j]));
+               p1k[2] += tkip_S(p1k[1] ^ Mk16(tk[ 9 + j], tk[ 8 + j]));
+               p1k[3] += tkip_S(p1k[2] ^ Mk16(tk[13 + j], tk[12 + j]));
+               p1k[4] += tkip_S(p1k[3] ^ Mk16(tk[ 1 + j], tk[ 0 + j])) + i;
+       }
+}
+
+
+static void tkip_mixing_phase2(const u16 *p1k, const u8 *tk, u16 tsc_IV16,
+                              u8 *rc4key)
+{
+       u16 ppk[6];
+       int i;
+
+       ppk[0] = p1k[0];
+       ppk[1] = p1k[1];
+       ppk[2] = p1k[2];
+       ppk[3] = p1k[3];
+       ppk[4] = p1k[4];
+       ppk[5] = p1k[4] + tsc_IV16;
+
+       ppk[0] += tkip_S(ppk[5] ^ Mk16(tk[ 1], tk[ 0]));
+       ppk[1] += tkip_S(ppk[0] ^ Mk16(tk[ 3], tk[ 2]));
+       ppk[2] += tkip_S(ppk[1] ^ Mk16(tk[ 5], tk[ 4]));
+       ppk[3] += tkip_S(ppk[2] ^ Mk16(tk[ 7], tk[ 6]));
+       ppk[4] += tkip_S(ppk[3] ^ Mk16(tk[ 9], tk[ 8]));
+       ppk[5] += tkip_S(ppk[4] ^ Mk16(tk[11], tk[10]));
+       ppk[0] +=  RotR1(ppk[5] ^ Mk16(tk[13], tk[12]));
+       ppk[1] +=  RotR1(ppk[0] ^ Mk16(tk[15], tk[14]));
+       ppk[2] +=  RotR1(ppk[1]);
+       ppk[3] +=  RotR1(ppk[2]);
+       ppk[4] +=  RotR1(ppk[3]);
+       ppk[5] +=  RotR1(ppk[4]);
+
+       rc4key[0] = Hi8(tsc_IV16);
+       rc4key[1] = (Hi8(tsc_IV16) | 0x20) & 0x7f;
+       rc4key[2] = Lo8(tsc_IV16);
+       rc4key[3] = Lo8((ppk[5] ^ Mk16(tk[1], tk[0])) >> 1);
+
+       for (i = 0; i < 6; i++) {
+               rc4key[4 + 2 * i] = Lo8(ppk[i]);
+               rc4key[5 + 2 * i] = Hi8(ppk[i]);
+       }
+}
+
+
+/* Add TKIP IV and Ext. IV at @pos. @iv0, @iv1, and @iv2 are the first octets
+ * of the IV. Returns pointer to the octet following IVs (i.e., beginning of
+ * the packet payload). */
+u8 * ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key,
+                          u8 iv0, u8 iv1, u8 iv2)
+{
+       *pos++ = iv0;
+       *pos++ = iv1;
+       *pos++ = iv2;
+       *pos++ = (key->keyidx << 6) | (1 << 5) /* Ext IV */;
+       *pos++ = key->u.tkip.iv32 & 0xff;
+       *pos++ = (key->u.tkip.iv32 >> 8) & 0xff;
+       *pos++ = (key->u.tkip.iv32 >> 16) & 0xff;
+       *pos++ = (key->u.tkip.iv32 >> 24) & 0xff;
+       return pos;
+}
+
+
+void ieee80211_tkip_gen_phase1key(struct ieee80211_key *key, u8 *ta,
+                                 u16 *phase1key)
+{
+       tkip_mixing_phase1(ta, &key->key[ALG_TKIP_TEMP_ENCR_KEY],
+                          key->u.tkip.iv32, phase1key);
+}
+
+void ieee80211_tkip_gen_rc4key(struct ieee80211_key *key, u8 *ta,
+                              u8 *rc4key)
+{
+       /* Calculate per-packet key */
+       if (key->u.tkip.iv16 == 0 || !key->u.tkip.tx_initialized) {
+               /* IV16 wrapped around - perform TKIP phase 1 */
+               tkip_mixing_phase1(ta, &key->key[ALG_TKIP_TEMP_ENCR_KEY],
+                                  key->u.tkip.iv32, key->u.tkip.p1k);
+               key->u.tkip.tx_initialized = 1;
+       }
+
+       tkip_mixing_phase2(key->u.tkip.p1k, &key->key[ALG_TKIP_TEMP_ENCR_KEY],
+                          key->u.tkip.iv16, rc4key);
+}
+
+/* Encrypt packet payload with TKIP using @key. @pos is a pointer to the
+ * beginning of the buffer containing payload. This payload must include
+ * headroom of eight octets for IV and Ext. IV and taildroom of four octets
+ * for ICV. @payload_len is the length of payload (_not_ including extra
+ * headroom and tailroom). @ta is the transmitter addresses. */
+void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
+                                struct ieee80211_key *key,
+                                u8 *pos, size_t payload_len, u8 *ta)
+{
+       u8 rc4key[16];
+
+       ieee80211_tkip_gen_rc4key(key, ta, rc4key);
+       pos = ieee80211_tkip_add_iv(pos, key, rc4key[0], rc4key[1], rc4key[2]);
+       ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len);
+}
+
+
+/* Decrypt packet payload with TKIP using @key. @pos is a pointer to the
+ * beginning of the buffer containing IEEE 802.11 header payload, i.e.,
+ * including IV, Ext. IV, real data, Michael MIC, ICV. @payload_len is the
+ * length of payload, including IV, Ext. IV, MIC, ICV.  */
+int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
+                               struct ieee80211_key *key,
+                               u8 *payload, size_t payload_len, u8 *ta,
+                               int only_iv, int queue)
+{
+       u32 iv32;
+       u32 iv16;
+       u8 rc4key[16], keyid, *pos = payload;
+       int res;
+
+       if (payload_len < 12)
+               return -1;
+
+       iv16 = (pos[0] << 8) | pos[2];
+       keyid = pos[3];
+       iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
+       pos += 8;
+#ifdef CONFIG_TKIP_DEBUG
+       {
+               int i;
+               printk(KERN_DEBUG "TKIP decrypt: data(len=%zd)", payload_len);
+               for (i = 0; i < payload_len; i++)
+                       printk(" %02x", payload[i]);
+               printk("\n");
+               printk(KERN_DEBUG "TKIP decrypt: iv16=%04x iv32=%08x\n",
+                      iv16, iv32);
+       }
+#endif /* CONFIG_TKIP_DEBUG */
+
+       if (!(keyid & (1 << 5)))
+               return TKIP_DECRYPT_NO_EXT_IV;
+
+       if ((keyid >> 6) != key->keyidx)
+               return TKIP_DECRYPT_INVALID_KEYIDX;
+
+       if (key->u.tkip.rx_initialized[queue] &&
+           (iv32 < key->u.tkip.iv32_rx[queue] ||
+            (iv32 == key->u.tkip.iv32_rx[queue] &&
+             iv16 <= key->u.tkip.iv16_rx[queue]))) {
+#ifdef CONFIG_TKIP_DEBUG
+               printk(KERN_DEBUG "TKIP replay detected for RX frame from "
+                      MAC_FMT " (RX IV (%04x,%02x) <= prev. IV (%04x,%02x)\n",
+                      MAC_ARG(ta),
+                      iv32, iv16, key->u.tkip.iv32_rx[queue],
+                      key->u.tkip.iv16_rx[queue]);
+#endif /* CONFIG_TKIP_DEBUG */
+               return TKIP_DECRYPT_REPLAY;
+       }
+
+       if (only_iv) {
+               res = TKIP_DECRYPT_OK;
+               key->u.tkip.rx_initialized[queue] = 1;
+               goto done;
+       }
+
+       if (!key->u.tkip.rx_initialized[queue] ||
+           key->u.tkip.iv32_rx[queue] != iv32) {
+               key->u.tkip.rx_initialized[queue] = 1;
+               /* IV16 wrapped around - perform TKIP phase 1 */
+               tkip_mixing_phase1(ta, &key->key[ALG_TKIP_TEMP_ENCR_KEY],
+                                  iv32, key->u.tkip.p1k_rx[queue]);
+#ifdef CONFIG_TKIP_DEBUG
+               {
+                       int i;
+                       printk(KERN_DEBUG "TKIP decrypt: Phase1 TA=" MAC_FMT
+                              " TK=", MAC_ARG(ta));
+                       for (i = 0; i < 16; i++)
+                               printk("%02x ",
+                                      key->key[ALG_TKIP_TEMP_ENCR_KEY + i]);
+                       printk("\n");
+                       printk(KERN_DEBUG "TKIP decrypt: P1K=");
+                       for (i = 0; i < 5; i++)
+                               printk("%04x ", key->u.tkip.p1k_rx[queue][i]);
+                       printk("\n");
+               }
+#endif /* CONFIG_TKIP_DEBUG */
+       }
+
+       tkip_mixing_phase2(key->u.tkip.p1k_rx[queue],
+                          &key->key[ALG_TKIP_TEMP_ENCR_KEY],
+                          iv16, rc4key);
+#ifdef CONFIG_TKIP_DEBUG
+       {
+               int i;
+               printk(KERN_DEBUG "TKIP decrypt: Phase2 rc4key=");
+               for (i = 0; i < 16; i++)
+                       printk("%02x ", rc4key[i]);
+               printk("\n");
+       }
+#endif /* CONFIG_TKIP_DEBUG */
+
+       res = ieee80211_wep_decrypt_data(tfm, rc4key, 16, pos, payload_len - 12);
+ done:
+       if (res == TKIP_DECRYPT_OK) {
+               /* FIX: these should be updated only after Michael MIC has been
+                * verified */
+               /* Record previously received IV */
+               key->u.tkip.iv32_rx[queue] = iv32;
+               key->u.tkip.iv16_rx[queue] = iv16;
+       }
+
+       return res;
+}
+
+
diff --git a/net/mac80211/tkip.h b/net/mac80211/tkip.h
new file mode 100644 (file)
index 0000000..a0d181a
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2002-2004, Instant802 Networks, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef TKIP_H
+#define TKIP_H
+
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include "ieee80211_key.h"
+
+u8 * ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key,
+                          u8 iv0, u8 iv1, u8 iv2);
+void ieee80211_tkip_gen_phase1key(struct ieee80211_key *key, u8 *ta,
+                                 u16 *phase1key);
+void ieee80211_tkip_gen_rc4key(struct ieee80211_key *key, u8 *ta,
+                              u8 *rc4key);
+void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
+                                struct ieee80211_key *key,
+                                u8 *pos, size_t payload_len, u8 *ta);
+enum {
+       TKIP_DECRYPT_OK = 0,
+       TKIP_DECRYPT_NO_EXT_IV = -1,
+       TKIP_DECRYPT_INVALID_KEYIDX = -2,
+       TKIP_DECRYPT_REPLAY = -3,
+};
+int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
+                               struct ieee80211_key *key,
+                               u8 *payload, size_t payload_len, u8 *ta,
+                               int only_iv, int queue);
+
+#endif /* TKIP_H */
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
new file mode 100644 (file)
index 0000000..1ad3d75
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * Software WEP encryption implementation
+ * Copyright 2002, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright 2003, Instant802 Networks, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <linux/random.h>
+#include <linux/compiler.h>
+#include <linux/crc32.h>
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <linux/mm.h>
+#include <asm/scatterlist.h>
+
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+#include "wep.h"
+
+
+int ieee80211_wep_init(struct ieee80211_local *local)
+{
+       /* start WEP IV from a random value */
+       get_random_bytes(&local->wep_iv, WEP_IV_LEN);
+
+       local->wep_tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0,
+                                               CRYPTO_ALG_ASYNC);
+       if (IS_ERR(local->wep_tx_tfm))
+               return -ENOMEM;
+
+       local->wep_rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0,
+                                               CRYPTO_ALG_ASYNC);
+       if (IS_ERR(local->wep_rx_tfm)) {
+               crypto_free_blkcipher(local->wep_tx_tfm);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+void ieee80211_wep_free(struct ieee80211_local *local)
+{
+       crypto_free_blkcipher(local->wep_tx_tfm);
+       crypto_free_blkcipher(local->wep_rx_tfm);
+}
+
+static inline int ieee80211_wep_weak_iv(u32 iv, int keylen)
+{
+       /* Fluhrer, Mantin, and Shamir have reported weaknesses in the
+        * key scheduling algorithm of RC4. At least IVs (KeyByte + 3,
+        * 0xff, N) can be used to speedup attacks, so avoid using them. */
+       if ((iv & 0xff00) == 0xff00) {
+               u8 B = (iv >> 16) & 0xff;
+               if (B >= 3 && B < 3 + keylen)
+                       return 1;
+       }
+       return 0;
+}
+
+
+void ieee80211_wep_get_iv(struct ieee80211_local *local,
+                         struct ieee80211_key *key, u8 *iv)
+{
+       local->wep_iv++;
+       if (ieee80211_wep_weak_iv(local->wep_iv, key->keylen))
+               local->wep_iv += 0x0100;
+
+       if (!iv)
+               return;
+
+       *iv++ = (local->wep_iv >> 16) & 0xff;
+       *iv++ = (local->wep_iv >> 8) & 0xff;
+       *iv++ = local->wep_iv & 0xff;
+       *iv++ = key->keyidx << 6;
+}
+
+
+u8 * ieee80211_wep_add_iv(struct ieee80211_local *local,
+                         struct sk_buff *skb,
+                         struct ieee80211_key *key)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       u16 fc;
+       int hdrlen;
+       u8 *newhdr;
+
+       fc = le16_to_cpu(hdr->frame_control);
+       fc |= IEEE80211_FCTL_PROTECTED;
+       hdr->frame_control = cpu_to_le16(fc);
+
+       if ((skb_headroom(skb) < WEP_IV_LEN ||
+            skb_tailroom(skb) < WEP_ICV_LEN)) {
+               I802_DEBUG_INC(local->tx_expand_skb_head);
+               if (unlikely(pskb_expand_head(skb, WEP_IV_LEN, WEP_ICV_LEN,
+                                             GFP_ATOMIC)))
+                       return NULL;
+       }
+
+       hdrlen = ieee80211_get_hdrlen(fc);
+       newhdr = skb_push(skb, WEP_IV_LEN);
+       memmove(newhdr, newhdr + WEP_IV_LEN, hdrlen);
+       ieee80211_wep_get_iv(local, key, newhdr + hdrlen);
+       return newhdr + hdrlen;
+}
+
+
+void ieee80211_wep_remove_iv(struct ieee80211_local *local,
+                            struct sk_buff *skb,
+                            struct ieee80211_key *key)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       u16 fc;
+       int hdrlen;
+
+       fc = le16_to_cpu(hdr->frame_control);
+       hdrlen = ieee80211_get_hdrlen(fc);
+       memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen);
+       skb_pull(skb, WEP_IV_LEN);
+}
+
+
+/* Perform WEP encryption using given key. data buffer must have tailroom
+ * for 4-byte ICV. data_len must not include this ICV. Note: this function
+ * does _not_ add IV. data = RC4(data | CRC32(data)) */
+void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
+                               size_t klen, u8 *data, size_t data_len)
+{
+       struct blkcipher_desc desc = { .tfm = tfm };
+       struct scatterlist sg;
+       __le32 *icv;
+
+       icv = (__le32 *)(data + data_len);
+       *icv = cpu_to_le32(~crc32_le(~0, data, data_len));
+
+       crypto_blkcipher_setkey(tfm, rc4key, klen);
+       sg.page = virt_to_page(data);
+       sg.offset = offset_in_page(data);
+       sg.length = data_len + WEP_ICV_LEN;
+       crypto_blkcipher_encrypt(&desc, &sg, &sg, sg.length);
+}
+
+
+/* Perform WEP encryption on given skb. 4 bytes of extra space (IV) in the
+ * beginning of the buffer 4 bytes of extra space (ICV) in the end of the
+ * buffer will be added. Both IV and ICV will be transmitted, so the
+ * payload length increases with 8 bytes.
+ *
+ * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
+ */
+int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb,
+                         struct ieee80211_key *key)
+{
+       u32 klen;
+       u8 *rc4key, *iv;
+       size_t len;
+
+       if (!key || key->alg != ALG_WEP)
+               return -1;
+
+       klen = 3 + key->keylen;
+       rc4key = kmalloc(klen, GFP_ATOMIC);
+       if (!rc4key)
+               return -1;
+
+       iv = ieee80211_wep_add_iv(local, skb, key);
+       if (!iv) {
+               kfree(rc4key);
+               return -1;
+       }
+
+       len = skb->len - (iv + WEP_IV_LEN - skb->data);
+
+       /* Prepend 24-bit IV to RC4 key */
+       memcpy(rc4key, iv, 3);
+
+       /* Copy rest of the WEP key (the secret part) */
+       memcpy(rc4key + 3, key->key, key->keylen);
+
+       /* Add room for ICV */
+       skb_put(skb, WEP_ICV_LEN);
+
+       ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, klen,
+                                  iv + WEP_IV_LEN, len);
+
+       kfree(rc4key);
+
+       return 0;
+}
+
+
+/* Perform WEP decryption using given key. data buffer includes encrypted
+ * payload, including 4-byte ICV, but _not_ IV. data_len must not include ICV.
+ * Return 0 on success and -1 on ICV mismatch. */
+int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
+                              size_t klen, u8 *data, size_t data_len)
+{
+       struct blkcipher_desc desc = { .tfm = tfm };
+       struct scatterlist sg;
+       __le32 crc;
+
+       crypto_blkcipher_setkey(tfm, rc4key, klen);
+       sg.page = virt_to_page(data);
+       sg.offset = offset_in_page(data);
+       sg.length = data_len + WEP_ICV_LEN;
+       crypto_blkcipher_decrypt(&desc, &sg, &sg, sg.length);
+
+       crc = cpu_to_le32(~crc32_le(~0, data, data_len));
+       if (memcmp(&crc, data + data_len, WEP_ICV_LEN) != 0)
+               /* ICV mismatch */
+               return -1;
+
+       return 0;
+}
+
+
+/* Perform WEP decryption on given skb. Buffer includes whole WEP part of
+ * the frame: IV (4 bytes), encrypted payload (including SNAP header),
+ * ICV (4 bytes). skb->len includes both IV and ICV.
+ *
+ * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
+ * failure. If frame is OK, IV and ICV will be removed, i.e., decrypted payload
+ * is moved to the beginning of the skb and skb length will be reduced.
+ */
+int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb,
+                         struct ieee80211_key *key)
+{
+       u32 klen;
+       u8 *rc4key;
+       u8 keyidx;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       u16 fc;
+       int hdrlen;
+       size_t len;
+       int ret = 0;
+
+       fc = le16_to_cpu(hdr->frame_control);
+       if (!(fc & IEEE80211_FCTL_PROTECTED))
+               return -1;
+
+       hdrlen = ieee80211_get_hdrlen(fc);
+
+       if (skb->len < 8 + hdrlen)
+               return -1;
+
+       len = skb->len - hdrlen - 8;
+
+       keyidx = skb->data[hdrlen + 3] >> 6;
+
+       if (!key || keyidx != key->keyidx || key->alg != ALG_WEP)
+               return -1;
+
+       klen = 3 + key->keylen;
+
+       rc4key = kmalloc(klen, GFP_ATOMIC);
+       if (!rc4key)
+               return -1;
+
+       /* Prepend 24-bit IV to RC4 key */
+       memcpy(rc4key, skb->data + hdrlen, 3);
+
+       /* Copy rest of the WEP key (the secret part) */
+       memcpy(rc4key + 3, key->key, key->keylen);
+
+       if (ieee80211_wep_decrypt_data(local->wep_rx_tfm, rc4key, klen,
+                                      skb->data + hdrlen + WEP_IV_LEN,
+                                      len)) {
+               printk(KERN_DEBUG "WEP decrypt failed (ICV)\n");
+               ret = -1;
+       }
+
+       kfree(rc4key);
+
+       /* Trim ICV */
+       skb_trim(skb, skb->len - WEP_ICV_LEN);
+
+       /* Remove IV */
+       memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen);
+       skb_pull(skb, WEP_IV_LEN);
+
+       return ret;
+}
+
+
+int ieee80211_wep_get_keyidx(struct sk_buff *skb)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       u16 fc;
+       int hdrlen;
+
+       fc = le16_to_cpu(hdr->frame_control);
+       if (!(fc & IEEE80211_FCTL_PROTECTED))
+               return -1;
+
+       hdrlen = ieee80211_get_hdrlen(fc);
+
+       if (skb->len < 8 + hdrlen)
+               return -1;
+
+       return skb->data[hdrlen + 3] >> 6;
+}
+
+
+u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       u16 fc;
+       int hdrlen;
+       u8 *ivpos;
+       u32 iv;
+
+       fc = le16_to_cpu(hdr->frame_control);
+       if (!(fc & IEEE80211_FCTL_PROTECTED))
+               return NULL;
+
+       hdrlen = ieee80211_get_hdrlen(fc);
+       ivpos = skb->data + hdrlen;
+       iv = (ivpos[0] << 16) | (ivpos[1] << 8) | ivpos[2];
+
+       if (ieee80211_wep_weak_iv(iv, key->keylen))
+               return ivpos;
+
+       return NULL;
+}
diff --git a/net/mac80211/wep.h b/net/mac80211/wep.h
new file mode 100644 (file)
index 0000000..bfe29e8
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Software WEP encryption implementation
+ * Copyright 2002, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright 2003, Instant802 Networks, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef WEP_H
+#define WEP_H
+
+#include <linux/skbuff.h>
+#include <linux/types.h>
+#include "ieee80211_i.h"
+#include "ieee80211_key.h"
+
+int ieee80211_wep_init(struct ieee80211_local *local);
+void ieee80211_wep_free(struct ieee80211_local *local);
+void ieee80211_wep_get_iv(struct ieee80211_local *local,
+                         struct ieee80211_key *key, u8 *iv);
+u8 * ieee80211_wep_add_iv(struct ieee80211_local *local,
+                         struct sk_buff *skb,
+                         struct ieee80211_key *key);
+void ieee80211_wep_remove_iv(struct ieee80211_local *local,
+                            struct sk_buff *skb,
+                            struct ieee80211_key *key);
+void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
+                               size_t klen, u8 *data, size_t data_len);
+int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key,
+                              size_t klen, u8 *data, size_t data_len);
+int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb,
+                         struct ieee80211_key *key);
+int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb,
+                         struct ieee80211_key *key);
+int ieee80211_wep_get_keyidx(struct sk_buff *skb);
+u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key);
+
+#endif /* WEP_H */
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
new file mode 100644 (file)
index 0000000..89ce815
--- /dev/null
@@ -0,0 +1,678 @@
+/*
+ * Copyright 2004, Instant802 Networks, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/module.h>
+#include <linux/if_arp.h>
+#include <linux/types.h>
+#include <net/ip.h>
+#include <net/pkt_sched.h>
+
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+#include "wme.h"
+
+static inline int WLAN_FC_IS_QOS_DATA(u16 fc)
+{
+       return (fc & 0x8C) == 0x88;
+}
+
+
+ieee80211_txrx_result
+ieee80211_rx_h_parse_qos(struct ieee80211_txrx_data *rx)
+{
+       u8 *data = rx->skb->data;
+       int tid;
+
+       /* does the frame have a qos control field? */
+       if (WLAN_FC_IS_QOS_DATA(rx->fc)) {
+               u8 *qc = data + ieee80211_get_hdrlen(rx->fc) - QOS_CONTROL_LEN;
+               /* frame has qos control */
+               tid = qc[0] & QOS_CONTROL_TID_MASK;
+       } else {
+               if (unlikely((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)) {
+                       /* Separate TID for management frames */
+                       tid = NUM_RX_DATA_QUEUES - 1;
+               } else {
+                       /* no qos control present */
+                       tid = 0; /* 802.1d - Best Effort */
+               }
+       }
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+       I802_DEBUG_INC(rx->local->wme_rx_queue[tid]);
+       if (rx->sta) {
+               I802_DEBUG_INC(rx->sta->wme_rx_queue[tid]);
+       }
+#endif /* CONFIG_MAC80211_DEBUG_COUNTERS */
+
+       rx->u.rx.queue = tid;
+       /* Set skb->priority to 1d tag if highest order bit of TID is not set.
+        * For now, set skb->priority to 0 for other cases. */
+       rx->skb->priority = (tid > 7) ? 0 : tid;
+
+       return TXRX_CONTINUE;
+}
+
+
+ieee80211_txrx_result
+ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx)
+{
+       u16 fc = rx->fc;
+       u8 *data = rx->skb->data;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) data;
+
+       if (!WLAN_FC_IS_QOS_DATA(fc))
+               return TXRX_CONTINUE;
+
+       /* remove the qos control field, update frame type and meta-data */
+       memmove(data + 2, data, ieee80211_get_hdrlen(fc) - 2);
+       hdr = (struct ieee80211_hdr *) skb_pull(rx->skb, 2);
+       /* change frame type to non QOS */
+       rx->fc = fc &= ~IEEE80211_STYPE_QOS_DATA;
+       hdr->frame_control = cpu_to_le16(fc);
+
+       return TXRX_CONTINUE;
+}
+
+
+#ifdef CONFIG_NET_SCHED
+/* maximum number of hardware queues we support. */
+#define TC_80211_MAX_QUEUES 8
+
+struct ieee80211_sched_data
+{
+       struct tcf_proto *filter_list;
+       struct Qdisc *queues[TC_80211_MAX_QUEUES];
+       struct sk_buff_head requeued[TC_80211_MAX_QUEUES];
+};
+
+
+/* given a data frame determine the 802.1p/1d tag to use */
+static inline unsigned classify_1d(struct sk_buff *skb, struct Qdisc *qd)
+{
+       struct iphdr *ip;
+       int dscp;
+       int offset;
+
+       struct ieee80211_sched_data *q = qdisc_priv(qd);
+       struct tcf_result res = { -1, 0 };
+
+       /* if there is a user set filter list, call out to that */
+       if (q->filter_list) {
+               tc_classify(skb, q->filter_list, &res);
+               if (res.class != -1)
+                       return res.class;
+       }
+
+       /* skb->priority values from 256->263 are magic values to
+        * directly indicate a specific 802.1d priority.
+        * This is used to allow 802.1d priority to be passed directly in
+        * from VLAN tags, etc. */
+       if (skb->priority >= 256 && skb->priority <= 263)
+               return skb->priority - 256;
+
+       /* check there is a valid IP header present */
+       offset = ieee80211_get_hdrlen_from_skb(skb) + 8 /* LLC + proto */;
+       if (skb->protocol != __constant_htons(ETH_P_IP) ||
+           skb->len < offset + sizeof(*ip))
+               return 0;
+
+       ip = (struct iphdr *) (skb->data + offset);
+
+       dscp = ip->tos & 0xfc;
+       if (dscp & 0x1c)
+               return 0;
+       return dscp >> 5;
+}
+
+
+static inline int wme_downgrade_ac(struct sk_buff *skb)
+{
+       switch (skb->priority) {
+       case 6:
+       case 7:
+               skb->priority = 5; /* VO -> VI */
+               return 0;
+       case 4:
+       case 5:
+               skb->priority = 3; /* VI -> BE */
+               return 0;
+       case 0:
+       case 3:
+               skb->priority = 2; /* BE -> BK */
+               return 0;
+       default:
+               return -1;
+       }
+}
+
+
+/* positive return value indicates which queue to use
+ * negative return value indicates to drop the frame */
+static inline int classify80211(struct sk_buff *skb, struct Qdisc *qd)
+{
+       struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+       struct ieee80211_tx_packet_data *pkt_data =
+               (struct ieee80211_tx_packet_data *) skb->cb;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       unsigned short fc = le16_to_cpu(hdr->frame_control);
+       int qos;
+       const int ieee802_1d_to_ac[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
+
+       /* see if frame is data or non data frame */
+       if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) {
+               /* management frames go on AC_VO queue, but are sent
+               * without QoS control fields */
+               return IEEE80211_TX_QUEUE_DATA0;
+       }
+
+       if (unlikely(pkt_data->mgmt_iface)) {
+               /* Data frames from hostapd (mainly, EAPOL) use AC_VO
+               * and they will include QoS control fields if
+               * the target STA is using WME. */
+               skb->priority = 7;
+               return ieee802_1d_to_ac[skb->priority];
+       }
+
+       /* is this a QoS frame? */
+       qos = fc & IEEE80211_STYPE_QOS_DATA;
+
+       if (!qos) {
+               skb->priority = 0; /* required for correct WPA/11i MIC */
+               return ieee802_1d_to_ac[skb->priority];
+       }
+
+       /* use the data classifier to determine what 802.1d tag the
+       * data frame has */
+       skb->priority = classify_1d(skb, qd);
+
+       /* incase we are a client verify acm is not set for this ac */
+       while (unlikely(local->wmm_acm & BIT(skb->priority))) {
+               if (wme_downgrade_ac(skb)) {
+                       /* No AC with lower priority has acm=0,
+                       * drop packet. */
+                       return -1;
+               }
+       }
+
+       /* look up which queue to use for frames with this 1d tag */
+       return ieee802_1d_to_ac[skb->priority];
+}
+
+
+static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
+{
+       struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+       struct ieee80211_sched_data *q = qdisc_priv(qd);
+       struct ieee80211_tx_packet_data *pkt_data =
+               (struct ieee80211_tx_packet_data *) skb->cb;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       unsigned short fc = le16_to_cpu(hdr->frame_control);
+       struct Qdisc *qdisc;
+       int err, queue;
+
+       if (pkt_data->requeue) {
+               skb_queue_tail(&q->requeued[pkt_data->queue], skb);
+               qd->q.qlen++;
+               return 0;
+       }
+
+       queue = classify80211(skb, qd);
+
+       /* now we know the 1d priority, fill in the QoS header if there is one
+        */
+       if (WLAN_FC_IS_QOS_DATA(fc)) {
+               u8 *p = skb->data + ieee80211_get_hdrlen(fc) - 2;
+               u8 qos_hdr = skb->priority & QOS_CONTROL_TAG1D_MASK;
+               if (local->wifi_wme_noack_test)
+                       qos_hdr |= QOS_CONTROL_ACK_POLICY_NOACK <<
+                                       QOS_CONTROL_ACK_POLICY_SHIFT;
+               /* qos header is 2 bytes, second reserved */
+               *p = qos_hdr;
+               p++;
+               *p = 0;
+       }
+
+       if (unlikely(queue >= local->hw.queues)) {
+#if 0
+               if (net_ratelimit()) {
+                       printk(KERN_DEBUG "%s - queue=%d (hw does not "
+                              "support) -> %d\n",
+                              __func__, queue, local->hw.queues - 1);
+               }
+#endif
+               queue = local->hw.queues - 1;
+       }
+
+       if (unlikely(queue < 0)) {
+                       kfree_skb(skb);
+                       err = NET_XMIT_DROP;
+       } else {
+               pkt_data->queue = (unsigned int) queue;
+               qdisc = q->queues[queue];
+               err = qdisc->enqueue(skb, qdisc);
+               if (err == NET_XMIT_SUCCESS) {
+                       qd->q.qlen++;
+                       qd->bstats.bytes += skb->len;
+                       qd->bstats.packets++;
+                       return NET_XMIT_SUCCESS;
+               }
+       }
+       qd->qstats.drops++;
+       return err;
+}
+
+
+/* TODO: clean up the cases where master_hard_start_xmit
+ * returns non 0 - it shouldn't ever do that. Once done we
+ * can remove this function */
+static int wme_qdiscop_requeue(struct sk_buff *skb, struct Qdisc* qd)
+{
+       struct ieee80211_sched_data *q = qdisc_priv(qd);
+       struct ieee80211_tx_packet_data *pkt_data =
+               (struct ieee80211_tx_packet_data *) skb->cb;
+       struct Qdisc *qdisc;
+       int err;
+
+       /* we recorded which queue to use earlier! */
+       qdisc = q->queues[pkt_data->queue];
+
+       if ((err = qdisc->ops->requeue(skb, qdisc)) == 0) {
+               qd->q.qlen++;
+               return 0;
+       }
+       qd->qstats.drops++;
+       return err;
+}
+
+
+static struct sk_buff *wme_qdiscop_dequeue(struct Qdisc* qd)
+{
+       struct ieee80211_sched_data *q = qdisc_priv(qd);
+       struct net_device *dev = qd->dev;
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_hw *hw = &local->hw;
+       struct sk_buff *skb;
+       struct Qdisc *qdisc;
+       int queue;
+
+       /* check all the h/w queues in numeric/priority order */
+       for (queue = 0; queue < hw->queues; queue++) {
+               /* see if there is room in this hardware queue */
+               if (test_bit(IEEE80211_LINK_STATE_XOFF,
+                            &local->state[queue]) ||
+                   test_bit(IEEE80211_LINK_STATE_PENDING,
+                            &local->state[queue]))
+                       continue;
+
+               /* there is space - try and get a frame */
+               skb = skb_dequeue(&q->requeued[queue]);
+               if (skb) {
+                       qd->q.qlen--;
+                       return skb;
+               }
+
+               qdisc = q->queues[queue];
+               skb = qdisc->dequeue(qdisc);
+               if (skb) {
+                       qd->q.qlen--;
+                       return skb;
+               }
+       }
+       /* returning a NULL here when all the h/w queues are full means we
+        * never need to call netif_stop_queue in the driver */
+       return NULL;
+}
+
+
+static void wme_qdiscop_reset(struct Qdisc* qd)
+{
+       struct ieee80211_sched_data *q = qdisc_priv(qd);
+       struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+       struct ieee80211_hw *hw = &local->hw;
+       int queue;
+
+       /* QUESTION: should we have some hardware flush functionality here? */
+
+       for (queue = 0; queue < hw->queues; queue++) {
+               skb_queue_purge(&q->requeued[queue]);
+               qdisc_reset(q->queues[queue]);
+       }
+       qd->q.qlen = 0;
+}
+
+
+static void wme_qdiscop_destroy(struct Qdisc* qd)
+{
+       struct ieee80211_sched_data *q = qdisc_priv(qd);
+       struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+       struct ieee80211_hw *hw = &local->hw;
+       int queue;
+
+       tcf_destroy_chain(q->filter_list);
+       q->filter_list = NULL;
+
+       for (queue=0; queue < hw->queues; queue++) {
+               skb_queue_purge(&q->requeued[queue]);
+               qdisc_destroy(q->queues[queue]);
+               q->queues[queue] = &noop_qdisc;
+       }
+}
+
+
+/* called whenever parameters are updated on existing qdisc */
+static int wme_qdiscop_tune(struct Qdisc *qd, struct rtattr *opt)
+{
+/*     struct ieee80211_sched_data *q = qdisc_priv(qd);
+*/
+       /* check our options block is the right size */
+       /* copy any options to our local structure */
+/*     Ignore options block for now - always use static mapping
+       struct tc_ieee80211_qopt *qopt = RTA_DATA(opt);
+
+       if (opt->rta_len < RTA_LENGTH(sizeof(*qopt)))
+               return -EINVAL;
+       memcpy(q->tag2queue, qopt->tag2queue, sizeof(qopt->tag2queue));
+*/
+       return 0;
+}
+
+
+/* called during initial creation of qdisc on device */
+static int wme_qdiscop_init(struct Qdisc *qd, struct rtattr *opt)
+{
+       struct ieee80211_sched_data *q = qdisc_priv(qd);
+       struct net_device *dev = qd->dev;
+       struct ieee80211_local *local;
+       int queues;
+       int err = 0, i;
+
+       /* check that device is a mac80211 device */
+       if (!dev->ieee80211_ptr ||
+           dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
+               return -EINVAL;
+
+       /* check this device is an ieee80211 master type device */
+       if (dev->type != ARPHRD_IEEE80211)
+               return -EINVAL;
+
+       /* check that there is no qdisc currently attached to device
+        * this ensures that we will be the root qdisc. (I can't find a better
+        * way to test this explicitly) */
+       if (dev->qdisc_sleeping != &noop_qdisc)
+               return -EINVAL;
+
+       if (qd->flags & TCQ_F_INGRESS)
+               return -EINVAL;
+
+       local = wdev_priv(dev->ieee80211_ptr);
+       queues = local->hw.queues;
+
+       /* if options were passed in, set them */
+       if (opt) {
+               err = wme_qdiscop_tune(qd, opt);
+       }
+
+       /* create child queues */
+       for (i = 0; i < queues; i++) {
+               skb_queue_head_init(&q->requeued[i]);
+               q->queues[i] = qdisc_create_dflt(qd->dev, &pfifo_qdisc_ops,
+                                                qd->handle);
+               if (q->queues[i] == 0) {
+                       q->queues[i] = &noop_qdisc;
+                       printk(KERN_ERR "%s child qdisc %i creation failed", dev->name, i);
+               }
+       }
+
+       return err;
+}
+
+static int wme_qdiscop_dump(struct Qdisc *qd, struct sk_buff *skb)
+{
+/*     struct ieee80211_sched_data *q = qdisc_priv(qd);
+       unsigned char *p = skb->tail;
+       struct tc_ieee80211_qopt opt;
+
+       memcpy(&opt.tag2queue, q->tag2queue, TC_80211_MAX_TAG + 1);
+       RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
+*/     return skb->len;
+/*
+rtattr_failure:
+       skb_trim(skb, p - skb->data);*/
+       return -1;
+}
+
+
+static int wme_classop_graft(struct Qdisc *qd, unsigned long arg,
+                            struct Qdisc *new, struct Qdisc **old)
+{
+       struct ieee80211_sched_data *q = qdisc_priv(qd);
+       struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+       struct ieee80211_hw *hw = &local->hw;
+       unsigned long queue = arg - 1;
+
+       if (queue >= hw->queues)
+               return -EINVAL;
+
+       if (!new)
+               new = &noop_qdisc;
+
+       sch_tree_lock(qd);
+       *old = q->queues[queue];
+       q->queues[queue] = new;
+       qdisc_reset(*old);
+       sch_tree_unlock(qd);
+
+       return 0;
+}
+
+
+static struct Qdisc *
+wme_classop_leaf(struct Qdisc *qd, unsigned long arg)
+{
+       struct ieee80211_sched_data *q = qdisc_priv(qd);
+       struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+       struct ieee80211_hw *hw = &local->hw;
+       unsigned long queue = arg - 1;
+
+       if (queue >= hw->queues)
+               return NULL;
+
+       return q->queues[queue];
+}
+
+
+static unsigned long wme_classop_get(struct Qdisc *qd, u32 classid)
+{
+       struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+       struct ieee80211_hw *hw = &local->hw;
+       unsigned long queue = TC_H_MIN(classid);
+
+       if (queue - 1 >= hw->queues)
+               return 0;
+
+       return queue;
+}
+
+
+static unsigned long wme_classop_bind(struct Qdisc *qd, unsigned long parent,
+                                     u32 classid)
+{
+       return wme_classop_get(qd, classid);
+}
+
+
+static void wme_classop_put(struct Qdisc *q, unsigned long cl)
+{
+}
+
+
+static int wme_classop_change(struct Qdisc *qd, u32 handle, u32 parent,
+                             struct rtattr **tca, unsigned long *arg)
+{
+       unsigned long cl = *arg;
+       struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+       struct ieee80211_hw *hw = &local->hw;
+
+       if (cl - 1 > hw->queues)
+               return -ENOENT;
+
+       /* TODO: put code to program hardware queue parameters here,
+        * to allow programming from tc command line */
+
+       return 0;
+}
+
+
+/* we don't support deleting hardware queues
+ * when we add WMM-SA support - TSPECs may be deleted here */
+static int wme_classop_delete(struct Qdisc *qd, unsigned long cl)
+{
+       struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+       struct ieee80211_hw *hw = &local->hw;
+
+       if (cl - 1 > hw->queues)
+               return -ENOENT;
+       return 0;
+}
+
+
+static int wme_classop_dump_class(struct Qdisc *qd, unsigned long cl,
+                                 struct sk_buff *skb, struct tcmsg *tcm)
+{
+       struct ieee80211_sched_data *q = qdisc_priv(qd);
+       struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+       struct ieee80211_hw *hw = &local->hw;
+
+       if (cl - 1 > hw->queues)
+               return -ENOENT;
+       tcm->tcm_handle = TC_H_MIN(cl);
+       tcm->tcm_parent = qd->handle;
+       tcm->tcm_info = q->queues[cl-1]->handle; /* do we need this? */
+       return 0;
+}
+
+
+static void wme_classop_walk(struct Qdisc *qd, struct qdisc_walker *arg)
+{
+       struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
+       struct ieee80211_hw *hw = &local->hw;
+       int queue;
+
+       if (arg->stop)
+               return;
+
+       for (queue = 0; queue < hw->queues; queue++) {
+               if (arg->count < arg->skip) {
+                       arg->count++;
+                       continue;
+               }
+               /* we should return classids for our internal queues here
+                * as well as the external ones */
+               if (arg->fn(qd, queue+1, arg) < 0) {
+                       arg->stop = 1;
+                       break;
+               }
+               arg->count++;
+       }
+}
+
+
+static struct tcf_proto ** wme_classop_find_tcf(struct Qdisc *qd,
+                                               unsigned long cl)
+{
+       struct ieee80211_sched_data *q = qdisc_priv(qd);
+
+       if (cl)
+               return NULL;
+
+       return &q->filter_list;
+}
+
+
+/* this qdisc is classful (i.e. has classes, some of which may have leaf qdiscs attached)
+ * - these are the operations on the classes */
+static struct Qdisc_class_ops class_ops =
+{
+       .graft = wme_classop_graft,
+       .leaf = wme_classop_leaf,
+
+       .get = wme_classop_get,
+       .put = wme_classop_put,
+       .change = wme_classop_change,
+       .delete = wme_classop_delete,
+       .walk = wme_classop_walk,
+
+       .tcf_chain = wme_classop_find_tcf,
+       .bind_tcf = wme_classop_bind,
+       .unbind_tcf = wme_classop_put,
+
+       .dump = wme_classop_dump_class,
+};
+
+
+/* queueing discipline operations */
+static struct Qdisc_ops wme_qdisc_ops =
+{
+       .next = NULL,
+       .cl_ops = &class_ops,
+       .id = "ieee80211",
+       .priv_size = sizeof(struct ieee80211_sched_data),
+
+       .enqueue = wme_qdiscop_enqueue,
+       .dequeue = wme_qdiscop_dequeue,
+       .requeue = wme_qdiscop_requeue,
+       .drop = NULL, /* drop not needed since we are always the root qdisc */
+
+       .init = wme_qdiscop_init,
+       .reset = wme_qdiscop_reset,
+       .destroy = wme_qdiscop_destroy,
+       .change = wme_qdiscop_tune,
+
+       .dump = wme_qdiscop_dump,
+};
+
+
+void ieee80211_install_qdisc(struct net_device *dev)
+{
+       struct Qdisc *qdisc;
+
+       qdisc = qdisc_create_dflt(dev, &wme_qdisc_ops, TC_H_ROOT);
+       if (!qdisc) {
+               printk(KERN_ERR "%s: qdisc installation failed\n", dev->name);
+               return;
+       }
+
+       /* same handle as would be allocated by qdisc_alloc_handle() */
+       qdisc->handle = 0x80010000;
+
+       qdisc_lock_tree(dev);
+       list_add_tail(&qdisc->list, &dev->qdisc_list);
+       dev->qdisc_sleeping = qdisc;
+       qdisc_unlock_tree(dev);
+}
+
+
+int ieee80211_qdisc_installed(struct net_device *dev)
+{
+       return dev->qdisc_sleeping->ops == &wme_qdisc_ops;
+}
+
+
+int ieee80211_wme_register(void)
+{
+       return register_qdisc(&wme_qdisc_ops);
+}
+
+
+void ieee80211_wme_unregister(void)
+{
+       unregister_qdisc(&wme_qdisc_ops);
+}
+#endif /* CONFIG_NET_SCHED */
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h
new file mode 100644 (file)
index 0000000..f0bff10
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * IEEE 802.11 driver (80211.o) - QoS datatypes
+ * Copyright 2004, Instant802 Networks, Inc.
+ * Copyright 2005, Devicescape Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _WME_H
+#define _WME_H
+
+#include <linux/netdevice.h>
+#include "ieee80211_i.h"
+
+#define QOS_CONTROL_LEN 2
+
+#define QOS_CONTROL_ACK_POLICY_NORMAL 0
+#define QOS_CONTROL_ACK_POLICY_NOACK 1
+
+#define QOS_CONTROL_TID_MASK 0x0f
+#define QOS_CONTROL_ACK_POLICY_SHIFT 5
+
+#define QOS_CONTROL_TAG1D_MASK 0x07
+
+ieee80211_txrx_result
+ieee80211_rx_h_parse_qos(struct ieee80211_txrx_data *rx);
+
+ieee80211_txrx_result
+ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx);
+
+#ifdef CONFIG_NET_SCHED
+void ieee80211_install_qdisc(struct net_device *dev);
+int ieee80211_qdisc_installed(struct net_device *dev);
+
+int ieee80211_wme_register(void);
+void ieee80211_wme_unregister(void);
+#else
+static inline void ieee80211_install_qdisc(struct net_device *dev)
+{
+}
+static inline int ieee80211_qdisc_installed(struct net_device *dev)
+{
+       return 0;
+}
+
+static inline int ieee80211_wme_register(void)
+{
+       return 0;
+}
+static inline void ieee80211_wme_unregister(void)
+{
+}
+#endif /* CONFIG_NET_SCHED */
+
+#endif /* _WME_H */
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
new file mode 100644 (file)
index 0000000..783af32
--- /dev/null
@@ -0,0 +1,660 @@
+/*
+ * Copyright 2002-2004, Instant802 Networks, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/compiler.h>
+#include <net/iw_handler.h>
+
+#include <net/mac80211.h>
+#include "ieee80211_common.h"
+#include "ieee80211_i.h"
+#include "michael.h"
+#include "tkip.h"
+#include "aes_ccm.h"
+#include "wpa.h"
+
+static int ieee80211_get_hdr_info(const struct sk_buff *skb, u8 **sa, u8 **da,
+                                 u8 *qos_tid, u8 **data, size_t *data_len)
+{
+       struct ieee80211_hdr *hdr;
+       size_t hdrlen;
+       u16 fc;
+       int a4_included;
+       u8 *pos;
+
+       hdr = (struct ieee80211_hdr *) skb->data;
+       fc = le16_to_cpu(hdr->frame_control);
+
+       hdrlen = 24;
+       if ((fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) ==
+           (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
+               hdrlen += ETH_ALEN;
+               *sa = hdr->addr4;
+               *da = hdr->addr3;
+       } else if (fc & IEEE80211_FCTL_FROMDS) {
+               *sa = hdr->addr3;
+               *da = hdr->addr1;
+       } else if (fc & IEEE80211_FCTL_TODS) {
+               *sa = hdr->addr2;
+               *da = hdr->addr3;
+       } else {
+               *sa = hdr->addr2;
+               *da = hdr->addr1;
+       }
+
+       if (fc & 0x80)
+               hdrlen += 2;
+
+       *data = skb->data + hdrlen;
+       *data_len = skb->len - hdrlen;
+
+       a4_included = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+               (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS);
+       if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
+           fc & IEEE80211_STYPE_QOS_DATA) {
+               pos = (u8 *) &hdr->addr4;
+               if (a4_included)
+                       pos += 6;
+               *qos_tid = pos[0] & 0x0f;
+               *qos_tid |= 0x80; /* qos_included flag */
+       } else
+               *qos_tid = 0;
+
+       return skb->len < hdrlen ? -1 : 0;
+}
+
+
+ieee80211_txrx_result
+ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx)
+{
+       u8 *data, *sa, *da, *key, *mic, qos_tid;
+       size_t data_len;
+       u16 fc;
+       struct sk_buff *skb = tx->skb;
+       int authenticator;
+       int wpa_test = 0;
+
+       fc = tx->fc;
+
+       if (!tx->key || tx->key->alg != ALG_TKIP || skb->len < 24 ||
+           !WLAN_FC_DATA_PRESENT(fc))
+               return TXRX_CONTINUE;
+
+       if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len))
+               return TXRX_DROP;
+
+       if (!tx->key->force_sw_encrypt &&
+           !tx->fragmented &&
+           !(tx->local->hw.flags & IEEE80211_HW_TKIP_INCLUDE_MMIC) &&
+           !wpa_test) {
+               /* hwaccel - with no need for preallocated room for Michael MIC
+                */
+               return TXRX_CONTINUE;
+       }
+
+       if (skb_tailroom(skb) < MICHAEL_MIC_LEN) {
+               I802_DEBUG_INC(tx->local->tx_expand_skb_head);
+               if (unlikely(pskb_expand_head(skb, TKIP_IV_LEN,
+                                             MICHAEL_MIC_LEN + TKIP_ICV_LEN,
+                                             GFP_ATOMIC))) {
+                       printk(KERN_DEBUG "%s: failed to allocate more memory "
+                              "for Michael MIC\n", tx->dev->name);
+                       return TXRX_DROP;
+               }
+       }
+
+#if 0
+       authenticator = fc & IEEE80211_FCTL_FROMDS; /* FIX */
+#else
+       authenticator = 1;
+#endif
+       key = &tx->key->key[authenticator ? ALG_TKIP_TEMP_AUTH_TX_MIC_KEY :
+                           ALG_TKIP_TEMP_AUTH_RX_MIC_KEY];
+       mic = skb_put(skb, MICHAEL_MIC_LEN);
+       michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic);
+
+       return TXRX_CONTINUE;
+}
+
+
+ieee80211_txrx_result
+ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx)
+{
+       u8 *data, *sa, *da, *key = NULL, qos_tid;
+       size_t data_len;
+       u16 fc;
+       u8 mic[MICHAEL_MIC_LEN];
+       struct sk_buff *skb = rx->skb;
+       int authenticator = 1, wpa_test = 0;
+
+       fc = rx->fc;
+
+       /* If device handles decryption totally, skip this check */
+       if ((rx->local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP) ||
+           (rx->local->hw.flags & IEEE80211_HW_DEVICE_STRIPS_MIC))
+               return TXRX_CONTINUE;
+
+       if (!rx->key || rx->key->alg != ALG_TKIP ||
+           !(rx->fc & IEEE80211_FCTL_PROTECTED) || !WLAN_FC_DATA_PRESENT(fc))
+               return TXRX_CONTINUE;
+
+       if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
+           !rx->key->force_sw_encrypt) {
+               if (rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) {
+                       if (skb->len < MICHAEL_MIC_LEN)
+                               return TXRX_DROP;
+               }
+               /* Need to verify Michael MIC sometimes in software even when
+                * hwaccel is used. Atheros ar5212: fragmented frames and QoS
+                * frames. */
+               if (!rx->fragmented && !wpa_test)
+                       goto remove_mic;
+       }
+
+       if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len)
+           || data_len < MICHAEL_MIC_LEN)
+               return TXRX_DROP;
+
+       data_len -= MICHAEL_MIC_LEN;
+
+#if 0
+       authenticator = fc & IEEE80211_FCTL_TODS; /* FIX */
+#else
+       authenticator = 1;
+#endif
+       key = &rx->key->key[authenticator ? ALG_TKIP_TEMP_AUTH_RX_MIC_KEY :
+                           ALG_TKIP_TEMP_AUTH_TX_MIC_KEY];
+       michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic);
+       if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) {
+               if (!rx->u.rx.ra_match)
+                       return TXRX_DROP;
+
+               printk(KERN_DEBUG "%s: invalid Michael MIC in data frame from "
+                      MAC_FMT "\n", rx->dev->name, MAC_ARG(sa));
+
+               do {
+                       struct ieee80211_hdr *hdr;
+                       union iwreq_data wrqu;
+                       char *buf = kmalloc(128, GFP_ATOMIC);
+                       if (!buf)
+                               break;
+
+                       /* TODO: needed parameters: count, key type, TSC */
+                       hdr = (struct ieee80211_hdr *) skb->data;
+                       sprintf(buf, "MLME-MICHAELMICFAILURE.indication("
+                               "keyid=%d %scast addr=" MAC_FMT ")",
+                               rx->key->keyidx,
+                               hdr->addr1[0] & 0x01 ? "broad" : "uni",
+                               MAC_ARG(hdr->addr2));
+                       memset(&wrqu, 0, sizeof(wrqu));
+                       wrqu.data.length = strlen(buf);
+                       wireless_send_event(rx->dev, IWEVCUSTOM, &wrqu, buf);
+                       kfree(buf);
+               } while (0);
+
+               if (!rx->local->apdev)
+                       return TXRX_DROP;
+
+               ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status,
+                                 ieee80211_msg_michael_mic_failure);
+
+               return TXRX_QUEUED;
+       }
+
+ remove_mic:
+       /* remove Michael MIC from payload */
+       skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
+
+       return TXRX_CONTINUE;
+}
+
+
+static int tkip_encrypt_skb(struct ieee80211_txrx_data *tx,
+                           struct sk_buff *skb, int test)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       struct ieee80211_key *key = tx->key;
+       int hdrlen, len, tailneed;
+       u16 fc;
+       u8 *pos;
+
+       fc = le16_to_cpu(hdr->frame_control);
+       hdrlen = ieee80211_get_hdrlen(fc);
+       len = skb->len - hdrlen;
+
+       tailneed = !tx->key->force_sw_encrypt ? 0 : TKIP_ICV_LEN;
+       if ((skb_headroom(skb) < TKIP_IV_LEN ||
+            skb_tailroom(skb) < tailneed)) {
+               I802_DEBUG_INC(tx->local->tx_expand_skb_head);
+               if (unlikely(pskb_expand_head(skb, TKIP_IV_LEN, tailneed,
+                                             GFP_ATOMIC)))
+                       return -1;
+       }
+
+       pos = skb_push(skb, TKIP_IV_LEN);
+       memmove(pos, pos + TKIP_IV_LEN, hdrlen);
+       pos += hdrlen;
+
+       /* Increase IV for the frame */
+       key->u.tkip.iv16++;
+       if (key->u.tkip.iv16 == 0)
+               key->u.tkip.iv32++;
+
+       if (!tx->key->force_sw_encrypt) {
+               u32 flags = tx->local->hw.flags;
+               hdr = (struct ieee80211_hdr *)skb->data;
+
+               /* hwaccel - with preallocated room for IV */
+               ieee80211_tkip_add_iv(pos, key,
+                                     (u8) (key->u.tkip.iv16 >> 8),
+                                     (u8) (((key->u.tkip.iv16 >> 8) | 0x20) &
+                                           0x7f),
+                                     (u8) key->u.tkip.iv16);
+
+               if (flags & IEEE80211_HW_TKIP_REQ_PHASE2_KEY)
+                       ieee80211_tkip_gen_rc4key(key, hdr->addr2,
+                                                 tx->u.tx.control->tkip_key);
+               else if (flags & IEEE80211_HW_TKIP_REQ_PHASE1_KEY) {
+                       if (key->u.tkip.iv16 == 0 ||
+                           !key->u.tkip.tx_initialized) {
+                               ieee80211_tkip_gen_phase1key(key, hdr->addr2,
+                                           (u16 *)tx->u.tx.control->tkip_key);
+                               key->u.tkip.tx_initialized = 1;
+                               tx->u.tx.control->flags |=
+                                           IEEE80211_TXCTL_TKIP_NEW_PHASE1_KEY;
+                       } else
+                               tx->u.tx.control->flags &=
+                                           ~IEEE80211_TXCTL_TKIP_NEW_PHASE1_KEY;
+               }
+
+               tx->u.tx.control->key_idx = tx->key->hw_key_idx;
+               return 0;
+       }
+
+       /* Add room for ICV */
+       skb_put(skb, TKIP_ICV_LEN);
+
+       hdr = (struct ieee80211_hdr *) skb->data;
+       ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm,
+                                   key, pos, len, hdr->addr2);
+       return 0;
+}
+
+
+ieee80211_txrx_result
+ieee80211_tx_h_tkip_encrypt(struct ieee80211_txrx_data *tx)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
+       u16 fc;
+       struct ieee80211_key *key = tx->key;
+       struct sk_buff *skb = tx->skb;
+       int wpa_test = 0, test = 0;
+
+       fc = le16_to_cpu(hdr->frame_control);
+
+       if (!key || key->alg != ALG_TKIP || !WLAN_FC_DATA_PRESENT(fc))
+               return TXRX_CONTINUE;
+
+       tx->u.tx.control->icv_len = TKIP_ICV_LEN;
+       tx->u.tx.control->iv_len = TKIP_IV_LEN;
+       ieee80211_tx_set_iswep(tx);
+
+       if (!tx->key->force_sw_encrypt &&
+           !(tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) &&
+           !wpa_test) {
+               /* hwaccel - with no need for preallocated room for IV/ICV */
+               tx->u.tx.control->key_idx = tx->key->hw_key_idx;
+               return TXRX_CONTINUE;
+       }
+
+       if (tkip_encrypt_skb(tx, skb, test) < 0)
+               return TXRX_DROP;
+
+       if (tx->u.tx.extra_frag) {
+               int i;
+               for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+                       if (tkip_encrypt_skb(tx, tx->u.tx.extra_frag[i], test)
+                           < 0)
+                               return TXRX_DROP;
+               }
+       }
+
+       return TXRX_CONTINUE;
+}
+
+
+ieee80211_txrx_result
+ieee80211_rx_h_tkip_decrypt(struct ieee80211_txrx_data *rx)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+       u16 fc;
+       int hdrlen, res, hwaccel = 0, wpa_test = 0;
+       struct ieee80211_key *key = rx->key;
+       struct sk_buff *skb = rx->skb;
+
+       fc = le16_to_cpu(hdr->frame_control);
+       hdrlen = ieee80211_get_hdrlen(fc);
+
+       if (!rx->key || rx->key->alg != ALG_TKIP ||
+           !(rx->fc & IEEE80211_FCTL_PROTECTED) ||
+           (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)
+               return TXRX_CONTINUE;
+
+       if (!rx->sta || skb->len - hdrlen < 12)
+               return TXRX_DROP;
+
+       if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
+           !rx->key->force_sw_encrypt) {
+               if (!(rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV)) {
+                       /* Hardware takes care of all processing, including
+                        * replay protection, so no need to continue here. */
+                       return TXRX_CONTINUE;
+               }
+
+               /* let TKIP code verify IV, but skip decryption */
+               hwaccel = 1;
+       }
+
+       res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
+                                         key, skb->data + hdrlen,
+                                         skb->len - hdrlen, rx->sta->addr,
+                                         hwaccel, rx->u.rx.queue);
+       if (res != TKIP_DECRYPT_OK || wpa_test) {
+               printk(KERN_DEBUG "%s: TKIP decrypt failed for RX frame from "
+                      MAC_FMT " (res=%d)\n",
+                      rx->dev->name, MAC_ARG(rx->sta->addr), res);
+               return TXRX_DROP;
+       }
+
+       /* Trim ICV */
+       skb_trim(skb, skb->len - TKIP_ICV_LEN);
+
+       /* Remove IV */
+       memmove(skb->data + TKIP_IV_LEN, skb->data, hdrlen);
+       skb_pull(skb, TKIP_IV_LEN);
+
+       return TXRX_CONTINUE;
+}
+
+
+static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad,
+                               int encrypted)
+{
+       u16 fc;
+       int a4_included, qos_included;
+       u8 qos_tid, *fc_pos, *data, *sa, *da;
+       int len_a;
+       size_t data_len;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+
+       fc_pos = (u8 *) &hdr->frame_control;
+       fc = fc_pos[0] ^ (fc_pos[1] << 8);
+       a4_included = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+               (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS);
+
+       ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len);
+       data_len -= CCMP_HDR_LEN + (encrypted ? CCMP_MIC_LEN : 0);
+       if (qos_tid & 0x80) {
+               qos_included = 1;
+               qos_tid &= 0x0f;
+       } else
+               qos_included = 0;
+       /* First block, b_0 */
+
+       b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
+       /* Nonce: QoS Priority | A2 | PN */
+       b_0[1] = qos_tid;
+       memcpy(&b_0[2], hdr->addr2, 6);
+       memcpy(&b_0[8], pn, CCMP_PN_LEN);
+       /* l(m) */
+       b_0[14] = (data_len >> 8) & 0xff;
+       b_0[15] = data_len & 0xff;
+
+
+       /* AAD (extra authenticate-only data) / masked 802.11 header
+        * FC | A1 | A2 | A3 | SC | [A4] | [QC] */
+
+       len_a = a4_included ? 28 : 22;
+       if (qos_included)
+               len_a += 2;
+
+       aad[0] = 0; /* (len_a >> 8) & 0xff; */
+       aad[1] = len_a & 0xff;
+       /* Mask FC: zero subtype b4 b5 b6 */
+       aad[2] = fc_pos[0] & ~(BIT(4) | BIT(5) | BIT(6));
+       /* Retry, PwrMgt, MoreData; set Protected */
+       aad[3] = (fc_pos[1] & ~(BIT(3) | BIT(4) | BIT(5))) | BIT(6);
+       memcpy(&aad[4], &hdr->addr1, 18);
+
+       /* Mask Seq#, leave Frag# */
+       aad[22] = *((u8 *) &hdr->seq_ctrl) & 0x0f;
+       aad[23] = 0;
+       if (a4_included) {
+               memcpy(&aad[24], hdr->addr4, 6);
+               aad[30] = 0;
+               aad[31] = 0;
+       } else
+               memset(&aad[24], 0, 8);
+       if (qos_included) {
+               u8 *dpos = &aad[a4_included ? 30 : 24];
+
+               /* Mask QoS Control field */
+               dpos[0] = qos_tid;
+               dpos[1] = 0;
+       }
+}
+
+
+static inline void ccmp_pn2hdr(u8 *hdr, u8 *pn, int key_id)
+{
+       hdr[0] = pn[5];
+       hdr[1] = pn[4];
+       hdr[2] = 0;
+       hdr[3] = 0x20 | (key_id << 6);
+       hdr[4] = pn[3];
+       hdr[5] = pn[2];
+       hdr[6] = pn[1];
+       hdr[7] = pn[0];
+}
+
+
+static inline int ccmp_hdr2pn(u8 *pn, u8 *hdr)
+{
+       pn[0] = hdr[7];
+       pn[1] = hdr[6];
+       pn[2] = hdr[5];
+       pn[3] = hdr[4];
+       pn[4] = hdr[1];
+       pn[5] = hdr[0];
+       return (hdr[3] >> 6) & 0x03;
+}
+
+
+static int ccmp_encrypt_skb(struct ieee80211_txrx_data *tx,
+                           struct sk_buff *skb, int test)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       struct ieee80211_key *key = tx->key;
+       int hdrlen, len, tailneed;
+       u16 fc;
+       u8 *pos, *pn, *b_0, *aad, *scratch;
+       int i;
+
+       scratch = key->u.ccmp.tx_crypto_buf;
+       b_0 = scratch + 3 * AES_BLOCK_LEN;
+       aad = scratch + 4 * AES_BLOCK_LEN;
+
+       fc = le16_to_cpu(hdr->frame_control);
+       hdrlen = ieee80211_get_hdrlen(fc);
+       len = skb->len - hdrlen;
+
+       tailneed = !key->force_sw_encrypt ? 0 : CCMP_MIC_LEN;
+
+       if ((skb_headroom(skb) < CCMP_HDR_LEN ||
+            skb_tailroom(skb) < tailneed)) {
+               I802_DEBUG_INC(tx->local->tx_expand_skb_head);
+               if (unlikely(pskb_expand_head(skb, CCMP_HDR_LEN, tailneed,
+                                             GFP_ATOMIC)))
+                       return -1;
+       }
+
+       pos = skb_push(skb, CCMP_HDR_LEN);
+       memmove(pos, pos + CCMP_HDR_LEN, hdrlen);
+       hdr = (struct ieee80211_hdr *) pos;
+       pos += hdrlen;
+
+       /* PN = PN + 1 */
+       pn = key->u.ccmp.tx_pn;
+
+       for (i = CCMP_PN_LEN - 1; i >= 0; i--) {
+               pn[i]++;
+               if (pn[i])
+                       break;
+       }
+
+       ccmp_pn2hdr(pos, pn, key->keyidx);
+
+       if (!key->force_sw_encrypt) {
+               /* hwaccel - with preallocated room for CCMP header */
+               tx->u.tx.control->key_idx = key->hw_key_idx;
+               return 0;
+       }
+
+       pos += CCMP_HDR_LEN;
+       ccmp_special_blocks(skb, pn, b_0, aad, 0);
+       ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, b_0, aad, pos, len,
+                                 pos, skb_put(skb, CCMP_MIC_LEN));
+
+       return 0;
+}
+
+
+ieee80211_txrx_result
+ieee80211_tx_h_ccmp_encrypt(struct ieee80211_txrx_data *tx)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
+       struct ieee80211_key *key = tx->key;
+       u16 fc;
+       struct sk_buff *skb = tx->skb;
+       int test = 0;
+
+       fc = le16_to_cpu(hdr->frame_control);
+
+       if (!key || key->alg != ALG_CCMP || !WLAN_FC_DATA_PRESENT(fc))
+               return TXRX_CONTINUE;
+
+       tx->u.tx.control->icv_len = CCMP_MIC_LEN;
+       tx->u.tx.control->iv_len = CCMP_HDR_LEN;
+       ieee80211_tx_set_iswep(tx);
+
+       if (!tx->key->force_sw_encrypt &&
+           !(tx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV)) {
+               /* hwaccel - with no need for preallocated room for CCMP "
+                * header or MIC fields */
+               tx->u.tx.control->key_idx = tx->key->hw_key_idx;
+               return TXRX_CONTINUE;
+       }
+
+       if (ccmp_encrypt_skb(tx, skb, test) < 0)
+               return TXRX_DROP;
+
+       if (tx->u.tx.extra_frag) {
+               int i;
+
+               for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+                       if (ccmp_encrypt_skb(tx, tx->u.tx.extra_frag[i], test)
+                           < 0)
+                               return TXRX_DROP;
+               }
+       }
+
+       return TXRX_CONTINUE;
+}
+
+
+ieee80211_txrx_result
+ieee80211_rx_h_ccmp_decrypt(struct ieee80211_txrx_data *rx)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
+       u16 fc;
+       int hdrlen;
+       struct ieee80211_key *key = rx->key;
+       struct sk_buff *skb = rx->skb;
+       u8 pn[CCMP_PN_LEN];
+       int data_len;
+
+       fc = le16_to_cpu(hdr->frame_control);
+       hdrlen = ieee80211_get_hdrlen(fc);
+
+       if (!key || key->alg != ALG_CCMP ||
+           !(rx->fc & IEEE80211_FCTL_PROTECTED) ||
+           (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)
+               return TXRX_CONTINUE;
+
+       data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN;
+       if (!rx->sta || data_len < 0)
+               return TXRX_DROP;
+
+       if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
+           !key->force_sw_encrypt &&
+           !(rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV))
+               return TXRX_CONTINUE;
+
+       (void) ccmp_hdr2pn(pn, skb->data + hdrlen);
+
+       if (memcmp(pn, key->u.ccmp.rx_pn[rx->u.rx.queue], CCMP_PN_LEN) <= 0) {
+#ifdef CONFIG_MAC80211_DEBUG
+               u8 *ppn = key->u.ccmp.rx_pn[rx->u.rx.queue];
+               printk(KERN_DEBUG "%s: CCMP replay detected for RX frame from "
+                      MAC_FMT " (RX PN %02x%02x%02x%02x%02x%02x <= prev. PN "
+                      "%02x%02x%02x%02x%02x%02x)\n", rx->dev->name,
+                      MAC_ARG(rx->sta->addr),
+                      pn[0], pn[1], pn[2], pn[3], pn[4], pn[5],
+                      ppn[0], ppn[1], ppn[2], ppn[3], ppn[4], ppn[5]);
+#endif /* CONFIG_MAC80211_DEBUG */
+               key->u.ccmp.replays++;
+               return TXRX_DROP;
+       }
+
+       if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
+           !key->force_sw_encrypt) {
+               /* hwaccel has already decrypted frame and verified MIC */
+       } else {
+               u8 *scratch, *b_0, *aad;
+
+               scratch = key->u.ccmp.rx_crypto_buf;
+               b_0 = scratch + 3 * AES_BLOCK_LEN;
+               aad = scratch + 4 * AES_BLOCK_LEN;
+
+               ccmp_special_blocks(skb, pn, b_0, aad, 1);
+
+               if (ieee80211_aes_ccm_decrypt(
+                           key->u.ccmp.tfm, scratch, b_0, aad,
+                           skb->data + hdrlen + CCMP_HDR_LEN, data_len,
+                           skb->data + skb->len - CCMP_MIC_LEN,
+                           skb->data + hdrlen + CCMP_HDR_LEN)) {
+                       printk(KERN_DEBUG "%s: CCMP decrypt failed for RX "
+                              "frame from " MAC_FMT "\n", rx->dev->name,
+                              MAC_ARG(rx->sta->addr));
+                       return TXRX_DROP;
+               }
+       }
+
+       memcpy(key->u.ccmp.rx_pn[rx->u.rx.queue], pn, CCMP_PN_LEN);
+
+       /* Remove CCMP header and MIC */
+       skb_trim(skb, skb->len - CCMP_MIC_LEN);
+       memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen);
+       skb_pull(skb, CCMP_HDR_LEN);
+
+       return TXRX_CONTINUE;
+}
+
diff --git a/net/mac80211/wpa.h b/net/mac80211/wpa.h
new file mode 100644 (file)
index 0000000..da3b959
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2002-2004, Instant802 Networks, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef WPA_H
+#define WPA_H
+
+#include <linux/skbuff.h>
+#include <linux/types.h>
+#include "ieee80211_i.h"
+
+ieee80211_txrx_result
+ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx);
+ieee80211_txrx_result
+ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx);
+
+ieee80211_txrx_result
+ieee80211_tx_h_tkip_encrypt(struct ieee80211_txrx_data *tx);
+ieee80211_txrx_result
+ieee80211_rx_h_tkip_decrypt(struct ieee80211_txrx_data *rx);
+
+ieee80211_txrx_result
+ieee80211_tx_h_ccmp_encrypt(struct ieee80211_txrx_data *tx);
+ieee80211_txrx_result
+ieee80211_rx_h_ccmp_decrypt(struct ieee80211_txrx_data *rx);
+
+#endif /* WPA_H */
index 42d2fb9..507828d 100644 (file)
@@ -140,6 +140,14 @@ static struct hlist_head *nl_pid_hashfn(struct nl_pid_hash *hash, u32 pid)
 
 static void netlink_sock_destruct(struct sock *sk)
 {
+       struct netlink_sock *nlk = nlk_sk(sk);
+
+       if (nlk->cb) {
+               if (nlk->cb->done)
+                       nlk->cb->done(nlk->cb);
+               netlink_destroy_callback(nlk->cb);
+       }
+
        skb_queue_purge(&sk->sk_receive_queue);
 
        if (!sock_flag(sk, SOCK_DEAD)) {
@@ -148,7 +156,6 @@ static void netlink_sock_destruct(struct sock *sk)
        }
        BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc));
        BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc));
-       BUG_TRAP(!nlk_sk(sk)->cb);
        BUG_TRAP(!nlk_sk(sk)->groups);
 }
 
@@ -456,17 +463,10 @@ static int netlink_release(struct socket *sock)
        sock_orphan(sk);
        nlk = nlk_sk(sk);
 
-       mutex_lock(nlk->cb_mutex);
-       if (nlk->cb) {
-               if (nlk->cb->done)
-                       nlk->cb->done(nlk->cb);
-               netlink_destroy_callback(nlk->cb);
-               nlk->cb = NULL;
-       }
-       mutex_unlock(nlk->cb_mutex);
-
-       /* OK. Socket is unlinked, and, therefore,
-          no new packets will arrive */
+       /*
+        * OK. Socket is unlinked, any packets that arrive now
+        * will be purged.
+        */
 
        sock->sk = NULL;
        wake_up_interruptible_all(&nlk->wait);
@@ -1245,16 +1245,14 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
                siocb->scm = &scm;
        }
        siocb->scm->creds = *NETLINK_CREDS(skb);
+       if (flags & MSG_TRUNC)
+               copied = skb->len;
        skb_free_datagram(sk, skb);
 
        if (nlk->cb && atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2)
                netlink_dump(sk);
 
        scm_recv(sock, msg, siocb->scm, flags);
-
-       if (flags & MSG_TRUNC)
-               copied = skb->len;
-
 out:
        netlink_rcv_wake(sk);
        return err ? : copied;
@@ -1426,9 +1424,9 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
                return -ECONNREFUSED;
        }
        nlk = nlk_sk(sk);
-       /* A dump or destruction is in progress... */
+       /* A dump is in progress... */
        mutex_lock(nlk->cb_mutex);
-       if (nlk->cb || sock_flag(sk, SOCK_DEAD)) {
+       if (nlk->cb) {
                mutex_unlock(nlk->cb_mutex);
                netlink_destroy_callback(cb);
                sock_put(sk);
index 8e6bd4e..2f76e06 100644 (file)
@@ -598,7 +598,7 @@ struct net_device *nr_dev_first(void)
        struct net_device *dev, *first = NULL;
 
        read_lock(&dev_base_lock);
-       for (dev = dev_base; dev != NULL; dev = dev->next) {
+       for_each_netdev(dev) {
                if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM)
                        if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
                                first = dev;
@@ -618,12 +618,13 @@ struct net_device *nr_dev_get(ax25_address *addr)
        struct net_device *dev;
 
        read_lock(&dev_base_lock);
-       for (dev = dev_base; dev != NULL; dev = dev->next) {
+       for_each_netdev(dev) {
                if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM && ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) {
                        dev_hold(dev);
                        goto out;
                }
        }
+       dev = NULL;
 out:
        read_unlock(&dev_base_lock);
        return dev;
index 1f9aefd..929a784 100644 (file)
@@ -596,7 +596,7 @@ struct net_device *rose_dev_first(void)
        struct net_device *dev, *first = NULL;
 
        read_lock(&dev_base_lock);
-       for (dev = dev_base; dev != NULL; dev = dev->next) {
+       for_each_netdev(dev) {
                if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE)
                        if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
                                first = dev;
@@ -614,12 +614,13 @@ struct net_device *rose_dev_get(rose_address *addr)
        struct net_device *dev;
 
        read_lock(&dev_base_lock);
-       for (dev = dev_base; dev != NULL; dev = dev->next) {
+       for_each_netdev(dev) {
                if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0) {
                        dev_hold(dev);
                        goto out;
                }
        }
+       dev = NULL;
 out:
        read_unlock(&dev_base_lock);
        return dev;
@@ -630,10 +631,11 @@ static int rose_dev_exists(rose_address *addr)
        struct net_device *dev;
 
        read_lock(&dev_base_lock);
-       for (dev = dev_base; dev != NULL; dev = dev->next) {
+       for_each_netdev(dev) {
                if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0)
                        goto out;
        }
+       dev = NULL;
 out:
        read_unlock(&dev_base_lock);
        return dev != NULL;
index 8750f6d..91b3d52 100644 (file)
@@ -5,6 +5,7 @@
 config AF_RXRPC
        tristate "RxRPC session sockets"
        depends on EXPERIMENTAL
+       select KEYS
        help
          Say Y or M here to include support for RxRPC session sockets (just
          the transport part, not the presentation part: (un)marshalling is
@@ -29,7 +30,7 @@ config AF_RXRPC_DEBUG
 
 config RXKAD
        tristate "RxRPC Kerberos security"
-       depends on AF_RXRPC && KEYS
+       depends on AF_RXRPC
        select CRYPTO
        select CRYPTO_MANAGER
        select CRYPTO_BLKCIPHER
index fc07a92..657ee69 100644 (file)
@@ -543,6 +543,38 @@ static void rxrpc_zap_tx_window(struct rxrpc_call *call)
 }
 
 /*
+ * process the extra information that may be appended to an ACK packet
+ */
+static void rxrpc_extract_ackinfo(struct rxrpc_call *call, struct sk_buff *skb,
+                                 unsigned latest, int nAcks)
+{
+       struct rxrpc_ackinfo ackinfo;
+       struct rxrpc_peer *peer;
+       unsigned mtu;
+
+       if (skb_copy_bits(skb, nAcks + 3, &ackinfo, sizeof(ackinfo)) < 0) {
+               _leave(" [no ackinfo]");
+               return;
+       }
+
+       _proto("Rx ACK %%%u Info { rx=%u max=%u rwin=%u jm=%u }",
+              latest,
+              ntohl(ackinfo.rxMTU), ntohl(ackinfo.maxMTU),
+              ntohl(ackinfo.rwind), ntohl(ackinfo.jumbo_max));
+
+       mtu = min(ntohl(ackinfo.rxMTU), ntohl(ackinfo.maxMTU));
+
+       peer = call->conn->trans->peer;
+       if (mtu < peer->maxdata) {
+               spin_lock_bh(&peer->lock);
+               peer->maxdata = mtu;
+               peer->mtu = mtu + peer->hdrsize;
+               spin_unlock_bh(&peer->lock);
+               _net("Net MTU %u (maxdata %u)", peer->mtu, peer->maxdata);
+       }
+}
+
+/*
  * process packets in the reception queue
  */
 static int rxrpc_process_rx_queue(struct rxrpc_call *call,
@@ -606,6 +638,8 @@ process_further:
                       rxrpc_acks[ack.reason],
                       ack.nAcks);
 
+               rxrpc_extract_ackinfo(call, skb, latest, ack.nAcks);
+
                if (ack.reason == RXRPC_ACK_PING) {
                        _proto("Rx ACK %%%u PING Request", latest);
                        rxrpc_propose_ACK(call, RXRPC_ACK_PING_RESPONSE,
@@ -801,9 +835,9 @@ void rxrpc_process_call(struct work_struct *work)
        struct msghdr msg;
        struct kvec iov[5];
        unsigned long bits;
-       __be32 data;
+       __be32 data, pad;
        size_t len;
-       int genbit, loop, nbit, ioc, ret;
+       int genbit, loop, nbit, ioc, ret, mtu;
        u32 abort_code = RX_PROTOCOL_ERROR;
        u8 *acks = NULL;
 
@@ -899,9 +933,30 @@ void rxrpc_process_call(struct work_struct *work)
        }
 
        if (test_bit(RXRPC_CALL_ACK_FINAL, &call->events)) {
-               hdr.type = RXRPC_PACKET_TYPE_ACKALL;
                genbit = RXRPC_CALL_ACK_FINAL;
-               goto send_message;
+
+               ack.bufferSpace = htons(8);
+               ack.maxSkew     = 0;
+               ack.serial      = 0;
+               ack.reason      = RXRPC_ACK_IDLE;
+               ack.nAcks       = 0;
+               call->ackr_reason = 0;
+
+               spin_lock_bh(&call->lock);
+               ack.serial = call->ackr_serial;
+               ack.previousPacket = call->ackr_prev_seq;
+               ack.firstPacket = htonl(call->rx_data_eaten + 1);
+               spin_unlock_bh(&call->lock);
+
+               pad = 0;
+
+               iov[1].iov_base = &ack;
+               iov[1].iov_len  = sizeof(ack);
+               iov[2].iov_base = &pad;
+               iov[2].iov_len  = 3;
+               iov[3].iov_base = &ackinfo;
+               iov[3].iov_len  = sizeof(ackinfo);
+               goto send_ACK;
        }
 
        if (call->events & ((1 << RXRPC_CALL_RCVD_BUSY) |
@@ -971,8 +1026,6 @@ void rxrpc_process_call(struct work_struct *work)
 
        /* consider sending an ordinary ACK */
        if (test_bit(RXRPC_CALL_ACK, &call->events)) {
-               __be32 pad;
-
                _debug("send ACK: window: %d - %d { %lx }",
                       call->rx_data_eaten, call->ackr_win_top,
                       call->ackr_window[0]);
@@ -997,12 +1050,6 @@ void rxrpc_process_call(struct work_struct *work)
                ack.serial      = 0;
                ack.reason      = 0;
 
-               ackinfo.rxMTU   = htonl(5692);
-//             ackinfo.rxMTU   = htonl(call->conn->trans->peer->maxdata);
-               ackinfo.maxMTU  = htonl(call->conn->trans->peer->maxdata);
-               ackinfo.rwind   = htonl(32);
-               ackinfo.jumbo_max = htonl(4);
-
                spin_lock_bh(&call->lock);
                ack.reason = call->ackr_reason;
                ack.serial = call->ackr_serial;
@@ -1116,6 +1163,15 @@ send_ACK_with_skew:
        ack.maxSkew = htons(atomic_read(&call->conn->hi_serial) -
                            ntohl(ack.serial));
 send_ACK:
+       mtu = call->conn->trans->peer->if_mtu;
+       mtu -= call->conn->trans->peer->hdrsize;
+       ackinfo.maxMTU  = htonl(mtu);
+       ackinfo.rwind   = htonl(32);
+
+       /* permit the peer to send us jumbo packets if it wants to */
+       ackinfo.rxMTU   = htonl(5692);
+       ackinfo.jumbo_max = htonl(4);
+
        hdr.serial = htonl(atomic_inc_return(&call->conn->serial));
        _proto("Tx ACK %%%u { m=%hu f=#%u p=#%u s=%%%u r=%s n=%u }",
               ntohl(hdr.serial),
index 2c27df1..6cb3e88 100644 (file)
@@ -100,8 +100,10 @@ void rxrpc_UDP_error_report(struct sock *sk)
                }
 
                if (mtu < peer->mtu) {
+                       spin_lock_bh(&peer->lock);
                        peer->mtu = mtu;
                        peer->maxdata = peer->mtu - peer->hdrsize;
+                       spin_unlock_bh(&peer->lock);
                        _net("Net MTU %u (maxdata %u)",
                             peer->mtu, peer->maxdata);
                }
index 5cdde4a..591c442 100644 (file)
@@ -582,7 +582,7 @@ static int rxrpc_send_data(struct kiocb *iocb,
                        max &= ~(call->conn->size_align - 1UL);
 
                        chunk = max;
-                       if (chunk > len)
+                       if (chunk > len && !more)
                                chunk = len;
 
                        space = chunk + call->conn->size_align;
index d399de4..ce08b78 100644 (file)
@@ -19,6 +19,7 @@
 #include <net/sock.h>
 #include <net/af_rxrpc.h>
 #include <net/ip.h>
+#include <net/route.h>
 #include "ar-internal.h"
 
 static LIST_HEAD(rxrpc_peers);
@@ -28,6 +29,47 @@ static DECLARE_WAIT_QUEUE_HEAD(rxrpc_peer_wq);
 static void rxrpc_destroy_peer(struct work_struct *work);
 
 /*
+ * assess the MTU size for the network interface through which this peer is
+ * reached
+ */
+static void rxrpc_assess_MTU_size(struct rxrpc_peer *peer)
+{
+       struct rtable *rt;
+       struct flowi fl;
+       int ret;
+
+       peer->if_mtu = 1500;
+
+       memset(&fl, 0, sizeof(fl));
+
+       switch (peer->srx.transport.family) {
+       case AF_INET:
+               fl.oif = 0;
+               fl.proto = IPPROTO_UDP,
+               fl.nl_u.ip4_u.saddr = 0;
+               fl.nl_u.ip4_u.daddr = peer->srx.transport.sin.sin_addr.s_addr;
+               fl.nl_u.ip4_u.tos = 0;
+               /* assume AFS.CM talking to AFS.FS */
+               fl.uli_u.ports.sport = htons(7001);
+               fl.uli_u.ports.dport = htons(7000);
+               break;
+       default:
+               BUG();
+       }
+
+       ret = ip_route_output_key(&rt, &fl);
+       if (ret < 0) {
+               kleave(" [route err %d]", ret);
+               return;
+       }
+
+       peer->if_mtu = dst_mtu(&rt->u.dst);
+       dst_release(&rt->u.dst);
+
+       kleave(" [if_mtu %u]", peer->if_mtu);
+}
+
+/*
  * allocate a new peer
  */
 static struct rxrpc_peer *rxrpc_alloc_peer(struct sockaddr_rxrpc *srx,
@@ -47,7 +89,8 @@ static struct rxrpc_peer *rxrpc_alloc_peer(struct sockaddr_rxrpc *srx,
                peer->debug_id = atomic_inc_return(&rxrpc_debug_id);
                memcpy(&peer->srx, srx, sizeof(*srx));
 
-               peer->mtu = peer->if_mtu = 65535;
+               rxrpc_assess_MTU_size(peer);
+               peer->mtu = peer->if_mtu;
 
                if (srx->transport.family == AF_INET) {
                        peer->hdrsize = sizeof(struct iphdr);
index 8699e70..bec600a 100644 (file)
@@ -894,9 +894,10 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
        s_idx = cb->args[0];
        s_q_idx = q_idx = cb->args[1];
        read_lock(&dev_base_lock);
-       for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
+       idx = 0;
+       for_each_netdev(dev) {
                if (idx < s_idx)
-                       continue;
+                       goto cont;
                if (idx > s_idx)
                        s_q_idx = 0;
                q_idx = 0;
@@ -910,6 +911,8 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
                                goto done;
                        q_idx++;
                }
+cont:
+               idx++;
        }
 
 done:
index db73ef9..df94e3c 100644 (file)
@@ -1103,6 +1103,13 @@ void sctp_assoc_update(struct sctp_association *asoc,
                        asoc->ssnmap = new->ssnmap;
                        new->ssnmap = NULL;
                }
+
+               if (!asoc->assoc_id) {
+                       /* get a new association id since we don't have one
+                        * yet.
+                        */
+                       sctp_assoc_set_id(asoc, GFP_ATOMIC);
+               }
        }
 }
 
@@ -1375,3 +1382,25 @@ out:
        sctp_read_unlock(&asoc->base.addr_lock);
        return found;
 }
+
+/* Set an association id for a given association */
+int sctp_assoc_set_id(struct sctp_association *asoc, gfp_t gfp)
+{
+       int assoc_id;
+       int error = 0;
+retry:
+       if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp)))
+               return -ENOMEM;
+
+       spin_lock_bh(&sctp_assocs_id_lock);
+       error = idr_get_new_above(&sctp_assocs_id, (void *)asoc,
+                                   1, &assoc_id);
+       spin_unlock_bh(&sctp_assocs_id_lock);
+       if (error == -EAGAIN)
+               goto retry;
+       else if (error)
+               return error;
+
+       asoc->assoc_id = (sctp_assoc_t) assoc_id;
+       return error;
+}
index ca527a2..84cd536 100644 (file)
@@ -992,45 +992,52 @@ static struct sctp_pf sctp_pf_inet6_specific = {
        .af            = &sctp_ipv6_specific,
 };
 
-/* Initialize IPv6 support and register with inet6 stack.  */
+/* Initialize IPv6 support and register with socket layer.  */
 int sctp_v6_init(void)
 {
-       int rc = proto_register(&sctpv6_prot, 1);
+       int rc;
 
+       /* Register the SCTP specific PF_INET6 functions. */
+       sctp_register_pf(&sctp_pf_inet6_specific, PF_INET6);
+
+       /* Register the SCTP specific AF_INET6 functions. */
+       sctp_register_af(&sctp_ipv6_specific);
+
+       rc = proto_register(&sctpv6_prot, 1);
        if (rc)
-               goto out;
-       /* Register inet6 protocol. */
-       rc = -EAGAIN;
-       if (inet6_add_protocol(&sctpv6_protocol, IPPROTO_SCTP) < 0)
-               goto out_unregister_sctp_proto;
+               return rc;
 
        /* Add SCTPv6(UDP and TCP style) to inetsw6 linked list. */
        inet6_register_protosw(&sctpv6_seqpacket_protosw);
        inet6_register_protosw(&sctpv6_stream_protosw);
 
-       /* Register the SCTP specific PF_INET6 functions. */
-       sctp_register_pf(&sctp_pf_inet6_specific, PF_INET6);
-
-       /* Register the SCTP specific AF_INET6 functions. */
-       sctp_register_af(&sctp_ipv6_specific);
+       return 0;
+}
 
+/* Register with inet6 layer. */
+int sctp_v6_add_protocol(void)
+{
        /* Register notifier for inet6 address additions/deletions. */
        register_inet6addr_notifier(&sctp_inet6addr_notifier);
-       rc = 0;
-out:
-       return rc;
-out_unregister_sctp_proto:
-       proto_unregister(&sctpv6_prot);
-       goto out;
+
+       if (inet6_add_protocol(&sctpv6_protocol, IPPROTO_SCTP) < 0)
+               return -EAGAIN;
+
+       return 0;
 }
 
 /* IPv6 specific exit support. */
 void sctp_v6_exit(void)
 {
-       list_del(&sctp_ipv6_specific.list);
-       inet6_del_protocol(&sctpv6_protocol, IPPROTO_SCTP);
        inet6_unregister_protosw(&sctpv6_seqpacket_protosw);
        inet6_unregister_protosw(&sctpv6_stream_protosw);
-       unregister_inet6addr_notifier(&sctp_inet6addr_notifier);
        proto_unregister(&sctpv6_prot);
+       list_del(&sctp_ipv6_specific.list);
+}
+
+/* Unregister with inet6 layer. */
+void sctp_v6_del_protocol(void)
+{
+       inet6_del_protocol(&sctpv6_protocol, IPPROTO_SCTP);
+       unregister_inet6addr_notifier(&sctp_inet6addr_notifier);
 }
index c361deb..34bab36 100644 (file)
@@ -170,7 +170,7 @@ static void sctp_get_local_addr_list(void)
        struct sctp_af *af;
 
        read_lock(&dev_base_lock);
-       for (dev = dev_base; dev; dev = dev->next) {
+       for_each_netdev(dev) {
                __list_for_each(pos, &sctp_address_families) {
                        af = list_entry(pos, struct sctp_af, list);
                        af->copy_addrlist(&sctp_local_addr_list, dev);
@@ -975,28 +975,14 @@ SCTP_STATIC __init int sctp_init(void)
        if (!sctp_sanity_check())
                goto out;
 
-       status = proto_register(&sctp_prot, 1);
-       if (status)
-               goto out;
-
-       /* Add SCTP to inet_protos hash table.  */
-       status = -EAGAIN;
-       if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0)
-               goto err_add_protocol;
-
-       /* Add SCTP(TCP and UDP style) to inetsw linked list.  */
-       inet_register_protosw(&sctp_seqpacket_protosw);
-       inet_register_protosw(&sctp_stream_protosw);
-
-       /* Allocate a cache pools. */
+       /* Allocate bind_bucket and chunk caches. */
        status = -ENOBUFS;
        sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket",
                                               sizeof(struct sctp_bind_bucket),
                                               0, SLAB_HWCACHE_ALIGN,
                                               NULL, NULL);
-
        if (!sctp_bucket_cachep)
-               goto err_bucket_cachep;
+               goto out;
 
        sctp_chunk_cachep = kmem_cache_create("sctp_chunk",
                                               sizeof(struct sctp_chunk),
@@ -1153,6 +1139,14 @@ SCTP_STATIC __init int sctp_init(void)
        INIT_LIST_HEAD(&sctp_address_families);
        sctp_register_af(&sctp_ipv4_specific);
 
+       status = proto_register(&sctp_prot, 1);
+       if (status)
+               goto err_proto_register;
+
+       /* Register SCTP(UDP and TCP style) with socket layer.  */
+       inet_register_protosw(&sctp_seqpacket_protosw);
+       inet_register_protosw(&sctp_stream_protosw);
+
        status = sctp_v6_init();
        if (status)
                goto err_v6_init;
@@ -1166,19 +1160,39 @@ SCTP_STATIC __init int sctp_init(void)
 
        /* Initialize the local address list. */
        INIT_LIST_HEAD(&sctp_local_addr_list);
-
        sctp_get_local_addr_list();
 
        /* Register notifier for inet address additions/deletions. */
        register_inetaddr_notifier(&sctp_inetaddr_notifier);
 
+       /* Register SCTP with inet layer.  */
+       if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0) {
+               status = -EAGAIN;
+               goto err_add_protocol;
+       }
+
+       /* Register SCTP with inet6 layer.  */
+       status = sctp_v6_add_protocol();
+       if (status)
+               goto err_v6_add_protocol;
+
        __unsafe(THIS_MODULE);
        status = 0;
 out:
        return status;
+err_v6_add_protocol:
+       inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
+       unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
+err_add_protocol:
+       sctp_free_local_addr_list();
+       sock_release(sctp_ctl_socket);
 err_ctl_sock_init:
        sctp_v6_exit();
 err_v6_init:
+       inet_unregister_protosw(&sctp_stream_protosw);
+       inet_unregister_protosw(&sctp_seqpacket_protosw);
+       proto_unregister(&sctp_prot);
+err_proto_register:
        sctp_sysctl_unregister();
        list_del(&sctp_ipv4_specific.list);
        free_pages((unsigned long)sctp_port_hashtable,
@@ -1192,19 +1206,13 @@ err_ehash_alloc:
                             sizeof(struct sctp_hashbucket)));
 err_ahash_alloc:
        sctp_dbg_objcnt_exit();
-err_init_proc:
        sctp_proc_exit();
+err_init_proc:
        cleanup_sctp_mibs();
 err_init_mibs:
        kmem_cache_destroy(sctp_chunk_cachep);
 err_chunk_cachep:
        kmem_cache_destroy(sctp_bucket_cachep);
-err_bucket_cachep:
-       inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
-       inet_unregister_protosw(&sctp_seqpacket_protosw);
-       inet_unregister_protosw(&sctp_stream_protosw);
-err_add_protocol:
-       proto_unregister(&sctp_prot);
        goto out;
 }
 
@@ -1215,8 +1223,9 @@ SCTP_STATIC __exit void sctp_exit(void)
         * up all the remaining associations and all that memory.
         */
 
-       /* Unregister notifier for inet address additions/deletions. */
-       unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
+       /* Unregister with inet6/inet layers. */
+       sctp_v6_del_protocol();
+       inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
 
        /* Free the local address list.  */
        sctp_free_local_addr_list();
@@ -1224,7 +1233,16 @@ SCTP_STATIC __exit void sctp_exit(void)
        /* Free the control endpoint.  */
        sock_release(sctp_ctl_socket);
 
+       /* Cleanup v6 initializations. */
        sctp_v6_exit();
+
+       /* Unregister with socket layer. */
+       inet_unregister_protosw(&sctp_stream_protosw);
+       inet_unregister_protosw(&sctp_seqpacket_protosw);
+
+       /* Unregister notifier for inet address additions/deletions. */
+       unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
+
        sctp_sysctl_unregister();
        list_del(&sctp_ipv4_specific.list);
 
@@ -1236,16 +1254,13 @@ SCTP_STATIC __exit void sctp_exit(void)
                   get_order(sctp_port_hashsize *
                             sizeof(struct sctp_bind_hashbucket)));
 
-       kmem_cache_destroy(sctp_chunk_cachep);
-       kmem_cache_destroy(sctp_bucket_cachep);
-
        sctp_dbg_objcnt_exit();
        sctp_proc_exit();
        cleanup_sctp_mibs();
 
-       inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
-       inet_unregister_protosw(&sctp_seqpacket_protosw);
-       inet_unregister_protosw(&sctp_stream_protosw);
+       kmem_cache_destroy(sctp_chunk_cachep);
+       kmem_cache_destroy(sctp_bucket_cachep);
+
        proto_unregister(&sctp_prot);
 }
 
index be783a3..8d18f57 100644 (file)
@@ -1939,7 +1939,6 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
         * association.
         */
        if (!asoc->temp) {
-               int assoc_id;
                int error;
 
                asoc->ssnmap = sctp_ssnmap_new(asoc->c.sinit_max_instreams,
@@ -1947,19 +1946,9 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
                if (!asoc->ssnmap)
                        goto clean_up;
 
-       retry:
-               if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp)))
+               error = sctp_assoc_set_id(asoc, gfp);
+               if (error)
                        goto clean_up;
-               spin_lock_bh(&sctp_assocs_id_lock);
-               error = idr_get_new_above(&sctp_assocs_id, (void *)asoc, 1,
-                                         &assoc_id);
-               spin_unlock_bh(&sctp_assocs_id_lock);
-               if (error == -EAGAIN)
-                       goto retry;
-               else if (error)
-                       goto clean_up;
-
-               asoc->assoc_id = (sctp_assoc_t) assoc_id;
        }
 
        /* ADDIP Section 4.1 ASCONF Chunk Procedures
index b37a7ad..d9fad4f 100644 (file)
@@ -862,6 +862,33 @@ static void sctp_cmd_set_sk_err(struct sctp_association *asoc, int error)
                sk->sk_err = error;
 }
 
+/* Helper function to generate an association change event */
+static void sctp_cmd_assoc_change(sctp_cmd_seq_t *commands,
+                                struct sctp_association *asoc,
+                                u8 state)
+{
+       struct sctp_ulpevent *ev;
+
+       ev = sctp_ulpevent_make_assoc_change(asoc, 0, state, 0,
+                                           asoc->c.sinit_num_ostreams,
+                                           asoc->c.sinit_max_instreams,
+                                           NULL, GFP_ATOMIC);
+       if (ev)
+               sctp_ulpq_tail_event(&asoc->ulpq, ev);
+}
+
+/* Helper function to generate an adaptation indication event */
+static void sctp_cmd_adaptation_ind(sctp_cmd_seq_t *commands,
+                                   struct sctp_association *asoc)
+{
+       struct sctp_ulpevent *ev;
+
+       ev = sctp_ulpevent_make_adaptation_indication(asoc, GFP_ATOMIC);
+
+       if (ev)
+               sctp_ulpq_tail_event(&asoc->ulpq, ev);
+}
+
 /* These three macros allow us to pull the debugging code out of the
  * main flow of sctp_do_sm() to keep attention focused on the real
  * functionality there.
@@ -1485,6 +1512,14 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                case SCTP_CMD_SET_SK_ERR:
                        sctp_cmd_set_sk_err(asoc, cmd->obj.error);
                        break;
+               case SCTP_CMD_ASSOC_CHANGE:
+                       sctp_cmd_assoc_change(commands, asoc,
+                                             cmd->obj.u8);
+                       break;
+               case SCTP_CMD_ADAPTATION_IND:
+                       sctp_cmd_adaptation_ind(commands, asoc);
+                       break;
+
                default:
                        printk(KERN_WARNING "Impossible command: %u, %p\n",
                               cmd->verb, cmd->obj.ptr);
index 9e28a5d..f02ce3d 100644 (file)
@@ -1656,7 +1656,6 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep,
                                        struct sctp_association *new_asoc)
 {
        sctp_init_chunk_t *peer_init;
-       struct sctp_ulpevent *ev;
        struct sctp_chunk *repl;
 
        /* new_asoc is a brand-new association, so these are not yet
@@ -1687,34 +1686,28 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep,
         * D) IMPLEMENTATION NOTE: An implementation may choose to
         * send the Communication Up notification to the SCTP user
         * upon reception of a valid COOKIE ECHO chunk.
+        *
+        * Sadly, this needs to be implemented as a side-effect, because
+        * we are not guaranteed to have set the association id of the real
+        * association and so these notifications need to be delayed until
+        * the association id is allocated.
         */
-       ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_COMM_UP, 0,
-                                            new_asoc->c.sinit_num_ostreams,
-                                            new_asoc->c.sinit_max_instreams,
-                                            NULL, GFP_ATOMIC);
-       if (!ev)
-               goto nomem_ev;
 
-       sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
+       sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_CHANGE, SCTP_U8(SCTP_COMM_UP));
 
        /* Sockets API Draft Section 5.3.1.6
         * When a peer sends a Adaptation Layer Indication parameter , SCTP
         * delivers this notification to inform the application that of the
         * peers requested adaptation layer.
+        *
+        * This also needs to be done as a side effect for the same reason as
+        * above.
         */
-       if (asoc->peer.adaptation_ind) {
-               ev = sctp_ulpevent_make_adaptation_indication(asoc, GFP_ATOMIC);
-               if (!ev)
-                       goto nomem_ev;
-
-               sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
-                               SCTP_ULPEVENT(ev));
-       }
+       if (asoc->peer.adaptation_ind)
+               sctp_add_cmd_sf(commands, SCTP_CMD_ADAPTATION_IND, SCTP_NULL());
 
        return SCTP_DISPOSITION_CONSUME;
 
-nomem_ev:
-       sctp_chunk_free(repl);
 nomem:
        return SCTP_DISPOSITION_NOMEM;
 }
index 2fc0a92..9f1a908 100644 (file)
@@ -972,6 +972,7 @@ static int __sctp_connect(struct sock* sk,
        int walk_size = 0;
        union sctp_addr *sa_addr;
        void *addr_buf;
+       unsigned short port;
 
        sp = sctp_sk(sk);
        ep = sp->ep;
@@ -992,6 +993,7 @@ static int __sctp_connect(struct sock* sk,
        while (walk_size < addrs_size) {
                sa_addr = (union sctp_addr *)addr_buf;
                af = sctp_get_af_specific(sa_addr->sa.sa_family);
+               port = ntohs(sa_addr->v4.sin_port);
 
                /* If the address family is not supported or if this address
                 * causes the address buffer to overflow return EINVAL.
@@ -1005,6 +1007,12 @@ static int __sctp_connect(struct sock* sk,
                if (err)
                        goto out_free;
 
+               /* Make sure the destination port is correctly set
+                * in all addresses.
+                */
+               if (asoc && asoc->peer.port && asoc->peer.port != port)
+                       goto out_free;
+
                memcpy(&to, sa_addr, af->sockaddr_len);
 
                /* Check if there already is a matching association on the
@@ -5012,7 +5020,8 @@ pp_found:
                struct hlist_node *node;
 
                SCTP_DEBUG_PRINTK("sctp_get_port() found a possible match\n");
-               if (pp->fastreuse && sk->sk_reuse)
+               if (pp->fastreuse && sk->sk_reuse &&
+                       sk->sk_state != SCTP_SS_LISTENING)
                        goto success;
 
                /* Run through the list of sockets bound to the port
@@ -5029,7 +5038,8 @@ pp_found:
                        struct sctp_endpoint *ep2;
                        ep2 = sctp_sk(sk2)->ep;
 
-                       if (reuse && sk2->sk_reuse)
+                       if (reuse && sk2->sk_reuse &&
+                           sk2->sk_state != SCTP_SS_LISTENING)
                                continue;
 
                        if (sctp_bind_addr_match(&ep2->base.bind_addr, addr,
@@ -5050,9 +5060,13 @@ pp_not_found:
         * if sk->sk_reuse is too (that is, if the caller requested
         * SO_REUSEADDR on this socket -sk-).
         */
-       if (hlist_empty(&pp->owner))
-               pp->fastreuse = sk->sk_reuse ? 1 : 0;
-       else if (pp->fastreuse && !sk->sk_reuse)
+       if (hlist_empty(&pp->owner)) {
+               if (sk->sk_reuse && sk->sk_state != SCTP_SS_LISTENING)
+                       pp->fastreuse = 1;
+               else
+                       pp->fastreuse = 0;
+       } else if (pp->fastreuse &&
+               (!sk->sk_reuse || sk->sk_state == SCTP_SS_LISTENING))
                pp->fastreuse = 0;
 
        /* We are set, so fill up all the data in the hash table
@@ -5060,8 +5074,8 @@ pp_not_found:
         * sockets FIXME: Blurry, NPI (ipg).
         */
 success:
-       inet_sk(sk)->num = snum;
        if (!sctp_sk(sk)->bind_hash) {
+               inet_sk(sk)->num = snum;
                sk_add_bind_node(sk, &pp->owner);
                sctp_sk(sk)->bind_hash = pp;
        }
@@ -5134,12 +5148,16 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog)
         * This is not currently spelled out in the SCTP sockets
         * extensions draft, but follows the practice as seen in TCP
         * sockets.
+        *
+        * Additionally, turn off fastreuse flag since we are not listening
         */
+       sk->sk_state = SCTP_SS_LISTENING;
        if (!ep->base.bind_addr.port) {
                if (sctp_autobind(sk))
                        return -EAGAIN;
-       }
-       sk->sk_state = SCTP_SS_LISTENING;
+       } else
+               sctp_sk(sk)->bind_hash->fastreuse = 0;
+
        sctp_hash_endpoint(ep);
        return 0;
 }
@@ -5177,11 +5195,13 @@ SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog)
         * extensions draft, but follows the practice as seen in TCP
         * sockets.
         */
+       sk->sk_state = SCTP_SS_LISTENING;
        if (!ep->base.bind_addr.port) {
                if (sctp_autobind(sk))
                        return -EAGAIN;
-       }
-       sk->sk_state = SCTP_SS_LISTENING;
+       } else
+               sctp_sk(sk)->bind_hash->fastreuse = 0;
+
        sk->sk_max_ack_backlog = backlog;
        sctp_hash_endpoint(ep);
        return 0;
index cdcab9c..8ebfc4d 100644 (file)
@@ -9,7 +9,7 @@ obj-$(CONFIG_SUNRPC_GSS) += auth_gss/
 sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \
            auth.o auth_null.o auth_unix.o \
            svc.o svcsock.o svcauth.o svcauth_unix.o \
-           pmap_clnt.o timer.o xdr.o \
+           rpcb_clnt.o timer.o xdr.o \
            sunrpc_syms.o cache.o rpc_pipe.o
 sunrpc-$(CONFIG_PROC_FS) += stats.o
 sunrpc-$(CONFIG_SYSCTL) += sysctl.o
index 104cbf4..d158635 100644 (file)
@@ -123,9 +123,6 @@ spkm3_make_token(struct spkm3_ctx *ctx,
 
        return  GSS_S_COMPLETE;
 out_err:
-       if (md5cksum.data)
-               kfree(md5cksum.data);
-
        token->data = NULL;
        token->len = 0;
        return GSS_S_FAILURE;
@@ -152,7 +149,7 @@ make_spkm3_checksum(s32 cksumtype, struct xdr_netobj *key, char *header,
 
        switch (cksumtype) {
                case CKSUMTYPE_HMAC_MD5:
-                       cksumname = "md5";
+                       cksumname = "hmac(md5)";
                        break;
                default:
                        dprintk("RPC:       spkm3_make_checksum:"
@@ -172,8 +169,12 @@ make_spkm3_checksum(s32 cksumtype, struct xdr_netobj *key, char *header,
        if (err)
                goto out;
 
+       err = crypto_hash_init(&desc);
+       if (err)
+               goto out;
+
        sg_set_buf(sg, header, hdrlen);
-       crypto_hash_update(&desc, sg, 1);
+       crypto_hash_update(&desc, sg, sg->length);
 
        xdr_process_buf(body, body_offset, body->len - body_offset,
                        spkm3_checksummer, &desc);
@@ -184,5 +185,3 @@ out:
 
        return err ? GSS_S_FAILURE : 0;
 }
-
-EXPORT_SYMBOL(make_spkm3_checksum);
index 396cdbe..d8fbee4 100644 (file)
@@ -36,8 +36,6 @@
 #include <linux/sunrpc/metrics.h>
 
 
-#define RPC_SLACK_SPACE                (1024)  /* total overkill */
-
 #ifdef RPC_DEBUG
 # define RPCDBG_FACILITY       RPCDBG_CALL
 #endif
@@ -747,21 +745,38 @@ call_reserveresult(struct rpc_task *task)
 static void
 call_allocate(struct rpc_task *task)
 {
+       unsigned int slack = task->tk_auth->au_cslack;
        struct rpc_rqst *req = task->tk_rqstp;
        struct rpc_xprt *xprt = task->tk_xprt;
-       unsigned int    bufsiz;
+       struct rpc_procinfo *proc = task->tk_msg.rpc_proc;
 
        dprint_status(task);
 
+       task->tk_status = 0;
        task->tk_action = call_bind;
+
        if (req->rq_buffer)
                return;
 
-       /* FIXME: compute buffer requirements more exactly using
-        * auth->au_wslack */
-       bufsiz = task->tk_msg.rpc_proc->p_bufsiz + RPC_SLACK_SPACE;
+       if (proc->p_proc != 0) {
+               BUG_ON(proc->p_arglen == 0);
+               if (proc->p_decode != NULL)
+                       BUG_ON(proc->p_replen == 0);
+       }
 
-       if (xprt->ops->buf_alloc(task, bufsiz << 1) != NULL)
+       /*
+        * Calculate the size (in quads) of the RPC call
+        * and reply headers, and convert both values
+        * to byte sizes.
+        */
+       req->rq_callsize = RPC_CALLHDRSIZE + (slack << 1) + proc->p_arglen;
+       req->rq_callsize <<= 2;
+       req->rq_rcvsize = RPC_REPHDRSIZE + slack + proc->p_replen;
+       req->rq_rcvsize <<= 2;
+
+       req->rq_buffer = xprt->ops->buf_alloc(task,
+                                       req->rq_callsize + req->rq_rcvsize);
+       if (req->rq_buffer != NULL)
                return;
 
        dprintk("RPC: %5u rpc_buffer allocation failed\n", task->tk_pid);
@@ -788,6 +803,17 @@ rpc_task_force_reencode(struct rpc_task *task)
        task->tk_rqstp->rq_snd_buf.len = 0;
 }
 
+static inline void
+rpc_xdr_buf_init(struct xdr_buf *buf, void *start, size_t len)
+{
+       buf->head[0].iov_base = start;
+       buf->head[0].iov_len = len;
+       buf->tail[0].iov_len = 0;
+       buf->page_len = 0;
+       buf->len = 0;
+       buf->buflen = len;
+}
+
 /*
  * 3.  Encode arguments of an RPC call
  */
@@ -795,28 +821,17 @@ static void
 call_encode(struct rpc_task *task)
 {
        struct rpc_rqst *req = task->tk_rqstp;
-       struct xdr_buf *sndbuf = &req->rq_snd_buf;
-       struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
-       unsigned int    bufsiz;
        kxdrproc_t      encode;
        __be32          *p;
 
        dprint_status(task);
 
-       /* Default buffer setup */
-       bufsiz = req->rq_bufsize >> 1;
-       sndbuf->head[0].iov_base = (void *)req->rq_buffer;
-       sndbuf->head[0].iov_len  = bufsiz;
-       sndbuf->tail[0].iov_len  = 0;
-       sndbuf->page_len         = 0;
-       sndbuf->len              = 0;
-       sndbuf->buflen           = bufsiz;
-       rcvbuf->head[0].iov_base = (void *)((char *)req->rq_buffer + bufsiz);
-       rcvbuf->head[0].iov_len  = bufsiz;
-       rcvbuf->tail[0].iov_len  = 0;
-       rcvbuf->page_len         = 0;
-       rcvbuf->len              = 0;
-       rcvbuf->buflen           = bufsiz;
+       rpc_xdr_buf_init(&req->rq_snd_buf,
+                        req->rq_buffer,
+                        req->rq_callsize);
+       rpc_xdr_buf_init(&req->rq_rcv_buf,
+                        (char *)req->rq_buffer + req->rq_callsize,
+                        req->rq_rcvsize);
 
        /* Encode header and provided arguments */
        encode = task->tk_msg.rpc_proc->p_encode;
@@ -887,9 +902,11 @@ call_bind_status(struct rpc_task *task)
                                task->tk_pid);
                break;
        case -EPROTONOSUPPORT:
-               dprintk("RPC: %5u remote rpcbind version 2 unavailable\n",
+               dprintk("RPC: %5u remote rpcbind version unavailable, retrying\n",
                                task->tk_pid);
-               break;
+               task->tk_status = 0;
+               task->tk_action = call_bind;
+               return;
        default:
                dprintk("RPC: %5u unrecognized rpcbind error (%d)\n",
                                task->tk_pid, -task->tk_status);
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
deleted file mode 100644 (file)
index d9f7653..0000000
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * linux/net/sunrpc/pmap_clnt.c
- *
- * In-kernel RPC portmapper client.
- *
- * Portmapper supports version 2 of the rpcbind protocol (RFC 1833).
- *
- * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
- */
-
-#include <linux/types.h>
-#include <linux/socket.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/uio.h>
-#include <linux/in.h>
-#include <linux/sunrpc/clnt.h>
-#include <linux/sunrpc/sched.h>
-
-#ifdef RPC_DEBUG
-# define RPCDBG_FACILITY       RPCDBG_PMAP
-#endif
-
-#define PMAP_SET               1
-#define PMAP_UNSET             2
-#define PMAP_GETPORT           3
-
-struct portmap_args {
-       u32                     pm_prog;
-       u32                     pm_vers;
-       u32                     pm_prot;
-       unsigned short          pm_port;
-       struct rpc_xprt *       pm_xprt;
-};
-
-static struct rpc_procinfo     pmap_procedures[];
-static struct rpc_clnt *       pmap_create(char *, struct sockaddr_in *, int, int);
-static void                    pmap_getport_done(struct rpc_task *, void *);
-static struct rpc_program      pmap_program;
-
-static void pmap_getport_prepare(struct rpc_task *task, void *calldata)
-{
-       struct portmap_args *map = calldata;
-       struct rpc_message msg = {
-               .rpc_proc       = &pmap_procedures[PMAP_GETPORT],
-               .rpc_argp       = map,
-               .rpc_resp       = &map->pm_port,
-       };
-
-       rpc_call_setup(task, &msg, 0);
-}
-
-static inline struct portmap_args *pmap_map_alloc(void)
-{
-       return kmalloc(sizeof(struct portmap_args), GFP_NOFS);
-}
-
-static inline void pmap_map_free(struct portmap_args *map)
-{
-       kfree(map);
-}
-
-static void pmap_map_release(void *data)
-{
-       struct portmap_args *map = data;
-
-       xprt_put(map->pm_xprt);
-       pmap_map_free(map);
-}
-
-static const struct rpc_call_ops pmap_getport_ops = {
-       .rpc_call_prepare       = pmap_getport_prepare,
-       .rpc_call_done          = pmap_getport_done,
-       .rpc_release            = pmap_map_release,
-};
-
-static inline void pmap_wake_portmap_waiters(struct rpc_xprt *xprt, int status)
-{
-       xprt_clear_binding(xprt);
-       rpc_wake_up_status(&xprt->binding, status);
-}
-
-/**
- * rpc_getport - obtain the port for a given RPC service on a given host
- * @task: task that is waiting for portmapper request
- *
- * This one can be called for an ongoing RPC request, and can be used in
- * an async (rpciod) context.
- */
-void rpc_getport(struct rpc_task *task)
-{
-       struct rpc_clnt *clnt = task->tk_client;
-       struct rpc_xprt *xprt = task->tk_xprt;
-       struct sockaddr_in addr;
-       struct portmap_args *map;
-       struct rpc_clnt *pmap_clnt;
-       struct rpc_task *child;
-       int status;
-
-       dprintk("RPC: %5u rpc_getport(%s, %u, %u, %d)\n",
-                       task->tk_pid, clnt->cl_server,
-                       clnt->cl_prog, clnt->cl_vers, xprt->prot);
-
-       /* Autobind on cloned rpc clients is discouraged */
-       BUG_ON(clnt->cl_parent != clnt);
-
-       status = -EACCES;               /* tell caller to check again */
-       if (xprt_test_and_set_binding(xprt))
-               goto bailout_nowake;
-
-       /* Put self on queue before sending rpcbind request, in case
-        * pmap_getport_done completes before we return from rpc_run_task */
-       rpc_sleep_on(&xprt->binding, task, NULL, NULL);
-
-       /* Someone else may have bound if we slept */
-       status = 0;
-       if (xprt_bound(xprt))
-               goto bailout_nofree;
-
-       status = -ENOMEM;
-       map = pmap_map_alloc();
-       if (!map)
-               goto bailout_nofree;
-       map->pm_prog = clnt->cl_prog;
-       map->pm_vers = clnt->cl_vers;
-       map->pm_prot = xprt->prot;
-       map->pm_port = 0;
-       map->pm_xprt = xprt_get(xprt);
-
-       rpc_peeraddr(clnt, (struct sockaddr *) &addr, sizeof(addr));
-       pmap_clnt = pmap_create(clnt->cl_server, &addr, map->pm_prot, 0);
-       status = PTR_ERR(pmap_clnt);
-       if (IS_ERR(pmap_clnt))
-               goto bailout;
-
-       status = -EIO;
-       child = rpc_run_task(pmap_clnt, RPC_TASK_ASYNC, &pmap_getport_ops, map);
-       if (IS_ERR(child))
-               goto bailout_nofree;
-       rpc_put_task(child);
-
-       task->tk_xprt->stat.bind_count++;
-       return;
-
-bailout:
-       pmap_map_free(map);
-       xprt_put(xprt);
-bailout_nofree:
-       pmap_wake_portmap_waiters(xprt, status);
-bailout_nowake:
-       task->tk_status = status;
-}
-
-#ifdef CONFIG_ROOT_NFS
-/**
- * rpc_getport_external - obtain the port for a given RPC service on a given host
- * @sin: address of remote peer
- * @prog: RPC program number to bind
- * @vers: RPC version number to bind
- * @prot: transport protocol to use to make this request
- *
- * This one is called from outside the RPC client in a synchronous task context.
- */
-int rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot)
-{
-       struct portmap_args map = {
-               .pm_prog        = prog,
-               .pm_vers        = vers,
-               .pm_prot        = prot,
-               .pm_port        = 0
-       };
-       struct rpc_message msg = {
-               .rpc_proc       = &pmap_procedures[PMAP_GETPORT],
-               .rpc_argp       = &map,
-               .rpc_resp       = &map.pm_port,
-       };
-       struct rpc_clnt *pmap_clnt;
-       char            hostname[32];
-       int             status;
-
-       dprintk("RPC:       rpc_getport_external(%u.%u.%u.%u, %u, %u, %d)\n",
-                       NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
-
-       sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr));
-       pmap_clnt = pmap_create(hostname, sin, prot, 0);
-       if (IS_ERR(pmap_clnt))
-               return PTR_ERR(pmap_clnt);
-
-       /* Setup the call info struct */
-       status = rpc_call_sync(pmap_clnt, &msg, 0);
-
-       if (status >= 0) {
-               if (map.pm_port != 0)
-                       return map.pm_port;
-               status = -EACCES;
-       }
-       return status;
-}
-#endif
-
-/*
- * Portmapper child task invokes this callback via tk_exit.
- */
-static void pmap_getport_done(struct rpc_task *child, void *data)
-{
-       struct portmap_args *map = data;
-       struct rpc_xprt *xprt = map->pm_xprt;
-       int status = child->tk_status;
-
-       if (status < 0) {
-               /* Portmapper not available */
-               xprt->ops->set_port(xprt, 0);
-       } else if (map->pm_port == 0) {
-               /* Requested RPC service wasn't registered */
-               xprt->ops->set_port(xprt, 0);
-               status = -EACCES;
-       } else {
-               /* Succeeded */
-               xprt->ops->set_port(xprt, map->pm_port);
-               xprt_set_bound(xprt);
-               status = 0;
-       }
-
-       dprintk("RPC: %5u pmap_getport_done(status %d, port %u)\n",
-                       child->tk_pid, status, map->pm_port);
-
-       pmap_wake_portmap_waiters(xprt, status);
-}
-
-/**
- * rpc_register - set or unset a port registration with the local portmapper
- * @prog: RPC program number to bind
- * @vers: RPC version number to bind
- * @prot: transport protocol to use to make this request
- * @port: port value to register
- * @okay: result code
- *
- * port == 0 means unregister, port != 0 means register.
- */
-int rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
-{
-       struct sockaddr_in      sin = {
-               .sin_family     = AF_INET,
-               .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
-       };
-       struct portmap_args     map = {
-               .pm_prog        = prog,
-               .pm_vers        = vers,
-               .pm_prot        = prot,
-               .pm_port        = port,
-       };
-       struct rpc_message msg = {
-               .rpc_proc       = &pmap_procedures[port ? PMAP_SET : PMAP_UNSET],
-               .rpc_argp       = &map,
-               .rpc_resp       = okay,
-       };
-       struct rpc_clnt         *pmap_clnt;
-       int error = 0;
-
-       dprintk("RPC:       registering (%u, %u, %d, %u) with portmapper.\n",
-                       prog, vers, prot, port);
-
-       pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP, 1);
-       if (IS_ERR(pmap_clnt)) {
-               error = PTR_ERR(pmap_clnt);
-               dprintk("RPC:       couldn't create pmap client. Error = %d\n",
-                               error);
-               return error;
-       }
-
-       error = rpc_call_sync(pmap_clnt, &msg, 0);
-
-       if (error < 0) {
-               printk(KERN_WARNING
-                       "RPC: failed to contact portmap (errno %d).\n",
-                       error);
-       }
-       dprintk("RPC:       registration status %d/%d\n", error, *okay);
-
-       /* Client deleted automatically because cl_oneshot == 1 */
-       return error;
-}
-
-static struct rpc_clnt *pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto, int privileged)
-{
-       struct rpc_create_args args = {
-               .protocol       = proto,
-               .address        = (struct sockaddr *)srvaddr,
-               .addrsize       = sizeof(*srvaddr),
-               .servername     = hostname,
-               .program        = &pmap_program,
-               .version        = RPC_PMAP_VERSION,
-               .authflavor     = RPC_AUTH_UNIX,
-               .flags          = (RPC_CLNT_CREATE_ONESHOT |
-                                  RPC_CLNT_CREATE_NOPING),
-       };
-
-       srvaddr->sin_port = htons(RPC_PMAP_PORT);
-       if (!privileged)
-               args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
-       return rpc_create(&args);
-}
-
-/*
- * XDR encode/decode functions for PMAP
- */
-static int xdr_encode_mapping(struct rpc_rqst *req, __be32 *p, struct portmap_args *map)
-{
-       dprintk("RPC:       xdr_encode_mapping(%u, %u, %u, %u)\n",
-                       map->pm_prog, map->pm_vers,
-                       map->pm_prot, map->pm_port);
-       *p++ = htonl(map->pm_prog);
-       *p++ = htonl(map->pm_vers);
-       *p++ = htonl(map->pm_prot);
-       *p++ = htonl(map->pm_port);
-
-       req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
-       return 0;
-}
-
-static int xdr_decode_port(struct rpc_rqst *req, __be32 *p, unsigned short *portp)
-{
-       *portp = (unsigned short) ntohl(*p++);
-       return 0;
-}
-
-static int xdr_decode_bool(struct rpc_rqst *req, __be32 *p, unsigned int *boolp)
-{
-       *boolp = (unsigned int) ntohl(*p++);
-       return 0;
-}
-
-static struct rpc_procinfo     pmap_procedures[] = {
-[PMAP_SET] = {
-         .p_proc               = PMAP_SET,
-         .p_encode             = (kxdrproc_t) xdr_encode_mapping,
-         .p_decode             = (kxdrproc_t) xdr_decode_bool,
-         .p_bufsiz             = 4,
-         .p_count              = 1,
-         .p_statidx            = PMAP_SET,
-         .p_name               = "SET",
-       },
-[PMAP_UNSET] = {
-         .p_proc               = PMAP_UNSET,
-         .p_encode             = (kxdrproc_t) xdr_encode_mapping,
-         .p_decode             = (kxdrproc_t) xdr_decode_bool,
-         .p_bufsiz             = 4,
-         .p_count              = 1,
-         .p_statidx            = PMAP_UNSET,
-         .p_name               = "UNSET",
-       },
-[PMAP_GETPORT] = {
-         .p_proc               = PMAP_GETPORT,
-         .p_encode             = (kxdrproc_t) xdr_encode_mapping,
-         .p_decode             = (kxdrproc_t) xdr_decode_port,
-         .p_bufsiz             = 4,
-         .p_count              = 1,
-         .p_statidx            = PMAP_GETPORT,
-         .p_name               = "GETPORT",
-       },
-};
-
-static struct rpc_version      pmap_version2 = {
-       .number         = 2,
-       .nrprocs        = 4,
-       .procs          = pmap_procedures
-};
-
-static struct rpc_version *    pmap_version[] = {
-       NULL,
-       NULL,
-       &pmap_version2
-};
-
-static struct rpc_stat         pmap_stats;
-
-static struct rpc_program      pmap_program = {
-       .name           = "portmap",
-       .number         = RPC_PMAP_PROGRAM,
-       .nrvers         = ARRAY_SIZE(pmap_version),
-       .version        = pmap_version,
-       .stats          = &pmap_stats,
-};
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
new file mode 100644 (file)
index 0000000..6c7aa8a
--- /dev/null
@@ -0,0 +1,625 @@
+/*
+ * In-kernel rpcbind client supporting versions 2, 3, and 4 of the rpcbind
+ * protocol
+ *
+ * Based on RFC 1833: "Binding Protocols for ONC RPC Version 2" and
+ * RFC 3530: "Network File System (NFS) version 4 Protocol"
+ *
+ * Original: Gilles Quillard, Bull Open Source, 2005 <gilles.quillard@bull.net>
+ * Updated: Chuck Lever, Oracle Corporation, 2007 <chuck.lever@oracle.com>
+ *
+ * Descended from net/sunrpc/pmap_clnt.c,
+ *  Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include <linux/types.h>
+#include <linux/socket.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+
+#include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/sched.h>
+
+#ifdef RPC_DEBUG
+# define RPCDBG_FACILITY       RPCDBG_BIND
+#endif
+
+#define RPCBIND_PROGRAM                (100000u)
+#define RPCBIND_PORT           (111u)
+
+enum {
+       RPCBPROC_NULL,
+       RPCBPROC_SET,
+       RPCBPROC_UNSET,
+       RPCBPROC_GETPORT,
+       RPCBPROC_GETADDR = 3,           /* alias for GETPORT */
+       RPCBPROC_DUMP,
+       RPCBPROC_CALLIT,
+       RPCBPROC_BCAST = 5,             /* alias for CALLIT */
+       RPCBPROC_GETTIME,
+       RPCBPROC_UADDR2TADDR,
+       RPCBPROC_TADDR2UADDR,
+       RPCBPROC_GETVERSADDR,
+       RPCBPROC_INDIRECT,
+       RPCBPROC_GETADDRLIST,
+       RPCBPROC_GETSTAT,
+};
+
+#define RPCB_HIGHPROC_2                RPCBPROC_CALLIT
+#define RPCB_HIGHPROC_3                RPCBPROC_TADDR2UADDR
+#define RPCB_HIGHPROC_4                RPCBPROC_GETSTAT
+
+/*
+ * r_addr
+ *
+ * Quoting RFC 3530, section 2.2:
+ *
+ * For TCP over IPv4 and for UDP over IPv4, the format of r_addr is the
+ * US-ASCII string:
+ *
+ *     h1.h2.h3.h4.p1.p2
+ *
+ * The prefix, "h1.h2.h3.h4", is the standard textual form for
+ * representing an IPv4 address, which is always four octets long.
+ * Assuming big-endian ordering, h1, h2, h3, and h4, are respectively,
+ * the first through fourth octets each converted to ASCII-decimal.
+ * Assuming big-endian ordering, p1 and p2 are, respectively, the first
+ * and second octets each converted to ASCII-decimal.  For example, if a
+ * host, in big-endian order, has an address of 0x0A010307 and there is
+ * a service listening on, in big endian order, port 0x020F (decimal
+ * 527), then the complete universal address is "10.1.3.7.2.15".
+ *
+ * ...
+ *
+ * For TCP over IPv6 and for UDP over IPv6, the format of r_addr is the
+ * US-ASCII string:
+ *
+ *     x1:x2:x3:x4:x5:x6:x7:x8.p1.p2
+ *
+ * The suffix "p1.p2" is the service port, and is computed the same way
+ * as with universal addresses for TCP and UDP over IPv4.  The prefix,
+ * "x1:x2:x3:x4:x5:x6:x7:x8", is the standard textual form for
+ * representing an IPv6 address as defined in Section 2.2 of [RFC2373].
+ * Additionally, the two alternative forms specified in Section 2.2 of
+ * [RFC2373] are also acceptable.
+ *
+ * XXX: Currently this implementation does not explicitly convert the
+ *      stored address to US-ASCII on non-ASCII systems.
+ */
+#define RPCB_MAXADDRLEN                (128u)
+
+/*
+ * r_netid
+ *
+ * Quoting RFC 3530, section 2.2:
+ *
+ * For TCP over IPv4 the value of r_netid is the string "tcp".  For UDP
+ * over IPv4 the value of r_netid is the string "udp".
+ *
+ * ...
+ *
+ * For TCP over IPv6 the value of r_netid is the string "tcp6".  For UDP
+ * over IPv6 the value of r_netid is the string "udp6".
+ */
+#define RPCB_NETID_UDP "\165\144\160"          /* "udp" */
+#define RPCB_NETID_TCP "\164\143\160"          /* "tcp" */
+#define RPCB_NETID_UDP6        "\165\144\160\066"      /* "udp6" */
+#define RPCB_NETID_TCP6        "\164\143\160\066"      /* "tcp6" */
+
+#define RPCB_MAXNETIDLEN       (4u)
+
+/*
+ * r_owner
+ *
+ * The "owner" is allowed to unset a service in the rpcbind database.
+ * We always use the following (arbitrary) fixed string.
+ */
+#define RPCB_OWNER_STRING      "rpcb"
+#define RPCB_MAXOWNERLEN       sizeof(RPCB_OWNER_STRING)
+
+static void                    rpcb_getport_done(struct rpc_task *, void *);
+extern struct rpc_program      rpcb_program;
+
+struct rpcbind_args {
+       struct rpc_xprt *       r_xprt;
+
+       u32                     r_prog;
+       u32                     r_vers;
+       u32                     r_prot;
+       unsigned short          r_port;
+       char *                  r_netid;
+       char                    r_addr[RPCB_MAXADDRLEN];
+       char *                  r_owner;
+};
+
+static struct rpc_procinfo rpcb_procedures2[];
+static struct rpc_procinfo rpcb_procedures3[];
+
+static struct rpcb_info {
+       int                     rpc_vers;
+       struct rpc_procinfo *   rpc_proc;
+} rpcb_next_version[];
+
+static void rpcb_getport_prepare(struct rpc_task *task, void *calldata)
+{
+       struct rpcbind_args *map = calldata;
+       struct rpc_xprt *xprt = map->r_xprt;
+       struct rpc_message msg = {
+               .rpc_proc       = rpcb_next_version[xprt->bind_index].rpc_proc,
+               .rpc_argp       = map,
+               .rpc_resp       = &map->r_port,
+       };
+
+       rpc_call_setup(task, &msg, 0);
+}
+
+static void rpcb_map_release(void *data)
+{
+       struct rpcbind_args *map = data;
+
+       xprt_put(map->r_xprt);
+       kfree(map);
+}
+
+static const struct rpc_call_ops rpcb_getport_ops = {
+       .rpc_call_prepare       = rpcb_getport_prepare,
+       .rpc_call_done          = rpcb_getport_done,
+       .rpc_release            = rpcb_map_release,
+};
+
+static void rpcb_wake_rpcbind_waiters(struct rpc_xprt *xprt, int status)
+{
+       xprt_clear_binding(xprt);
+       rpc_wake_up_status(&xprt->binding, status);
+}
+
+static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
+                                       int proto, int version, int privileged)
+{
+       struct rpc_create_args args = {
+               .protocol       = proto,
+               .address        = srvaddr,
+               .addrsize       = sizeof(struct sockaddr_in),
+               .servername     = hostname,
+               .program        = &rpcb_program,
+               .version        = version,
+               .authflavor     = RPC_AUTH_UNIX,
+               .flags          = (RPC_CLNT_CREATE_ONESHOT |
+                                  RPC_CLNT_CREATE_NOPING),
+       };
+
+       ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT);
+       if (!privileged)
+               args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
+       return rpc_create(&args);
+}
+
+/**
+ * rpcb_register - set or unset a port registration with the local rpcbind svc
+ * @prog: RPC program number to bind
+ * @vers: RPC version number to bind
+ * @prot: transport protocol to use to make this request
+ * @port: port value to register
+ * @okay: result code
+ *
+ * port == 0 means unregister, port != 0 means register.
+ *
+ * This routine supports only rpcbind version 2.
+ */
+int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
+{
+       struct sockaddr_in sin = {
+               .sin_family             = AF_INET,
+               .sin_addr.s_addr        = htonl(INADDR_LOOPBACK),
+       };
+       struct rpcbind_args map = {
+               .r_prog         = prog,
+               .r_vers         = vers,
+               .r_prot         = prot,
+               .r_port         = port,
+       };
+       struct rpc_message msg = {
+               .rpc_proc       = &rpcb_procedures2[port ?
+                                       RPCBPROC_SET : RPCBPROC_UNSET],
+               .rpc_argp       = &map,
+               .rpc_resp       = okay,
+       };
+       struct rpc_clnt *rpcb_clnt;
+       int error = 0;
+
+       dprintk("RPC:       %sregistering (%u, %u, %d, %u) with local "
+                       "rpcbind\n", (port ? "" : "un"),
+                       prog, vers, prot, port);
+
+       rpcb_clnt = rpcb_create("localhost", (struct sockaddr *) &sin,
+                                       IPPROTO_UDP, 2, 1);
+       if (IS_ERR(rpcb_clnt))
+               return PTR_ERR(rpcb_clnt);
+
+       error = rpc_call_sync(rpcb_clnt, &msg, 0);
+
+       if (error < 0)
+               printk(KERN_WARNING "RPC: failed to contact local rpcbind "
+                               "server (errno %d).\n", -error);
+       dprintk("RPC:       registration status %d/%d\n", error, *okay);
+
+       return error;
+}
+
+#ifdef CONFIG_ROOT_NFS
+/**
+ * rpcb_getport_external - obtain the port for an RPC service on a given host
+ * @sin: address of remote peer
+ * @prog: RPC program number to bind
+ * @vers: RPC version number to bind
+ * @prot: transport protocol to use to make this request
+ *
+ * Called from outside the RPC client in a synchronous task context.
+ *
+ * For now, this supports only version 2 queries, but is used only by
+ * mount_clnt for NFS_ROOT.
+ */
+int rpcb_getport_external(struct sockaddr_in *sin, __u32 prog,
+                               __u32 vers, int prot)
+{
+       struct rpcbind_args map = {
+               .r_prog         = prog,
+               .r_vers         = vers,
+               .r_prot         = prot,
+               .r_port         = 0,
+       };
+       struct rpc_message msg = {
+               .rpc_proc       = &rpcb_procedures2[RPCBPROC_GETPORT],
+               .rpc_argp       = &map,
+               .rpc_resp       = &map.r_port,
+       };
+       struct rpc_clnt *rpcb_clnt;
+       char hostname[40];
+       int status;
+
+       dprintk("RPC:       rpcb_getport_external(%u.%u.%u.%u, %u, %u, %d)\n",
+                       NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
+
+       sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr));
+       rpcb_clnt = rpcb_create(hostname, (struct sockaddr *)sin, prot, 2, 0);
+       if (IS_ERR(rpcb_clnt))
+               return PTR_ERR(rpcb_clnt);
+
+       status = rpc_call_sync(rpcb_clnt, &msg, 0);
+
+       if (status >= 0) {
+               if (map.r_port != 0)
+                       return map.r_port;
+               status = -EACCES;
+       }
+       return status;
+}
+#endif
+
+/**
+ * rpcb_getport - obtain the port for a given RPC service on a given host
+ * @task: task that is waiting for portmapper request
+ *
+ * This one can be called for an ongoing RPC request, and can be used in
+ * an async (rpciod) context.
+ */
+void rpcb_getport(struct rpc_task *task)
+{
+       struct rpc_clnt *clnt = task->tk_client;
+       int bind_version;
+       struct rpc_xprt *xprt = task->tk_xprt;
+       struct rpc_clnt *rpcb_clnt;
+       static struct rpcbind_args *map;
+       struct rpc_task *child;
+       struct sockaddr addr;
+       int status;
+
+       dprintk("RPC: %5u rpcb_getport(%s, %u, %u, %d)\n",
+                       task->tk_pid, clnt->cl_server,
+                       clnt->cl_prog, clnt->cl_vers, xprt->prot);
+
+       /* Autobind on cloned rpc clients is discouraged */
+       BUG_ON(clnt->cl_parent != clnt);
+
+       if (xprt_test_and_set_binding(xprt)) {
+               status = -EACCES;               /* tell caller to check again */
+               dprintk("RPC: %5u rpcb_getport waiting for another binder\n",
+                               task->tk_pid);
+               goto bailout_nowake;
+       }
+
+       /* Put self on queue before sending rpcbind request, in case
+        * rpcb_getport_done completes before we return from rpc_run_task */
+       rpc_sleep_on(&xprt->binding, task, NULL, NULL);
+
+       /* Someone else may have bound if we slept */
+       if (xprt_bound(xprt)) {
+               status = 0;
+               dprintk("RPC: %5u rpcb_getport already bound\n", task->tk_pid);
+               goto bailout_nofree;
+       }
+
+       if (rpcb_next_version[xprt->bind_index].rpc_proc == NULL) {
+               xprt->bind_index = 0;
+               status = -EACCES;       /* tell caller to try again later */
+               dprintk("RPC: %5u rpcb_getport no more getport versions "
+                               "available\n", task->tk_pid);
+               goto bailout_nofree;
+       }
+       bind_version = rpcb_next_version[xprt->bind_index].rpc_vers;
+
+       dprintk("RPC: %5u rpcb_getport trying rpcbind version %u\n",
+                       task->tk_pid, bind_version);
+
+       map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC);
+       if (!map) {
+               status = -ENOMEM;
+               dprintk("RPC: %5u rpcb_getport no memory available\n",
+                               task->tk_pid);
+               goto bailout_nofree;
+       }
+       map->r_prog = clnt->cl_prog;
+       map->r_vers = clnt->cl_vers;
+       map->r_prot = xprt->prot;
+       map->r_port = 0;
+       map->r_xprt = xprt_get(xprt);
+       map->r_netid = (xprt->prot == IPPROTO_TCP) ? RPCB_NETID_TCP :
+                                                  RPCB_NETID_UDP;
+       memcpy(&map->r_addr, rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR),
+                       sizeof(map->r_addr));
+       map->r_owner = RPCB_OWNER_STRING;       /* ignored for GETADDR */
+
+       rpc_peeraddr(clnt, (void *)&addr, sizeof(addr));
+       rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, bind_version, 0);
+       if (IS_ERR(rpcb_clnt)) {
+               status = PTR_ERR(rpcb_clnt);
+               dprintk("RPC: %5u rpcb_getport rpcb_create failed, error %ld\n",
+                               task->tk_pid, PTR_ERR(rpcb_clnt));
+               goto bailout;
+       }
+
+       child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map);
+       if (IS_ERR(child)) {
+               status = -EIO;
+               dprintk("RPC: %5u rpcb_getport rpc_run_task failed\n",
+                               task->tk_pid);
+               goto bailout_nofree;
+       }
+       rpc_put_task(child);
+
+       task->tk_xprt->stat.bind_count++;
+       return;
+
+bailout:
+       kfree(map);
+       xprt_put(xprt);
+bailout_nofree:
+       rpcb_wake_rpcbind_waiters(xprt, status);
+bailout_nowake:
+       task->tk_status = status;
+}
+
+/*
+ * Rpcbind child task calls this callback via tk_exit.
+ */
+static void rpcb_getport_done(struct rpc_task *child, void *data)
+{
+       struct rpcbind_args *map = data;
+       struct rpc_xprt *xprt = map->r_xprt;
+       int status = child->tk_status;
+
+       /* rpcbind server doesn't support this rpcbind protocol version */
+       if (status == -EPROTONOSUPPORT)
+               xprt->bind_index++;
+
+       if (status < 0) {
+               /* rpcbind server not available on remote host? */
+               xprt->ops->set_port(xprt, 0);
+       } else if (map->r_port == 0) {
+               /* Requested RPC service wasn't registered on remote host */
+               xprt->ops->set_port(xprt, 0);
+               status = -EACCES;
+       } else {
+               /* Succeeded */
+               xprt->ops->set_port(xprt, map->r_port);
+               xprt_set_bound(xprt);
+               status = 0;
+       }
+
+       dprintk("RPC: %5u rpcb_getport_done(status %d, port %u)\n",
+                       child->tk_pid, status, map->r_port);
+
+       rpcb_wake_rpcbind_waiters(xprt, status);
+}
+
+static int rpcb_encode_mapping(struct rpc_rqst *req, __be32 *p,
+                              struct rpcbind_args *rpcb)
+{
+       dprintk("RPC:       rpcb_encode_mapping(%u, %u, %d, %u)\n",
+                       rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port);
+       *p++ = htonl(rpcb->r_prog);
+       *p++ = htonl(rpcb->r_vers);
+       *p++ = htonl(rpcb->r_prot);
+       *p++ = htonl(rpcb->r_port);
+
+       req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+       return 0;
+}
+
+static int rpcb_decode_getport(struct rpc_rqst *req, __be32 *p,
+                              unsigned short *portp)
+{
+       *portp = (unsigned short) ntohl(*p++);
+       dprintk("RPC:      rpcb_decode_getport result %u\n",
+                       *portp);
+       return 0;
+}
+
+static int rpcb_decode_set(struct rpc_rqst *req, __be32 *p,
+                          unsigned int *boolp)
+{
+       *boolp = (unsigned int) ntohl(*p++);
+       dprintk("RPC:      rpcb_decode_set result %u\n",
+                       *boolp);
+       return 0;
+}
+
+static int rpcb_encode_getaddr(struct rpc_rqst *req, __be32 *p,
+                              struct rpcbind_args *rpcb)
+{
+       dprintk("RPC:       rpcb_encode_getaddr(%u, %u, %s)\n",
+                       rpcb->r_prog, rpcb->r_vers, rpcb->r_addr);
+       *p++ = htonl(rpcb->r_prog);
+       *p++ = htonl(rpcb->r_vers);
+
+       p = xdr_encode_string(p, rpcb->r_netid);
+       p = xdr_encode_string(p, rpcb->r_addr);
+       p = xdr_encode_string(p, rpcb->r_owner);
+
+       req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+
+       return 0;
+}
+
+static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p,
+                              unsigned short *portp)
+{
+       char *addr;
+       int addr_len, c, i, f, first, val;
+
+       *portp = 0;
+       addr_len = (unsigned int) ntohl(*p++);
+       if (addr_len > RPCB_MAXADDRLEN)                 /* sanity */
+               return -EINVAL;
+
+       dprintk("RPC:       rpcb_decode_getaddr returned string: '%s'\n",
+                       (char *) p);
+
+       addr = (char *)p;
+       val = 0;
+       first = 1;
+       f = 1;
+       for (i = addr_len - 1; i > 0; i--) {
+               c = addr[i];
+               if (c >= '0' && c <= '9') {
+                       val += (c - '0') * f;
+                       f *= 10;
+               } else if (c == '.') {
+                       if (first) {
+                               *portp = val;
+                               val = first = 0;
+                               f = 1;
+                       } else {
+                               *portp |= (val << 8);
+                               break;
+                       }
+               }
+       }
+
+       dprintk("RPC:       rpcb_decode_getaddr port=%u\n", *portp);
+       return 0;
+}
+
+#define RPCB_program_sz                (1u)
+#define RPCB_version_sz                (1u)
+#define RPCB_protocol_sz       (1u)
+#define RPCB_port_sz           (1u)
+#define RPCB_boolean_sz                (1u)
+
+#define RPCB_netid_sz          (1+XDR_QUADLEN(RPCB_MAXNETIDLEN))
+#define RPCB_addr_sz           (1+XDR_QUADLEN(RPCB_MAXADDRLEN))
+#define RPCB_ownerstring_sz    (1+XDR_QUADLEN(RPCB_MAXOWNERLEN))
+
+#define RPCB_mappingargs_sz    RPCB_program_sz+RPCB_version_sz+        \
+                               RPCB_protocol_sz+RPCB_port_sz
+#define RPCB_getaddrargs_sz    RPCB_program_sz+RPCB_version_sz+        \
+                               RPCB_netid_sz+RPCB_addr_sz+             \
+                               RPCB_ownerstring_sz
+
+#define RPCB_setres_sz         RPCB_boolean_sz
+#define RPCB_getportres_sz     RPCB_port_sz
+
+/*
+ * Note that RFC 1833 does not put any size restrictions on the
+ * address string returned by the remote rpcbind database.
+ */
+#define RPCB_getaddrres_sz     RPCB_addr_sz
+
+#define PROC(proc, argtype, restype)                                   \
+       [RPCBPROC_##proc] = {                                           \
+               .p_proc         = RPCBPROC_##proc,                      \
+               .p_encode       = (kxdrproc_t) rpcb_encode_##argtype,   \
+               .p_decode       = (kxdrproc_t) rpcb_decode_##restype,   \
+               .p_arglen       = RPCB_##argtype##args_sz,              \
+               .p_replen       = RPCB_##restype##res_sz,               \
+               .p_statidx      = RPCBPROC_##proc,                      \
+               .p_timer        = 0,                                    \
+               .p_name         = #proc,                                \
+       }
+
+/*
+ * Not all rpcbind procedures described in RFC 1833 are implemented
+ * since the Linux kernel RPC code requires only these.
+ */
+static struct rpc_procinfo rpcb_procedures2[] = {
+       PROC(SET,               mapping,        set),
+       PROC(UNSET,             mapping,        set),
+       PROC(GETADDR,           mapping,        getport),
+};
+
+static struct rpc_procinfo rpcb_procedures3[] = {
+       PROC(SET,               mapping,        set),
+       PROC(UNSET,             mapping,        set),
+       PROC(GETADDR,           getaddr,        getaddr),
+};
+
+static struct rpc_procinfo rpcb_procedures4[] = {
+       PROC(SET,               mapping,        set),
+       PROC(UNSET,             mapping,        set),
+       PROC(GETVERSADDR,       getaddr,        getaddr),
+};
+
+static struct rpcb_info rpcb_next_version[] = {
+#ifdef CONFIG_SUNRPC_BIND34
+       { 4, &rpcb_procedures4[RPCBPROC_GETVERSADDR] },
+       { 3, &rpcb_procedures3[RPCBPROC_GETADDR] },
+#endif
+       { 2, &rpcb_procedures2[RPCBPROC_GETPORT] },
+       { 0, NULL },
+};
+
+static struct rpc_version rpcb_version2 = {
+       .number         = 2,
+       .nrprocs        = RPCB_HIGHPROC_2,
+       .procs          = rpcb_procedures2
+};
+
+static struct rpc_version rpcb_version3 = {
+       .number         = 3,
+       .nrprocs        = RPCB_HIGHPROC_3,
+       .procs          = rpcb_procedures3
+};
+
+static struct rpc_version rpcb_version4 = {
+       .number         = 4,
+       .nrprocs        = RPCB_HIGHPROC_4,
+       .procs          = rpcb_procedures4
+};
+
+static struct rpc_version *rpcb_version[] = {
+       NULL,
+       NULL,
+       &rpcb_version2,
+       &rpcb_version3,
+       &rpcb_version4
+};
+
+static struct rpc_stat rpcb_stats;
+
+struct rpc_program rpcb_program = {
+       .name           = "rpcbind",
+       .number         = RPCBIND_PROGRAM,
+       .nrvers         = ARRAY_SIZE(rpcb_version),
+       .version        = rpcb_version,
+       .stats          = &rpcb_stats,
+};
index 6d87320..4a53e94 100644 (file)
@@ -741,50 +741,53 @@ static void rpc_async_schedule(struct work_struct *work)
  * @task: RPC task that will use this buffer
  * @size: requested byte size
  *
- * We try to ensure that some NFS reads and writes can always proceed
- * by using a mempool when allocating 'small' buffers.
+ * To prevent rpciod from hanging, this allocator never sleeps,
+ * returning NULL if the request cannot be serviced immediately.
+ * The caller can arrange to sleep in a way that is safe for rpciod.
+ *
+ * Most requests are 'small' (under 2KiB) and can be serviced from a
+ * mempool, ensuring that NFS reads and writes can always proceed,
+ * and that there is good locality of reference for these buffers.
+ *
  * In order to avoid memory starvation triggering more writebacks of
- * NFS requests, we use GFP_NOFS rather than GFP_KERNEL.
+ * NFS requests, we avoid using GFP_KERNEL.
  */
-void * rpc_malloc(struct rpc_task *task, size_t size)
+void *rpc_malloc(struct rpc_task *task, size_t size)
 {
-       struct rpc_rqst *req = task->tk_rqstp;
-       gfp_t   gfp;
+       size_t *buf;
+       gfp_t gfp = RPC_IS_SWAPPER(task) ? GFP_ATOMIC : GFP_NOWAIT;
 
-       if (task->tk_flags & RPC_TASK_SWAPPER)
-               gfp = GFP_ATOMIC;
+       size += sizeof(size_t);
+       if (size <= RPC_BUFFER_MAXSIZE)
+               buf = mempool_alloc(rpc_buffer_mempool, gfp);
        else
-               gfp = GFP_NOFS;
-
-       if (size > RPC_BUFFER_MAXSIZE) {
-               req->rq_buffer = kmalloc(size, gfp);
-               if (req->rq_buffer)
-                       req->rq_bufsize = size;
-       } else {
-               req->rq_buffer = mempool_alloc(rpc_buffer_mempool, gfp);
-               if (req->rq_buffer)
-                       req->rq_bufsize = RPC_BUFFER_MAXSIZE;
-       }
-       return req->rq_buffer;
+               buf = kmalloc(size, gfp);
+       *buf = size;
+       dprintk("RPC: %5u allocated buffer of size %u at %p\n",
+                       task->tk_pid, size, buf);
+       return (void *) ++buf;
 }
 
 /**
  * rpc_free - free buffer allocated via rpc_malloc
- * @task: RPC task with a buffer to be freed
+ * @buffer: buffer to free
  *
  */
-void rpc_free(struct rpc_task *task)
+void rpc_free(void *buffer)
 {
-       struct rpc_rqst *req = task->tk_rqstp;
+       size_t size, *buf = (size_t *) buffer;
 
-       if (req->rq_buffer) {
-               if (req->rq_bufsize == RPC_BUFFER_MAXSIZE)
-                       mempool_free(req->rq_buffer, rpc_buffer_mempool);
-               else
-                       kfree(req->rq_buffer);
-               req->rq_buffer = NULL;
-               req->rq_bufsize = 0;
-       }
+       if (!buffer)
+               return;
+       size = *buf;
+       buf--;
+
+       dprintk("RPC:       freeing buffer of size %u at %p\n",
+                       size, buf);
+       if (size <= RPC_BUFFER_MAXSIZE)
+               mempool_free(buf, rpc_buffer_mempool);
+       else
+               kfree(buf);
 }
 
 /*
index b4db53f..b7503c1 100644 (file)
@@ -757,7 +757,7 @@ svc_register(struct svc_serv *serv, int proto, unsigned short port)
                        if (progp->pg_vers[i]->vs_hidden)
                                continue;
 
-                       error = rpc_register(progp->pg_prog, i, proto, port, &dummy);
+                       error = rpcb_register(progp->pg_prog, i, proto, port, &dummy);
                        if (error < 0)
                                break;
                        if (port && !dummy) {
index 456a145..5b05b73 100644 (file)
@@ -823,7 +823,6 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
        req->rq_task    = task;
        req->rq_xprt    = xprt;
        req->rq_buffer  = NULL;
-       req->rq_bufsize = 0;
        req->rq_xid     = xprt_alloc_xid(xprt);
        req->rq_release_snd_buf = NULL;
        xprt_reset_majortimeo(req);
@@ -855,7 +854,7 @@ void xprt_release(struct rpc_task *task)
                mod_timer(&xprt->timer,
                                xprt->last_used + xprt->idle_timeout);
        spin_unlock_bh(&xprt->transport_lock);
-       xprt->ops->buf_free(task);
+       xprt->ops->buf_free(req->rq_buffer);
        task->tk_rqstp = NULL;
        if (req->rq_release_snd_buf)
                req->rq_release_snd_buf(req);
@@ -928,6 +927,7 @@ struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t si
        xprt->timer.data = (unsigned long) xprt;
        xprt->last_used = jiffies;
        xprt->cwnd = RPC_INITCWND;
+       xprt->bind_index = 0;
 
        rpc_init_wait_queue(&xprt->binding, "xprt_binding");
        rpc_init_wait_queue(&xprt->pending, "xprt_pending");
index a5a3202..cc33c58 100644 (file)
@@ -1476,7 +1476,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
        .set_buffer_size        = xs_udp_set_buffer_size,
        .reserve_xprt           = xprt_reserve_xprt_cong,
        .release_xprt           = xprt_release_xprt_cong,
-       .rpcbind                = rpc_getport,
+       .rpcbind                = rpcb_getport,
        .set_port               = xs_set_port,
        .connect                = xs_connect,
        .buf_alloc              = rpc_malloc,
@@ -1493,7 +1493,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
 static struct rpc_xprt_ops xs_tcp_ops = {
        .reserve_xprt           = xprt_reserve_xprt,
        .release_xprt           = xs_tcp_release_xprt,
-       .rpcbind                = rpc_getport,
+       .rpcbind                = rpcb_getport,
        .set_port               = xs_set_port,
        .connect                = xs_connect,
        .buf_alloc              = rpc_malloc,
index 67bb29b..0ee6ded 100644 (file)
@@ -120,16 +120,18 @@ static int recv_msg(struct sk_buff *buf, struct net_device *dev,
 
 static int enable_bearer(struct tipc_bearer *tb_ptr)
 {
-       struct net_device *dev = dev_base;
+       struct net_device *dev, *pdev;
        struct eth_bearer *eb_ptr = &eth_bearers[0];
        struct eth_bearer *stop = &eth_bearers[MAX_ETH_BEARERS];
        char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1;
 
        /* Find device with specified name */
-
-       while (dev && dev->name && strncmp(dev->name, driver_name, IFNAMSIZ)) {
-               dev = dev->next;
-       }
+       dev = NULL;
+       for_each_netdev(pdev)
+               if (!strncmp(dev->name, driver_name, IFNAMSIZ)) {
+                       dev = pdev;
+                       break;
+               }
        if (!dev)
                return -ENODEV;
 
index 263e34e..95271e8 100644 (file)
@@ -579,7 +579,7 @@ static inline int xfrm_byidx_should_resize(int total)
        return 0;
 }
 
-void xfrm_spd_getinfo(struct xfrm_spdinfo *si)
+void xfrm_spd_getinfo(struct xfrmk_spdinfo *si)
 {
        read_lock_bh(&xfrm_policy_lock);
        si->incnt = xfrm_policy_count[XFRM_POLICY_IN];
index f3a61eb..9955ff4 100644 (file)
@@ -421,7 +421,7 @@ restart:
 }
 EXPORT_SYMBOL(xfrm_state_flush);
 
-void xfrm_sad_getinfo(struct xfrm_sadinfo *si)
+void xfrm_sad_getinfo(struct xfrmk_sadinfo *si)
 {
        spin_lock_bh(&xfrm_state_lock);
        si->sadcnt = xfrm_state_num;
index 4210d91..b14c7e5 100644 (file)
@@ -674,7 +674,9 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,
 
 static int build_spdinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags)
 {
-       struct xfrm_spdinfo si;
+       struct xfrmk_spdinfo si;
+       struct xfrmu_spdinfo spc;
+       struct xfrmu_spdhinfo sph;
        struct nlmsghdr *nlh;
        u32 *f;
 
@@ -685,23 +687,17 @@ static int build_spdinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags)
        f = nlmsg_data(nlh);
        *f = flags;
        xfrm_spd_getinfo(&si);
-
-       if (flags & XFRM_SPD_HMASK)
-               NLA_PUT_U32(skb, XFRMA_SPDHMASK, si.spdhcnt);
-       if (flags & XFRM_SPD_HMAX)
-               NLA_PUT_U32(skb, XFRMA_SPDHMAX, si.spdhmcnt);
-       if (flags & XFRM_SPD_ICNT)
-               NLA_PUT_U32(skb, XFRMA_SPDICNT, si.incnt);
-       if (flags & XFRM_SPD_OCNT)
-               NLA_PUT_U32(skb, XFRMA_SPDOCNT, si.outcnt);
-       if (flags & XFRM_SPD_FCNT)
-               NLA_PUT_U32(skb, XFRMA_SPDFCNT, si.fwdcnt);
-       if (flags & XFRM_SPD_ISCNT)
-               NLA_PUT_U32(skb, XFRMA_SPDISCNT, si.inscnt);
-       if (flags & XFRM_SPD_OSCNT)
-               NLA_PUT_U32(skb, XFRMA_SPDOSCNT, si.inscnt);
-       if (flags & XFRM_SPD_FSCNT)
-               NLA_PUT_U32(skb, XFRMA_SPDFSCNT, si.inscnt);
+       spc.incnt = si.incnt;
+       spc.outcnt = si.outcnt;
+       spc.fwdcnt = si.fwdcnt;
+       spc.inscnt = si.inscnt;
+       spc.outscnt = si.outscnt;
+       spc.fwdscnt = si.fwdscnt;
+       sph.spdhcnt = si.spdhcnt;
+       sph.spdhmcnt = si.spdhmcnt;
+
+       NLA_PUT(skb, XFRMA_SPD_INFO, sizeof(spc), &spc);
+       NLA_PUT(skb, XFRMA_SPD_HINFO, sizeof(sph), &sph);
 
        return nlmsg_end(skb, nlh);
 
@@ -719,23 +715,8 @@ static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
        u32 seq = nlh->nlmsg_seq;
        int len = NLMSG_LENGTH(sizeof(u32));
 
-
-       if (*flags & XFRM_SPD_HMASK)
-               len += RTA_SPACE(sizeof(u32));
-       if (*flags & XFRM_SPD_HMAX)
-               len += RTA_SPACE(sizeof(u32));
-       if (*flags & XFRM_SPD_ICNT)
-               len += RTA_SPACE(sizeof(u32));
-       if (*flags & XFRM_SPD_OCNT)
-               len += RTA_SPACE(sizeof(u32));
-       if (*flags & XFRM_SPD_FCNT)
-               len += RTA_SPACE(sizeof(u32));
-       if (*flags & XFRM_SPD_ISCNT)
-               len += RTA_SPACE(sizeof(u32));
-       if (*flags & XFRM_SPD_OSCNT)
-               len += RTA_SPACE(sizeof(u32));
-       if (*flags & XFRM_SPD_FSCNT)
-               len += RTA_SPACE(sizeof(u32));
+       len += RTA_SPACE(sizeof(struct xfrmu_spdinfo));
+       len += RTA_SPACE(sizeof(struct xfrmu_spdhinfo));
 
        r_skb = alloc_skb(len, GFP_ATOMIC);
        if (r_skb == NULL)
@@ -749,7 +730,8 @@ static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
 
 static int build_sadinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags)
 {
-       struct xfrm_sadinfo si;
+       struct xfrmk_sadinfo si;
+       struct xfrmu_sadhinfo sh;
        struct nlmsghdr *nlh;
        u32 *f;
 
@@ -761,12 +743,11 @@ static int build_sadinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags)
        *f = flags;
        xfrm_sad_getinfo(&si);
 
-       if (flags & XFRM_SAD_HMASK)
-               NLA_PUT_U32(skb, XFRMA_SADHMASK, si.sadhcnt);
-       if (flags & XFRM_SAD_HMAX)
-               NLA_PUT_U32(skb, XFRMA_SADHMAX, si.sadhmcnt);
-       if (flags & XFRM_SAD_CNT)
-               NLA_PUT_U32(skb, XFRMA_SADCNT, si.sadcnt);
+       sh.sadhmcnt = si.sadhmcnt;
+       sh.sadhcnt = si.sadhcnt;
+
+       NLA_PUT_U32(skb, XFRMA_SAD_CNT, si.sadcnt);
+       NLA_PUT(skb, XFRMA_SAD_HINFO, sizeof(sh), &sh);
 
        return nlmsg_end(skb, nlh);
 
@@ -784,12 +765,8 @@ static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
        u32 seq = nlh->nlmsg_seq;
        int len = NLMSG_LENGTH(sizeof(u32));
 
-       if (*flags & XFRM_SAD_HMASK)
-               len += RTA_SPACE(sizeof(u32));
-       if (*flags & XFRM_SAD_HMAX)
-               len += RTA_SPACE(sizeof(u32));
-       if (*flags & XFRM_SAD_CNT)
-               len += RTA_SPACE(sizeof(u32));
+       len += RTA_SPACE(sizeof(struct xfrmu_sadhinfo));
+       len += RTA_SPACE(sizeof(u32));
 
        r_skb = alloc_skb(len, GFP_ATOMIC);
 
index d7ecf89..307211a 100644 (file)
@@ -321,7 +321,7 @@ static int __init securityfs_init(void)
 {
        int retval;
 
-       kset_set_kset_s(&security_subsys, kernel_subsys);
+       kobj_set_kset_s(&security_subsys, kernel_subsys);
        retval = subsystem_register(&security_subsys);
        if (retval)
                return retval;
index 4a431e3..f2fe357 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/ctype.h>
-#include <linux/pci.h>
 #include <linux/pm.h>
 
 #include <sound/core.h>
index a339f0c..23018a7 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/poll.h>
-#include <linux/pci.h>
 #include <linux/bitops.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
index dccae3a..9d12b37 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _TAS_IOCTL_H_
 #define _TAS_IOCTL_H_
 
-#include <linux/i2c.h>
 #include <linux/soundcard.h>
 
 
index dcd8d6d..a9c23b2 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/smp_lock.h>
 #include <linux/module.h>
 #include <linux/mm.h>
+#include <linux/device.h>
 
 /*
  * This ought to be moved into include/asm/dma.h
index b913a1f..9c3a9c8 100644 (file)
@@ -62,7 +62,6 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/moduleparam.h>
 #include <sound/core.h>
@@ -71,6 +70,7 @@
 #include <sound/ac97_codec.h>
 #include <sound/info.h>
 #include <sound/tlv.h>
+#include <asm/io.h>
 
 #include "ca0106.h"
 
index 75ca421..ae80f51 100644 (file)
@@ -64,7 +64,6 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/moduleparam.h>
 #include <sound/core.h>
@@ -73,6 +72,7 @@
 #include <sound/ac97_codec.h>
 #include <sound/info.h>
 #include <sound/asoundef.h>
+#include <asm/io.h>
 
 #include "ca0106.h"
 
index 89c4027..336e77e 100644 (file)
@@ -23,7 +23,6 @@
 #include <sound/driver.h>
 #include <asm/io.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
 #include <linux/pm.h>
 #include <linux/init.h>
 #include <linux/slab.h>
index 343f51d..57e357d 100644 (file)
@@ -24,7 +24,6 @@
 #include <sound/driver.h>
 #include <asm/io.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
 #include <linux/pm.h>
 #include <linux/init.h>
 #include <linux/slab.h>
index 1589d2f..1e5ff0c 100644 (file)
@@ -23,7 +23,6 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/pci.h>
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
index 17df4d0..e313e68 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/pci.h>
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
index 7333f27..831469d 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/pci.h>
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
index ed5e45e..6fcda9b 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/pci.h>
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
index 4c839b0..2b11ac8 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/pci.h>
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"